Human readable export location core implementation
Export locations are usually too difficult to memo rize.Currently, there is no way to determine the export location before the share is created, so users wait until the share creation request gets completed, and then they check the export locations to mount the share. The generated export locations are often not human readable and it is hard to memorize and control them. Implements: bp/human-readable-export-locations Change-Id: I72ac7e24ddd4330d76cafd5e7f78bac2b0174883
This commit is contained in:
parent
f4c77bfe71
commit
ea1ac5f448
@ -196,6 +196,20 @@ Share type common capability extra-specs that are visible to end users:
|
|||||||
this extra-spec, the share type is assumed to be serviceable in all
|
this extra-spec, the share type is assumed to be serviceable in all
|
||||||
availability zones known to the Shared File Systems service.
|
availability zones known to the Shared File Systems service.
|
||||||
|
|
||||||
|
* **mount_point_name_support** whether a custom export location could
|
||||||
|
be specified during share creation. To enable users to specify a custom
|
||||||
|
mount point for their shares, administrators must set this
|
||||||
|
extra-specification in the share type to True. They must also provide
|
||||||
|
an extra-spec named ``provisioning:mount_point_prefix``. The service will
|
||||||
|
use this prefix in conjunction with the mount point name provided by end
|
||||||
|
users during share creation. When ``provisioning:mount_point_prefix`` is not
|
||||||
|
set on a share type, but ``mount_point_name_support`` is enabled, the
|
||||||
|
share's export location will be prefixed with the ``project_id``.
|
||||||
|
However, shares created with a ``project_id`` prefix are not eligible
|
||||||
|
for transfer. For these shares to be transferred to a different project,
|
||||||
|
the admin will need to manually unmount them from the current project
|
||||||
|
and mount them to the target project.
|
||||||
|
|
||||||
Share type common capability extra-specs that are not visible to end users:
|
Share type common capability extra-specs that are not visible to end users:
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -274,3 +288,7 @@ Share type common capability extra-specs that are not visible to end users:
|
|||||||
the share type can not be greater than the specified value. This capability
|
the share type can not be greater than the specified value. This capability
|
||||||
is ignored for regular users and the "provisioning:max_share_size" is the
|
is ignored for regular users and the "provisioning:max_share_size" is the
|
||||||
only effective limit.
|
only effective limit.
|
||||||
|
|
||||||
|
* **provisioning:mount_point_prefix** can set prefix for human readable
|
||||||
|
mount_point_name, the value must be a string containing ASCII alphabets
|
||||||
|
and optionally, the underscore character.
|
||||||
|
@ -261,77 +261,77 @@ Mapping of share drivers and common capabilities
|
|||||||
|
|
||||||
More information: :ref:`capabilities_and_extra_specs`
|
More information: :ref:`capabilities_and_extra_specs`
|
||||||
|
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Driver name | DHSS=True | DHSS=False | dedupe | compression | thin_provisioning | thick_provisioning | qos | create share from snapshot | revert to snapshot | mountable snapshot | ipv4_support | ipv6_support | multiple subnets per AZ |
|
| Driver name | DHSS=True | DHSS=False | dedupe | compression | thin_provisioning | thick_provisioning | qos | create share from snapshot | revert to snapshot | mountable snapshot | ipv4_support | ipv6_support | multiple subnets per AZ | mount point name support |
|
||||||
+========================================+===========+============+========+=============+===================+====================+=====+============================+====================+====================+==============+==============+=========================+
|
+========================================+===========+============+========+=============+===================+====================+=====+============================+====================+====================+==============+==============+=========================+==========================+
|
||||||
| ZFSonLinux | \- | M | M | M | M | \- | \- | M | \- | \- | P | \- | \- |
|
| ZFSonLinux | \- | M | M | M | M | \- | \- | M | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Container | N | \- | \- | \- | \- | N | \- | \- | \- | \- | P | \- | Y |
|
| Container | N | \- | \- | \- | \- | N | \- | \- | \- | \- | P | \- | Y | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Generic (Cinder as back-end) | J | K | \- | \- | \- | L | \- | J | \- | \- | P | \- | \- |
|
| Generic (Cinder as back-end) | J | K | \- | \- | \- | L | \- | J | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| NetApp Clustered Data ONTAP | J | K | M | M | M | L | P | J | O | \- | P | Q | \- |
|
| NetApp Clustered Data ONTAP | J | K | M | M | M | L | P | J | O | \- | P | Q | \- | Y |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Dell EMC PowerMax | O | \- | \- | \- | \- | \- | \- | O | \- | \- | P | R | \- |
|
| Dell EMC PowerMax | O | \- | \- | \- | \- | \- | \- | O | \- | \- | P | R | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| EMC VNX | J | \- | \- | \- | \- | L | \- | J | \- | \- | P | Q | \- |
|
| EMC VNX | J | \- | \- | \- | \- | L | \- | J | \- | \- | P | Q | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| EMC Unity | N | T | \- | \- | N | \- | \- | N | S | \- | P | Q | \- |
|
| EMC Unity | N | T | \- | \- | N | \- | \- | N | S | \- | P | Q | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| EMC Isilon | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | \- |
|
| EMC Isilon | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Dell EMC PowerStore | \- | B | \- | \- | B | \- | \- | B | B | \- | B | \- | \- |
|
| Dell EMC PowerStore | \- | B | \- | \- | B | \- | \- | B | B | \- | B | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Dell EMC PowerFlex | \- | B | \- | \- | B | \- | \- | \- | \- | \- | B | \- | \- |
|
| Dell EMC PowerFlex | \- | B | \- | \- | B | \- | \- | \- | \- | \- | B | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| GlusterFS | \- | J | \- | \- | \- | L | \- | volume layout (L) | \- | \- | P | \- | \- |
|
| GlusterFS | \- | J | \- | \- | \- | L | \- | volume layout (L) | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| GlusterFS-Native | \- | J | \- | \- | \- | L | \- | L | \- | \- | P | \- | \- |
|
| GlusterFS-Native | \- | J | \- | \- | \- | L | \- | L | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| HDFS | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | \- |
|
| HDFS | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Hitachi HNAS | \- | L | N | \- | L | \- | \- | L | O | O | P | \- | \- |
|
| Hitachi HNAS | \- | L | N | \- | L | \- | \- | L | O | O | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Hitachi HSP | \- | N | \- | \- | N | \- | \- | \- | \- | \- | P | \- | \- |
|
| Hitachi HSP | \- | N | \- | \- | N | \- | \- | \- | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| HPE 3PAR | L | K | L | \- | L | L | \- | K | \- | \- | P | \- | \- |
|
| HPE 3PAR | L | K | L | \- | L | L | \- | K | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Huawei | M | K | L | L | L | L | M | M | \- | \- | P | \- | \- |
|
| Huawei | M | K | L | L | L | L | M | M | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| INFINIDAT | \- | Q | \- | \- | Q | Q | \- | Q | Q | Q | Q | \- | \- |
|
| INFINIDAT | \- | Q | \- | \- | Q | Q | \- | Q | Q | Q | Q | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Infortrend | \- | T | \- | \- | \- | \- | \- | \- | \- | \- | T | \- | \- |
|
| Infortrend | \- | T | \- | \- | \- | \- | \- | \- | \- | \- | T | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| LVM | \- | M | \- | \- | \- | M | \- | K | O | O | P | P | \- |
|
| LVM | \- | M | \- | \- | \- | M | \- | K | O | O | P | P | \- | Y |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Macrosan | \- | Z | \- | \- | \- | Z | \- | \- | \- | \- | Z | \- | \- |
|
| Macrosan | \- | Z | \- | \- | \- | Z | \- | \- | \- | \- | Z | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Quobyte | \- | K | \- | \- | \- | L | \- | M | \- | \- | P | \- | \- |
|
| Quobyte | \- | K | \- | \- | \- | L | \- | M | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Windows SMB | L | L | \- | \- | \- | L | \- | \- | \- | \- | P | \- | \- |
|
| Windows SMB | L | L | \- | \- | \- | L | \- | \- | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| IBM GPFS | \- | K | \- | \- | \- | L | \- | L | \- | \- | P | \- | \- |
|
| IBM GPFS | \- | K | \- | \- | \- | L | \- | L | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Oracle ZFSSA | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | \- |
|
| Oracle ZFSSA | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| CephFS | \- | M | \- | \- | \- | M | \- | \- | \- | \- | P | \- | \- |
|
| CephFS | \- | M | \- | \- | \- | M | \- | \- | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Tegile | \- | M | M | M | M | \- | \- | M | \- | \- | P | \- | \- |
|
| Tegile | \- | M | M | M | M | \- | \- | M | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| NexentaStor4 | \- | N | N | N | N | N | \- | N | \- | \- | P | \- | \- |
|
| NexentaStor4 | \- | N | N | N | N | N | \- | N | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| NexentaStor5 | \- | N | \- | N | N | N | \- | N | T | \- | P | \- | \- |
|
| NexentaStor5 | \- | N | \- | N | N | N | \- | N | T | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| MapRFS | \- | N | \- | \- | \- | N | \- | O | \- | \- | P | \- | \- |
|
| MapRFS | \- | N | \- | \- | \- | N | \- | O | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| QNAP | \- | O | Q | Q | O | Q | \- | O | \- | \- | P | \- | \- |
|
| QNAP | \- | O | Q | Q | O | Q | \- | O | \- | \- | P | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| INSPUR AS13000 | \- | R | \- | \- | R | \- | \- | R | \- | \- | R | \- | \- |
|
| INSPUR AS13000 | \- | R | \- | \- | R | \- | \- | R | \- | \- | R | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| INSPUR InStorage | \- | T | \- | \- | \- | T | \- | \- | \- | \- | T | \- | \- |
|
| INSPUR InStorage | \- | T | \- | \- | \- | T | \- | \- | \- | \- | T | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
| Pure Storage FlashBlade | \- | X | \- | \- | X | \- | \- | \- | X | \- | X | \- | \- |
|
| Pure Storage FlashBlade | \- | X | \- | \- | X | \- | \- | \- | X | \- | X | \- | \- | \- |
|
||||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -201,13 +201,14 @@ REST_API_VERSION_HISTORY = """
|
|||||||
* 2.81 - Added API methods, endpoint /resource-locks.
|
* 2.81 - Added API methods, endpoint /resource-locks.
|
||||||
* 2.82 - Added lock and restriction to share access rules.
|
* 2.82 - Added lock and restriction to share access rules.
|
||||||
* 2.83 - Added 'disabled_reason' field to services.
|
* 2.83 - Added 'disabled_reason' field to services.
|
||||||
|
* 2.84 - Added mount_point_name to shares.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# The minimum and maximum versions of the API supported
|
# The minimum and maximum versions of the API supported
|
||||||
# The default api version request is defined to be the
|
# The default api version request is defined to be the
|
||||||
# minimum version of the API supported.
|
# minimum version of the API supported.
|
||||||
_MIN_API_VERSION = "2.0"
|
_MIN_API_VERSION = "2.0"
|
||||||
_MAX_API_VERSION = "2.83"
|
_MAX_API_VERSION = "2.84"
|
||||||
DEFAULT_API_VERSION = _MIN_API_VERSION
|
DEFAULT_API_VERSION = _MIN_API_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
@ -450,3 +450,7 @@ user documentation.
|
|||||||
The ``disabled_reason`` field was added to the service to mark the reason why
|
The ``disabled_reason`` field was added to the service to mark the reason why
|
||||||
the user disabled the service. ``disabled`` field will be replaced by
|
the user disabled the service. ``disabled`` field will be replaced by
|
||||||
``status`` field.
|
``status`` field.
|
||||||
|
|
||||||
|
2.84
|
||||||
|
----
|
||||||
|
Added optional ``mount_point_name`` field to share.
|
||||||
|
@ -25,6 +25,7 @@ import webob
|
|||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
from manila.api import common
|
from manila.api import common
|
||||||
|
from manila.api.openstack import api_version_request as api_version
|
||||||
from manila.api.openstack import wsgi
|
from manila.api.openstack import wsgi
|
||||||
from manila.api.views import share_accesses as share_access_views
|
from manila.api.views import share_accesses as share_access_views
|
||||||
from manila.api.views import shares as share_views
|
from manila.api.views import shares as share_views
|
||||||
@ -445,6 +446,9 @@ class ShareMixin(object):
|
|||||||
|
|
||||||
kwargs['scheduler_hints'] = scheduler_hints
|
kwargs['scheduler_hints'] = scheduler_hints
|
||||||
|
|
||||||
|
if req.api_version_request >= api_version.APIVersionRequest("2.84"):
|
||||||
|
kwargs['mount_point_name'] = share.pop('mount_point_name', None)
|
||||||
|
|
||||||
new_share = self.share_api.create(context,
|
new_share = self.share_api.create(context,
|
||||||
share_proto,
|
share_proto,
|
||||||
size,
|
size,
|
||||||
|
@ -300,10 +300,12 @@ class ExtraSpecs(object):
|
|||||||
CREATE_SHARE_FROM_SNAPSHOT_SUPPORT = "create_share_from_snapshot_support"
|
CREATE_SHARE_FROM_SNAPSHOT_SUPPORT = "create_share_from_snapshot_support"
|
||||||
REVERT_TO_SNAPSHOT_SUPPORT = "revert_to_snapshot_support"
|
REVERT_TO_SNAPSHOT_SUPPORT = "revert_to_snapshot_support"
|
||||||
MOUNT_SNAPSHOT_SUPPORT = "mount_snapshot_support"
|
MOUNT_SNAPSHOT_SUPPORT = "mount_snapshot_support"
|
||||||
|
MOUNT_POINT_NAME_SUPPORT = "mount_point_name_support"
|
||||||
AVAILABILITY_ZONES = "availability_zones"
|
AVAILABILITY_ZONES = "availability_zones"
|
||||||
PROVISIONING_MAX_SHARE_SIZE = "provisioning:max_share_size"
|
PROVISIONING_MAX_SHARE_SIZE = "provisioning:max_share_size"
|
||||||
PROVISIONING_MIN_SHARE_SIZE = "provisioning:min_share_size"
|
PROVISIONING_MIN_SHARE_SIZE = "provisioning:min_share_size"
|
||||||
PROVISIONING_MAX_SHARE_EXTEND_SIZE = "provisioning:max_share_extend_size"
|
PROVISIONING_MAX_SHARE_EXTEND_SIZE = "provisioning:max_share_extend_size"
|
||||||
|
PROVISIONING_MOUNT_POINT_PREFIX = "provisioning:mount_point_prefix"
|
||||||
|
|
||||||
# Extra specs containers
|
# Extra specs containers
|
||||||
REQUIRED = (
|
REQUIRED = (
|
||||||
@ -316,10 +318,12 @@ class ExtraSpecs(object):
|
|||||||
REVERT_TO_SNAPSHOT_SUPPORT,
|
REVERT_TO_SNAPSHOT_SUPPORT,
|
||||||
REPLICATION_TYPE_SPEC,
|
REPLICATION_TYPE_SPEC,
|
||||||
MOUNT_SNAPSHOT_SUPPORT,
|
MOUNT_SNAPSHOT_SUPPORT,
|
||||||
|
MOUNT_POINT_NAME_SUPPORT,
|
||||||
AVAILABILITY_ZONES,
|
AVAILABILITY_ZONES,
|
||||||
PROVISIONING_MAX_SHARE_SIZE,
|
PROVISIONING_MAX_SHARE_SIZE,
|
||||||
PROVISIONING_MIN_SHARE_SIZE,
|
PROVISIONING_MIN_SHARE_SIZE,
|
||||||
PROVISIONING_MAX_SHARE_EXTEND_SIZE
|
PROVISIONING_MAX_SHARE_EXTEND_SIZE,
|
||||||
|
PROVISIONING_MOUNT_POINT_PREFIX,
|
||||||
)
|
)
|
||||||
|
|
||||||
# NOTE(cknight): Some extra specs are necessary parts of the Manila API and
|
# NOTE(cknight): Some extra specs are necessary parts of the Manila API and
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
"""add mount_point_name to share_instances
|
||||||
|
|
||||||
|
Revision ID: 6e32091979e0
|
||||||
|
Revises: 99d328f0a3d2
|
||||||
|
Create Date: 2024-01-26 22:08:22.412974
|
||||||
|
"""
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '6e32091979e0'
|
||||||
|
down_revision = '99d328f0a3d2'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
from oslo_log import log
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
share_instances_table_name = 'share_instances'
|
||||||
|
column_name = "mount_point_name"
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
try:
|
||||||
|
op.add_column(share_instances_table_name, sa.Column(column_name,
|
||||||
|
sa.String(255),
|
||||||
|
nullable=True))
|
||||||
|
except Exception:
|
||||||
|
LOG.error("Column mount_point_name not created!")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
try:
|
||||||
|
op.drop_column(share_instances_table_name, column_name)
|
||||||
|
except Exception:
|
||||||
|
LOG.error("Column mount_point_name not dropped!")
|
||||||
|
raise
|
@ -1619,6 +1619,7 @@ def _extract_share_instance_values(values):
|
|||||||
'status', 'host', 'scheduled_at', 'launched_at', 'terminated_at',
|
'status', 'host', 'scheduled_at', 'launched_at', 'terminated_at',
|
||||||
'share_server_id', 'share_network_id', 'availability_zone_id',
|
'share_server_id', 'share_network_id', 'availability_zone_id',
|
||||||
'replica_state', 'share_type_id', 'share_type', 'access_rules_status',
|
'replica_state', 'share_type_id', 'share_type', 'access_rules_status',
|
||||||
|
'mount_point_name',
|
||||||
]
|
]
|
||||||
share_instance_values, share_values = (
|
share_instance_values, share_values = (
|
||||||
_extract_subdict_by_fields(values, share_instance_model_fields)
|
_extract_subdict_by_fields(values, share_instance_model_fields)
|
||||||
|
@ -371,7 +371,7 @@ class ShareInstance(BASE, ManilaBase):
|
|||||||
host = Column(String(255))
|
host = Column(String(255))
|
||||||
status = Column(String(255))
|
status = Column(String(255))
|
||||||
progress = Column(String(32))
|
progress = Column(String(32))
|
||||||
|
mount_point_name = Column(String(255))
|
||||||
ACCESS_STATUS_PRIORITIES = {
|
ACCESS_STATUS_PRIORITIES = {
|
||||||
constants.STATUS_ACTIVE: 0,
|
constants.STATUS_ACTIVE: 0,
|
||||||
constants.SHARE_INSTANCE_RULES_SYNCING: 1,
|
constants.SHARE_INSTANCE_RULES_SYNCING: 1,
|
||||||
|
@ -39,6 +39,7 @@ class CapabilitiesFilter(base_host.BaseHostFilter):
|
|||||||
def host_passes(self, host_state, filter_properties):
|
def host_passes(self, host_state, filter_properties):
|
||||||
"""Return a list of hosts that can create resource_type."""
|
"""Return a list of hosts that can create resource_type."""
|
||||||
resource_type = filter_properties.get('resource_type')
|
resource_type = filter_properties.get('resource_type')
|
||||||
|
|
||||||
if not self._satisfies_extra_specs(host_state.capabilities,
|
if not self._satisfies_extra_specs(host_state.capabilities,
|
||||||
resource_type):
|
resource_type):
|
||||||
LOG.debug("%(host_state)s fails resource_type extra_specs "
|
LOG.debug("%(host_state)s fails resource_type extra_specs "
|
||||||
|
@ -162,6 +162,7 @@ class HostState(object):
|
|||||||
self.security_service_update_support = False
|
self.security_service_update_support = False
|
||||||
self.network_allocation_update_support = False
|
self.network_allocation_update_support = False
|
||||||
self.share_server_multiple_subnet_support = False
|
self.share_server_multiple_subnet_support = False
|
||||||
|
self.mount_point_name_support = False
|
||||||
|
|
||||||
# PoolState for all pools
|
# PoolState for all pools
|
||||||
self.pools = {}
|
self.pools = {}
|
||||||
|
@ -66,7 +66,9 @@ def generate_stats(host_state, properties):
|
|||||||
'network_allocation_update_support': (
|
'network_allocation_update_support': (
|
||||||
host_state.network_allocation_update_support),
|
host_state.network_allocation_update_support),
|
||||||
'share_server_multiple_subnet_support': (
|
'share_server_multiple_subnet_support': (
|
||||||
host_state.share_server_multiple_subnet_support)
|
host_state.share_server_multiple_subnet_support),
|
||||||
|
'mount_point_name_support': (
|
||||||
|
host_state.mount_point_name_support)
|
||||||
}
|
}
|
||||||
|
|
||||||
host_caps = host_state.capabilities
|
host_caps = host_state.capabilities
|
||||||
|
@ -21,6 +21,7 @@ Handles all requests relating to shares.
|
|||||||
"""
|
"""
|
||||||
import functools
|
import functools
|
||||||
import json
|
import json
|
||||||
|
import re
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
@ -270,7 +271,8 @@ class API(base.Base):
|
|||||||
share_network_id=None, share_type=None, is_public=False,
|
share_network_id=None, share_type=None, is_public=False,
|
||||||
share_group_id=None, share_group_snapshot_member=None,
|
share_group_id=None, share_group_snapshot_member=None,
|
||||||
availability_zones=None, scheduler_hints=None,
|
availability_zones=None, scheduler_hints=None,
|
||||||
az_request_multiple_subnet_support_map=None):
|
az_request_multiple_subnet_support_map=None,
|
||||||
|
mount_point_name=None):
|
||||||
"""Create new share."""
|
"""Create new share."""
|
||||||
|
|
||||||
api_common.check_metadata_properties(metadata)
|
api_common.check_metadata_properties(metadata)
|
||||||
@ -348,6 +350,18 @@ class API(base.Base):
|
|||||||
deltas = {'shares': 1, 'gigabytes': size}
|
deltas = {'shares': 1, 'gigabytes': size}
|
||||||
share_type_attributes = self.get_share_attributes_from_share_type(
|
share_type_attributes = self.get_share_attributes_from_share_type(
|
||||||
share_type)
|
share_type)
|
||||||
|
|
||||||
|
mount_point_name_support = share_type_attributes.get(
|
||||||
|
constants.ExtraSpecs.MOUNT_POINT_NAME_SUPPORT, None)
|
||||||
|
if mount_point_name is not None:
|
||||||
|
if not mount_point_name_support:
|
||||||
|
msg = _("Setting a mount point name is not supported"
|
||||||
|
" by the share type used: %s." % share_type_id)
|
||||||
|
raise exception.InvalidInput(reason=msg)
|
||||||
|
mount_point_name = self._prefix_mount_point_name(
|
||||||
|
share_type, context, mount_point_name
|
||||||
|
)
|
||||||
|
|
||||||
share_type_supports_replication = share_type_attributes.get(
|
share_type_supports_replication = share_type_attributes.get(
|
||||||
'replication_type', None)
|
'replication_type', None)
|
||||||
if share_type_supports_replication:
|
if share_type_supports_replication:
|
||||||
@ -482,7 +496,8 @@ class API(base.Base):
|
|||||||
share_type_id=share_type_id, availability_zones=availability_zones,
|
share_type_id=share_type_id, availability_zones=availability_zones,
|
||||||
snapshot_host=snapshot_host, scheduler_hints=scheduler_hints,
|
snapshot_host=snapshot_host, scheduler_hints=scheduler_hints,
|
||||||
az_request_multiple_subnet_support_map=(
|
az_request_multiple_subnet_support_map=(
|
||||||
az_request_multiple_subnet_support_map))
|
az_request_multiple_subnet_support_map),
|
||||||
|
mount_point_name=mount_point_name)
|
||||||
|
|
||||||
# Retrieve the share with instance details
|
# Retrieve the share with instance details
|
||||||
share = self.db.share_get(context, share['id'])
|
share = self.db.share_get(context, share['id'])
|
||||||
@ -505,6 +520,9 @@ class API(base.Base):
|
|||||||
constants.ExtraSpecs.REVERT_TO_SNAPSHOT_SUPPORT)
|
constants.ExtraSpecs.REVERT_TO_SNAPSHOT_SUPPORT)
|
||||||
mount_snapshot_support_key = (
|
mount_snapshot_support_key = (
|
||||||
constants.ExtraSpecs.MOUNT_SNAPSHOT_SUPPORT)
|
constants.ExtraSpecs.MOUNT_SNAPSHOT_SUPPORT)
|
||||||
|
mount_point_name_support_key = (
|
||||||
|
constants.ExtraSpecs.MOUNT_POINT_NAME_SUPPORT
|
||||||
|
)
|
||||||
|
|
||||||
snapshot_support_default = inferred_map.get(snapshot_support_key)
|
snapshot_support_default = inferred_map.get(snapshot_support_key)
|
||||||
create_share_from_snapshot_support_default = inferred_map.get(
|
create_share_from_snapshot_support_default = inferred_map.get(
|
||||||
@ -513,6 +531,7 @@ class API(base.Base):
|
|||||||
revert_to_snapshot_key)
|
revert_to_snapshot_key)
|
||||||
mount_snapshot_support_default = inferred_map.get(
|
mount_snapshot_support_default = inferred_map.get(
|
||||||
constants.ExtraSpecs.MOUNT_SNAPSHOT_SUPPORT)
|
constants.ExtraSpecs.MOUNT_SNAPSHOT_SUPPORT)
|
||||||
|
mount_point_name_support_default = False
|
||||||
|
|
||||||
if share_type:
|
if share_type:
|
||||||
snapshot_support = share_types.parse_boolean_extra_spec(
|
snapshot_support = share_types.parse_boolean_extra_spec(
|
||||||
@ -536,6 +555,11 @@ class API(base.Base):
|
|||||||
'extra_specs', {}).get(
|
'extra_specs', {}).get(
|
||||||
mount_snapshot_support_key,
|
mount_snapshot_support_key,
|
||||||
mount_snapshot_support_default))
|
mount_snapshot_support_default))
|
||||||
|
mount_point_name_support = share_types.parse_boolean_extra_spec(
|
||||||
|
mount_point_name_support_key, share_type.get(
|
||||||
|
'extra_specs', {}).get(
|
||||||
|
mount_point_name_support_key,
|
||||||
|
mount_point_name_support_default))
|
||||||
replication_type = share_type.get('extra_specs', {}).get(
|
replication_type = share_type.get('extra_specs', {}).get(
|
||||||
'replication_type')
|
'replication_type')
|
||||||
else:
|
else:
|
||||||
@ -544,6 +568,7 @@ class API(base.Base):
|
|||||||
create_share_from_snapshot_support_default)
|
create_share_from_snapshot_support_default)
|
||||||
revert_to_snapshot_support = revert_to_snapshot_support_default
|
revert_to_snapshot_support = revert_to_snapshot_support_default
|
||||||
mount_snapshot_support = mount_snapshot_support_default
|
mount_snapshot_support = mount_snapshot_support_default
|
||||||
|
mount_point_name_support = mount_point_name_support_default
|
||||||
replication_type = None
|
replication_type = None
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -553,6 +578,7 @@ class API(base.Base):
|
|||||||
'revert_to_snapshot_support': revert_to_snapshot_support,
|
'revert_to_snapshot_support': revert_to_snapshot_support,
|
||||||
'replication_type': replication_type,
|
'replication_type': replication_type,
|
||||||
'mount_snapshot_support': mount_snapshot_support,
|
'mount_snapshot_support': mount_snapshot_support,
|
||||||
|
'mount_point_name_support': mount_point_name_support,
|
||||||
}
|
}
|
||||||
|
|
||||||
def create_instance(self, context, share, share_network_id=None,
|
def create_instance(self, context, share, share_network_id=None,
|
||||||
@ -560,7 +586,8 @@ class API(base.Base):
|
|||||||
share_group=None, share_group_snapshot_member=None,
|
share_group=None, share_group_snapshot_member=None,
|
||||||
share_type_id=None, availability_zones=None,
|
share_type_id=None, availability_zones=None,
|
||||||
snapshot_host=None, scheduler_hints=None,
|
snapshot_host=None, scheduler_hints=None,
|
||||||
az_request_multiple_subnet_support_map=None):
|
az_request_multiple_subnet_support_map=None,
|
||||||
|
mount_point_name=None):
|
||||||
request_spec, share_instance = (
|
request_spec, share_instance = (
|
||||||
self.create_share_instance_and_get_request_spec(
|
self.create_share_instance_and_get_request_spec(
|
||||||
context, share, availability_zone=availability_zone,
|
context, share, availability_zone=availability_zone,
|
||||||
@ -570,7 +597,8 @@ class API(base.Base):
|
|||||||
availability_zones=availability_zones,
|
availability_zones=availability_zones,
|
||||||
snapshot_host=snapshot_host,
|
snapshot_host=snapshot_host,
|
||||||
az_request_multiple_subnet_support_map=(
|
az_request_multiple_subnet_support_map=(
|
||||||
az_request_multiple_subnet_support_map)))
|
az_request_multiple_subnet_support_map),
|
||||||
|
mount_point_name=mount_point_name))
|
||||||
|
|
||||||
if share_group_snapshot_member:
|
if share_group_snapshot_member:
|
||||||
# Inherit properties from the share_group_snapshot_member
|
# Inherit properties from the share_group_snapshot_member
|
||||||
@ -613,7 +641,8 @@ class API(base.Base):
|
|||||||
share_group=None, host=None, share_network_id=None,
|
share_group=None, host=None, share_network_id=None,
|
||||||
share_type_id=None, cast_rules_to_readonly=False,
|
share_type_id=None, cast_rules_to_readonly=False,
|
||||||
availability_zones=None, snapshot_host=None,
|
availability_zones=None, snapshot_host=None,
|
||||||
az_request_multiple_subnet_support_map=None):
|
az_request_multiple_subnet_support_map=None,
|
||||||
|
mount_point_name=None):
|
||||||
|
|
||||||
availability_zone_id = None
|
availability_zone_id = None
|
||||||
if availability_zone:
|
if availability_zone:
|
||||||
@ -633,6 +662,7 @@ class API(base.Base):
|
|||||||
'availability_zone_id': availability_zone_id,
|
'availability_zone_id': availability_zone_id,
|
||||||
'share_type_id': share_type_id,
|
'share_type_id': share_type_id,
|
||||||
'cast_rules_to_readonly': cast_rules_to_readonly,
|
'cast_rules_to_readonly': cast_rules_to_readonly,
|
||||||
|
'mount_point_name': mount_point_name,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -666,7 +696,7 @@ class API(base.Base):
|
|||||||
'host': share_instance['host'],
|
'host': share_instance['host'],
|
||||||
'status': share_instance['status'],
|
'status': share_instance['status'],
|
||||||
'replica_state': share_instance['replica_state'],
|
'replica_state': share_instance['replica_state'],
|
||||||
'share_type_id': share_instance['share_type_id'],
|
'share_type_id': share_instance['share_type_id']
|
||||||
}
|
}
|
||||||
|
|
||||||
share_type = None
|
share_type = None
|
||||||
@ -686,7 +716,7 @@ class API(base.Base):
|
|||||||
'availability_zone_id': availability_zone_id,
|
'availability_zone_id': availability_zone_id,
|
||||||
'availability_zones': availability_zones,
|
'availability_zones': availability_zones,
|
||||||
'az_request_multiple_subnet_support_map': (
|
'az_request_multiple_subnet_support_map': (
|
||||||
az_request_multiple_subnet_support_map),
|
az_request_multiple_subnet_support_map)
|
||||||
}
|
}
|
||||||
return request_spec, share_instance
|
return request_spec, share_instance
|
||||||
|
|
||||||
@ -1063,6 +1093,11 @@ class API(base.Base):
|
|||||||
share_type.get('extra_specs', {}).get(
|
share_type.get('extra_specs', {}).get(
|
||||||
'mount_snapshot_support')
|
'mount_snapshot_support')
|
||||||
),
|
),
|
||||||
|
'mount_point_name_support': kwargs.get(
|
||||||
|
'mount_point_name_support',
|
||||||
|
share_type.get('extra_specs', {}).get(
|
||||||
|
'mount_point_name_support')
|
||||||
|
),
|
||||||
'share_proto': kwargs.get('share_proto', share.get('share_proto')),
|
'share_proto': kwargs.get('share_proto', share.get('share_proto')),
|
||||||
'share_type_id': share_type['id'],
|
'share_type_id': share_type['id'],
|
||||||
'is_public': kwargs.get('is_public', share.get('is_public')),
|
'is_public': kwargs.get('is_public', share.get('is_public')),
|
||||||
@ -1094,6 +1129,25 @@ class API(base.Base):
|
|||||||
}
|
}
|
||||||
return request_spec
|
return request_spec
|
||||||
|
|
||||||
|
def _prefix_mount_point_name(self, share_type, context,
|
||||||
|
mount_point_name=None):
|
||||||
|
prefix = share_type.get('extra_specs').get(
|
||||||
|
constants.ExtraSpecs.PROVISIONING_MOUNT_POINT_PREFIX)
|
||||||
|
prefix = prefix or context.project_id
|
||||||
|
prefix = prefix.format(context.to_dict())
|
||||||
|
mount_point_name = f"{prefix}_{mount_point_name}"
|
||||||
|
|
||||||
|
if mount_point_name and (
|
||||||
|
not re.match(
|
||||||
|
r'^[a-zA-Z0-9_]*$', mount_point_name)
|
||||||
|
or len(mount_point_name) > 255
|
||||||
|
):
|
||||||
|
msg = _("Invalid mount_point_name: %s")
|
||||||
|
LOG.error(msg, mount_point_name)
|
||||||
|
raise exception.InvalidInput(msg % mount_point_name)
|
||||||
|
|
||||||
|
return mount_point_name
|
||||||
|
|
||||||
@prevent_locked_action_on_share('delete')
|
@prevent_locked_action_on_share('delete')
|
||||||
def unmanage(self, context, share):
|
def unmanage(self, context, share):
|
||||||
policy.check_policy(context, 'share', 'unmanage')
|
policy.check_policy(context, 'share', 'unmanage')
|
||||||
|
@ -1356,6 +1356,7 @@ class ShareDriver(object):
|
|||||||
network_allocation_update_support=(
|
network_allocation_update_support=(
|
||||||
self.network_allocation_update_support),
|
self.network_allocation_update_support),
|
||||||
share_server_multiple_subnet_support=False,
|
share_server_multiple_subnet_support=False,
|
||||||
|
mount_point_name_support=False,
|
||||||
)
|
)
|
||||||
if isinstance(data, dict):
|
if isinstance(data, dict):
|
||||||
common.update(data)
|
common.update(data)
|
||||||
|
@ -137,6 +137,7 @@ class ContainerShareDriver(driver.ShareDriver, driver.ExecuteMixin):
|
|||||||
'pools': self.storage.get_share_server_pools(),
|
'pools': self.storage.get_share_server_pools(),
|
||||||
'security_service_update_support': True,
|
'security_service_update_support': True,
|
||||||
'share_server_multiple_subnet_support': True,
|
'share_server_multiple_subnet_support': True,
|
||||||
|
'mount_point_name_support': False,
|
||||||
}
|
}
|
||||||
super(ContainerShareDriver, self)._update_share_stats(data)
|
super(ContainerShareDriver, self)._update_share_stats(data)
|
||||||
|
|
||||||
|
@ -116,6 +116,9 @@ class LVMMixin(driver.ExecuteMixin):
|
|||||||
except processutils.ProcessExecutionError:
|
except processutils.ProcessExecutionError:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
def _get_mount_point_name(self, share):
|
||||||
|
return share.get('mount_point_name') or share.get('name')
|
||||||
|
|
||||||
def _extend_container(self, share, device_name, size):
|
def _extend_container(self, share, device_name, size):
|
||||||
privsep_common.execute_with_retries(
|
privsep_common.execute_with_retries(
|
||||||
privsep_lvm.lvextend, [device_name, size],
|
privsep_lvm.lvextend, [device_name, size],
|
||||||
@ -267,14 +270,16 @@ class LVMShareDriver(LVMMixin, driver.ShareDriver):
|
|||||||
'reserved_percentage': 0,
|
'reserved_percentage': 0,
|
||||||
'reserved_snapshot_percentage': 0,
|
'reserved_snapshot_percentage': 0,
|
||||||
'reserved_share_extend_percentage': 0,
|
'reserved_share_extend_percentage': 0,
|
||||||
|
'mount_point_name_support': True,
|
||||||
}, ]
|
}, ]
|
||||||
|
|
||||||
def create_share(self, context, share, share_server=None):
|
def create_share(self, context, share, share_server=None):
|
||||||
self._allocate_container(share)
|
self._allocate_container(share)
|
||||||
# create file system
|
# create file system
|
||||||
device_name = self._get_local_path(share)
|
device_name = self._get_local_path(share)
|
||||||
|
share_export_location = self._get_mount_point_name(share)
|
||||||
location = self._get_helper(share).create_exports(
|
location = self._get_helper(share).create_exports(
|
||||||
self.share_server, share['name'])
|
self.share_server, share_export_location)
|
||||||
self._mount_device(share, device_name)
|
self._mount_device(share, device_name)
|
||||||
return location
|
return location
|
||||||
|
|
||||||
@ -287,8 +292,9 @@ class LVMShareDriver(LVMMixin, driver.ShareDriver):
|
|||||||
self._set_random_uuid_to_device(share)
|
self._set_random_uuid_to_device(share)
|
||||||
self._copy_volume(
|
self._copy_volume(
|
||||||
snapshot_device_name, share_device_name, share['size'])
|
snapshot_device_name, share_device_name, share['size'])
|
||||||
|
share_export_location = self._get_mount_point_name(share)
|
||||||
location = self._get_helper(share).create_exports(
|
location = self._get_helper(share).create_exports(
|
||||||
self.share_server, share['name'])
|
self.share_server, share_export_location)
|
||||||
self._mount_device(share, share_device_name)
|
self._mount_device(share, share_device_name)
|
||||||
return location
|
return location
|
||||||
|
|
||||||
@ -342,14 +348,19 @@ class LVMShareDriver(LVMMixin, driver.ShareDriver):
|
|||||||
"""Ensure that storage are mounted and exported."""
|
"""Ensure that storage are mounted and exported."""
|
||||||
device_name = self._get_local_path(share)
|
device_name = self._get_local_path(share)
|
||||||
self._mount_device(share, device_name)
|
self._mount_device(share, device_name)
|
||||||
|
share_export_location = self._get_mount_point_name(share)
|
||||||
return self._get_helper(share).create_exports(
|
return self._get_helper(share).create_exports(
|
||||||
self.share_server, share['name'], recreate=True)
|
self.share_server,
|
||||||
|
share_export_location,
|
||||||
|
recreate=True
|
||||||
|
)
|
||||||
|
|
||||||
def _delete_share(self, ctx, share):
|
def _delete_share(self, ctx, share):
|
||||||
|
share_export_location = self._get_mount_point_name(share)
|
||||||
"""Delete a share."""
|
"""Delete a share."""
|
||||||
try:
|
try:
|
||||||
self._get_helper(share).remove_exports(
|
self._get_helper(share).remove_exports(
|
||||||
self.share_server, share['name'])
|
self.share_server, share_export_location)
|
||||||
except exception.ProcessExecutionError:
|
except exception.ProcessExecutionError:
|
||||||
LOG.warning("Can't remove share %r", share['id'])
|
LOG.warning("Can't remove share %r", share['id'])
|
||||||
except exception.InvalidShare as exc:
|
except exception.InvalidShare as exc:
|
||||||
@ -379,8 +390,10 @@ class LVMShareDriver(LVMMixin, driver.ShareDriver):
|
|||||||
removed. access_rules doesn't contain these rules.
|
removed. access_rules doesn't contain these rules.
|
||||||
:param share_server: None or Share server model
|
:param share_server: None or Share server model
|
||||||
"""
|
"""
|
||||||
|
share_export_location = self._get_mount_point_name(share)
|
||||||
self._get_helper(share).update_access(self.share_server,
|
self._get_helper(share).update_access(self.share_server,
|
||||||
share['name'], access_rules,
|
share_export_location,
|
||||||
|
access_rules,
|
||||||
add_rules=add_rules,
|
add_rules=add_rules,
|
||||||
delete_rules=delete_rules)
|
delete_rules=delete_rules)
|
||||||
|
|
||||||
@ -434,11 +447,15 @@ class LVMShareDriver(LVMMixin, driver.ShareDriver):
|
|||||||
def revert_to_snapshot(self, context, snapshot, share_access_rules,
|
def revert_to_snapshot(self, context, snapshot, share_access_rules,
|
||||||
snapshot_access_rules, share_server=None):
|
snapshot_access_rules, share_server=None):
|
||||||
share = snapshot['share']
|
share = snapshot['share']
|
||||||
|
snapshot_export_location = self._get_mount_point_name(snapshot)
|
||||||
|
share_export_location = self._get_mount_point_name(share)
|
||||||
# Temporarily remove all access rules
|
# Temporarily remove all access rules
|
||||||
self._get_helper(share).update_access(self.share_server,
|
self._get_helper(share).update_access(self.share_server,
|
||||||
snapshot['name'], [], [], [])
|
snapshot_export_location,
|
||||||
|
[], [], [])
|
||||||
self._get_helper(share).update_access(self.share_server,
|
self._get_helper(share).update_access(self.share_server,
|
||||||
share['name'], [], [], [])
|
share_export_location,
|
||||||
|
[], [], [])
|
||||||
# Unmount the snapshot filesystem
|
# Unmount the snapshot filesystem
|
||||||
self._unmount_device(snapshot)
|
self._unmount_device(snapshot)
|
||||||
# Unmount the share filesystem
|
# Unmount the share filesystem
|
||||||
@ -459,15 +476,17 @@ class LVMShareDriver(LVMMixin, driver.ShareDriver):
|
|||||||
# Also remount the snapshot
|
# Also remount the snapshot
|
||||||
device_name = self._get_local_path(snapshot)
|
device_name = self._get_local_path(snapshot)
|
||||||
self._mount_device(snapshot, device_name)
|
self._mount_device(snapshot, device_name)
|
||||||
|
share_export_location = self._get_mount_point_name(share)
|
||||||
|
snapshot_export_location = self._get_mount_point_name(share)
|
||||||
# Lastly we add all the access rules back
|
# Lastly we add all the access rules back
|
||||||
self._get_helper(share).update_access(self.share_server,
|
self._get_helper(share).update_access(self.share_server,
|
||||||
share['name'],
|
share_export_location,
|
||||||
share_access_rules,
|
share_access_rules,
|
||||||
[], [])
|
[], [])
|
||||||
snapshot_access_rules, __, __ = share_utils.change_rules_to_readonly(
|
snapshot_access_rules, __, __ = share_utils.change_rules_to_readonly(
|
||||||
snapshot_access_rules, [], [])
|
snapshot_access_rules, [], [])
|
||||||
self._get_helper(share).update_access(self.share_server,
|
self._get_helper(share).update_access(self.share_server,
|
||||||
snapshot['name'],
|
snapshot_export_location,
|
||||||
snapshot_access_rules,
|
snapshot_access_rules,
|
||||||
[], [])
|
[], [])
|
||||||
|
|
||||||
|
@ -330,6 +330,10 @@ def is_valid_csv(extra_spec_value):
|
|||||||
return all([v.strip() for v in values])
|
return all([v.strip() for v in values])
|
||||||
|
|
||||||
|
|
||||||
|
def is_valid_string(v):
|
||||||
|
return isinstance(v, str) and len(v) in range(1, 256)
|
||||||
|
|
||||||
|
|
||||||
def sanitize_csv(csv_string):
|
def sanitize_csv(csv_string):
|
||||||
return ','.join(value.strip() for value in csv_string.split(',')
|
return ','.join(value.strip() for value in csv_string.split(',')
|
||||||
if (csv_string and value))
|
if (csv_string and value))
|
||||||
@ -356,8 +360,12 @@ def is_valid_optional_extra_spec(key, value):
|
|||||||
return value in constants.ExtraSpecs.REPLICATION_TYPES
|
return value in constants.ExtraSpecs.REPLICATION_TYPES
|
||||||
elif key == constants.ExtraSpecs.MOUNT_SNAPSHOT_SUPPORT:
|
elif key == constants.ExtraSpecs.MOUNT_SNAPSHOT_SUPPORT:
|
||||||
return parse_boolean_extra_spec(key, value) is not None
|
return parse_boolean_extra_spec(key, value) is not None
|
||||||
|
elif key == constants.ExtraSpecs.MOUNT_POINT_NAME_SUPPORT:
|
||||||
|
return parse_boolean_extra_spec(key, value) is not None
|
||||||
elif key == constants.ExtraSpecs.AVAILABILITY_ZONES:
|
elif key == constants.ExtraSpecs.AVAILABILITY_ZONES:
|
||||||
return is_valid_csv(value)
|
return is_valid_csv(value)
|
||||||
|
elif key == constants.ExtraSpecs.PROVISIONING_MOUNT_POINT_PREFIX:
|
||||||
|
return is_valid_string(value)
|
||||||
elif key in [constants.ExtraSpecs.PROVISIONING_MAX_SHARE_SIZE,
|
elif key in [constants.ExtraSpecs.PROVISIONING_MAX_SHARE_SIZE,
|
||||||
constants.ExtraSpecs.PROVISIONING_MIN_SHARE_SIZE,
|
constants.ExtraSpecs.PROVISIONING_MIN_SHARE_SIZE,
|
||||||
constants.ExtraSpecs.PROVISIONING_MAX_SHARE_EXTEND_SIZE]:
|
constants.ExtraSpecs.PROVISIONING_MAX_SHARE_EXTEND_SIZE]:
|
||||||
|
@ -261,6 +261,37 @@ class ShareAPITest(test.TestCase):
|
|||||||
self.assertEqual("fakenetid",
|
self.assertEqual("fakenetid",
|
||||||
create_mock.call_args[1]['share_network_id'])
|
create_mock.call_args[1]['share_network_id'])
|
||||||
|
|
||||||
|
def test_share_create_mount_point_name(self):
|
||||||
|
shr = {
|
||||||
|
"size": 100,
|
||||||
|
"name": "Share Test Name",
|
||||||
|
"description": "Share Test Desc",
|
||||||
|
"share_proto": "fakeproto",
|
||||||
|
"mount_point_name": "fake_mp"
|
||||||
|
}
|
||||||
|
fake_network = {'id': 'fakenetid'}
|
||||||
|
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
||||||
|
display_name=shr['name'],
|
||||||
|
display_description=shr['description'],
|
||||||
|
size=shr['size'],
|
||||||
|
share_proto=shr['share_proto'].upper(),
|
||||||
|
mount_point_name=shr['mount_point_name']))
|
||||||
|
self.mock_object(share_api.API, 'create', create_mock)
|
||||||
|
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
||||||
|
return_value=fake_network))
|
||||||
|
self.mock_object(common, 'check_share_network_is_active',
|
||||||
|
mock.Mock(return_value=True))
|
||||||
|
self.mock_object(
|
||||||
|
db, 'share_network_subnets_get_all_by_availability_zone_id',
|
||||||
|
mock.Mock(return_value={'id': 'fakesubnetid'}))
|
||||||
|
|
||||||
|
body = {"share": copy.deepcopy(shr)}
|
||||||
|
req = fakes.HTTPRequest.blank('/v1/fake/shares')
|
||||||
|
self.controller.create(req, body)
|
||||||
|
|
||||||
|
self.mock_policy_check.assert_called_once_with(
|
||||||
|
req.environ['manila.context'], self.resource_name, 'create')
|
||||||
|
|
||||||
def test_share_create_with_share_net_not_active(self):
|
def test_share_create_with_share_net_not_active(self):
|
||||||
shr = {
|
shr = {
|
||||||
"size": 100,
|
"size": 100,
|
||||||
@ -459,6 +490,53 @@ class ShareAPITest(test.TestCase):
|
|||||||
self.mock_policy_check.assert_called_once_with(
|
self.mock_policy_check.assert_called_once_with(
|
||||||
req.environ['manila.context'], self.resource_name, 'create')
|
req.environ['manila.context'], self.resource_name, 'create')
|
||||||
|
|
||||||
|
def test_share_create_from_mount_point_name(self):
|
||||||
|
parent_share_net = 444
|
||||||
|
shr = {
|
||||||
|
"size": 100,
|
||||||
|
"name": "Share Test Name",
|
||||||
|
"description": "Share Test Desc",
|
||||||
|
"share_proto": "fakeproto",
|
||||||
|
"availability_zone": "zone1:host1",
|
||||||
|
"snapshot_id": 333,
|
||||||
|
"share_network_id": parent_share_net,
|
||||||
|
"mount_point_name": "fake_mp"
|
||||||
|
}
|
||||||
|
fake_share_net = {'id': parent_share_net}
|
||||||
|
share_net_subnets = [db_utils.create_share_network_subnet(
|
||||||
|
id='fake_subnet_id', share_network_id=fake_share_net['id'])]
|
||||||
|
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
||||||
|
display_name=shr['name'],
|
||||||
|
display_description=shr['description'],
|
||||||
|
size=shr['size'],
|
||||||
|
share_proto=shr['share_proto'].upper(),
|
||||||
|
snapshot_id=shr['snapshot_id'],
|
||||||
|
mount_point_name=shr['mount_point_name'],
|
||||||
|
instance=dict(
|
||||||
|
availability_zone=shr['availability_zone'],
|
||||||
|
share_network_id=shr['share_network_id'],
|
||||||
|
)))
|
||||||
|
self.mock_object(share_api.API, 'create', create_mock)
|
||||||
|
self.mock_object(share_api.API, 'get_snapshot',
|
||||||
|
stubs.stub_snapshot_get)
|
||||||
|
self.mock_object(common, 'check_share_network_is_active',
|
||||||
|
mock.Mock(return_value=True))
|
||||||
|
parent_share = stubs.stub_share(
|
||||||
|
'1', instance={'share_network_id': parent_share_net},
|
||||||
|
create_share_from_snapshot_support=True)
|
||||||
|
self.mock_object(share_api.API, 'get', mock.Mock(
|
||||||
|
return_value=parent_share))
|
||||||
|
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
||||||
|
return_value=fake_share_net))
|
||||||
|
self.mock_object(
|
||||||
|
db, 'share_network_subnets_get_all_by_availability_zone_id',
|
||||||
|
mock.Mock(return_value=share_net_subnets))
|
||||||
|
|
||||||
|
body = {"share": copy.deepcopy(shr)}
|
||||||
|
req = fakes.HTTPRequest.blank('/v1/fake/shares', version='2.84')
|
||||||
|
res_dict = self.controller.create(req, body)
|
||||||
|
self.assertEqual(res_dict['share']['project_id'], 'fakeproject')
|
||||||
|
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
{'name': 'name1', 'description': 'x' * 256},
|
{'name': 'name1', 'description': 'x' * 256},
|
||||||
{'name': 'x' * 256, 'description': 'description1'},
|
{'name': 'x' * 256, 'description': 'description1'},
|
||||||
|
@ -61,17 +61,40 @@ class ShareTransferAPITestCase(test.TestCase):
|
|||||||
size=1,
|
size=1,
|
||||||
project_id='fake_project_id',
|
project_id='fake_project_id',
|
||||||
user_id='fake_user_id',
|
user_id='fake_user_id',
|
||||||
share_network_id=None):
|
share_network_id=None,
|
||||||
|
mount_point_name=None):
|
||||||
"""Create a share object."""
|
"""Create a share object."""
|
||||||
share_type = db_utils.create_share_type()
|
share_type = db_utils.create_share_type()
|
||||||
share = db_utils.create_share(display_name=display_name,
|
if mount_point_name:
|
||||||
display_description=display_description,
|
instance_list = [
|
||||||
status=status, size=size,
|
db_utils.create_share_instance(
|
||||||
project_id=project_id,
|
status=status,
|
||||||
user_id=user_id,
|
share_id='fake_id',
|
||||||
share_type_id=share_type['id'],
|
mount_point_name=mount_point_name
|
||||||
share_network_id=share_network_id
|
)
|
||||||
)
|
]
|
||||||
|
share = db_utils.create_share(
|
||||||
|
display_name=display_name,
|
||||||
|
display_description=display_description,
|
||||||
|
status=status, size=size,
|
||||||
|
project_id=project_id,
|
||||||
|
user_id=user_id,
|
||||||
|
share_type_id=share_type['id'],
|
||||||
|
share_network_id=share_network_id,
|
||||||
|
instances=instance_list
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
share = db_utils.create_share(
|
||||||
|
display_name=display_name,
|
||||||
|
display_description=display_description,
|
||||||
|
status=status,
|
||||||
|
size=size,
|
||||||
|
project_id=project_id,
|
||||||
|
user_id=user_id,
|
||||||
|
share_type_id=share_type['id'],
|
||||||
|
share_network_id=share_network_id,
|
||||||
|
mount_point_name=mount_point_name
|
||||||
|
)
|
||||||
share_id = share['id']
|
share_id = share['id']
|
||||||
return share_id
|
return share_id
|
||||||
|
|
||||||
@ -232,6 +255,35 @@ class ShareTransferAPITestCase(test.TestCase):
|
|||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
self.v2_controller.create, req, body)
|
self.v2_controller.create, req, body)
|
||||||
|
|
||||||
|
def test_create_transfer_with_invalid_mount_point_name(self):
|
||||||
|
share_id = self._create_share(
|
||||||
|
project_id='fake_pid',
|
||||||
|
mount_point_name='fake_pid_mount_point_name')
|
||||||
|
body = {"transfer": {"name": "transfer1",
|
||||||
|
"share_id": share_id}}
|
||||||
|
db.share_update(context.get_admin_context(),
|
||||||
|
share_id, {'status': 'error'})
|
||||||
|
|
||||||
|
path = '/v2/fake_project_id/share-transfers'
|
||||||
|
req = fakes.HTTPRequest.blank(path, version=self.microversion)
|
||||||
|
req.environ['manila.context'] = self.ctxt
|
||||||
|
req.method = 'POST'
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.body = jsonutils.dumps(body).encode("utf-8")
|
||||||
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
|
self.v2_controller.create, req, body)
|
||||||
|
|
||||||
|
def test_create_transfer_with_project_id_prefix_mount_point_name(self):
|
||||||
|
share_id = self._create_share(project_id='fake',
|
||||||
|
mount_point_name='fake_mp')
|
||||||
|
'''self.share_transfer_api.create(context.get_admin_context(),
|
||||||
|
share_id,
|
||||||
|
'test_missing_share_type')'''
|
||||||
|
self.assertRaises(exception.Invalid,
|
||||||
|
self.share_transfer_api.create,
|
||||||
|
context.get_admin_context(), share_id,
|
||||||
|
'test_missing_share_type')
|
||||||
|
|
||||||
def test_create_transfer_share_with_network_id(self):
|
def test_create_transfer_share_with_network_id(self):
|
||||||
share_id = self._create_share(share_network_id='fake_id')
|
share_id = self._create_share(share_network_id='fake_id')
|
||||||
body = {"transfer": {"name": "transfer1",
|
body = {"transfer": {"name": "transfer1",
|
||||||
|
@ -393,6 +393,7 @@ class ShareTypesAPITest(test.TestCase):
|
|||||||
constants.ExtraSpecs.CREATE_SHARE_FROM_SNAPSHOT_SUPPORT: False,
|
constants.ExtraSpecs.CREATE_SHARE_FROM_SNAPSHOT_SUPPORT: False,
|
||||||
constants.ExtraSpecs.REVERT_TO_SNAPSHOT_SUPPORT: True,
|
constants.ExtraSpecs.REVERT_TO_SNAPSHOT_SUPPORT: True,
|
||||||
constants.ExtraSpecs.MOUNT_SNAPSHOT_SUPPORT: True,
|
constants.ExtraSpecs.MOUNT_SNAPSHOT_SUPPORT: True,
|
||||||
|
constants.ExtraSpecs.MOUNT_POINT_NAME_SUPPORT: True,
|
||||||
}
|
}
|
||||||
|
|
||||||
now = timeutils.utcnow().isoformat()
|
now = timeutils.utcnow().isoformat()
|
||||||
|
@ -94,7 +94,8 @@ def create_share(**kwargs):
|
|||||||
'availability_zone': 'fake_availability_zone',
|
'availability_zone': 'fake_availability_zone',
|
||||||
'status': constants.STATUS_CREATING,
|
'status': constants.STATUS_CREATING,
|
||||||
'host': 'fake_host',
|
'host': 'fake_host',
|
||||||
'is_soft_deleted': False
|
'is_soft_deleted': False,
|
||||||
|
'mount_point_name': 'fake_mp',
|
||||||
}
|
}
|
||||||
return _create_db_row(db.share_create, share, kwargs)
|
return _create_db_row(db.share_create, share, kwargs)
|
||||||
|
|
||||||
@ -112,7 +113,8 @@ def create_share_without_instance(**kwargs):
|
|||||||
'availability_zone': 'fake_availability_zone',
|
'availability_zone': 'fake_availability_zone',
|
||||||
'status': constants.STATUS_CREATING,
|
'status': constants.STATUS_CREATING,
|
||||||
'host': 'fake_host',
|
'host': 'fake_host',
|
||||||
'is_soft_deleted': False
|
'is_soft_deleted': False,
|
||||||
|
'mount_point_name': None,
|
||||||
}
|
}
|
||||||
share.update(copy.deepcopy(kwargs))
|
share.update(copy.deepcopy(kwargs))
|
||||||
return db.share_create(context.get_admin_context(), share, False)
|
return db.share_create(context.get_admin_context(), share, False)
|
||||||
|
@ -64,6 +64,7 @@ def fake_share_instance(base_share=None, **kwargs):
|
|||||||
'share_network_id': 'fakesharenetworkid',
|
'share_network_id': 'fakesharenetworkid',
|
||||||
'share_server_id': 'fakeshareserverid',
|
'share_server_id': 'fakeshareserverid',
|
||||||
'share_type_id': '1',
|
'share_type_id': '1',
|
||||||
|
'mount_point_name': None,
|
||||||
}
|
}
|
||||||
|
|
||||||
for attr in models.ShareInstance._proxified_properties:
|
for attr in models.ShareInstance._proxified_properties:
|
||||||
@ -82,7 +83,8 @@ def fake_share_type(**kwargs):
|
|||||||
'is_public': False,
|
'is_public': False,
|
||||||
'extra_specs': {
|
'extra_specs': {
|
||||||
'driver_handles_share_servers': 'False',
|
'driver_handles_share_servers': 'False',
|
||||||
}
|
},
|
||||||
|
'mount_point_name_support': False
|
||||||
}
|
}
|
||||||
|
|
||||||
extra_specs = kwargs.pop('extra_specs', {})
|
extra_specs = kwargs.pop('extra_specs', {})
|
||||||
|
@ -55,7 +55,8 @@ SERVICE_STATES_NO_POOLS = {
|
|||||||
create_share_from_snapshot_support=False,
|
create_share_from_snapshot_support=False,
|
||||||
revert_to_snapshot_support=True,
|
revert_to_snapshot_support=True,
|
||||||
mount_snapshot_support=True,
|
mount_snapshot_support=True,
|
||||||
driver_handles_share_servers=False),
|
driver_handles_share_servers=False,
|
||||||
|
mount_point_name_support=False),
|
||||||
'host2@back1': dict(share_backend_name='BBB',
|
'host2@back1': dict(share_backend_name='BBB',
|
||||||
total_capacity_gb=256, free_capacity_gb=100,
|
total_capacity_gb=256, free_capacity_gb=100,
|
||||||
timestamp=None, reserved_percentage=0,
|
timestamp=None, reserved_percentage=0,
|
||||||
@ -68,7 +69,8 @@ SERVICE_STATES_NO_POOLS = {
|
|||||||
create_share_from_snapshot_support=True,
|
create_share_from_snapshot_support=True,
|
||||||
revert_to_snapshot_support=False,
|
revert_to_snapshot_support=False,
|
||||||
mount_snapshot_support=False,
|
mount_snapshot_support=False,
|
||||||
driver_handles_share_servers=False),
|
driver_handles_share_servers=False,
|
||||||
|
mount_point_name_support=False),
|
||||||
'host2@back2': dict(share_backend_name='CCC',
|
'host2@back2': dict(share_backend_name='CCC',
|
||||||
total_capacity_gb=10000, free_capacity_gb=700,
|
total_capacity_gb=10000, free_capacity_gb=700,
|
||||||
timestamp=None, reserved_percentage=0,
|
timestamp=None, reserved_percentage=0,
|
||||||
@ -81,7 +83,8 @@ SERVICE_STATES_NO_POOLS = {
|
|||||||
create_share_from_snapshot_support=True,
|
create_share_from_snapshot_support=True,
|
||||||
revert_to_snapshot_support=False,
|
revert_to_snapshot_support=False,
|
||||||
mount_snapshot_support=False,
|
mount_snapshot_support=False,
|
||||||
driver_handles_share_servers=False),
|
driver_handles_share_servers=False,
|
||||||
|
mount_point_name_support=False),
|
||||||
}
|
}
|
||||||
|
|
||||||
SHARE_SERVICES_WITH_POOLS = [
|
SHARE_SERVICES_WITH_POOLS = [
|
||||||
@ -124,7 +127,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
|||||||
reserved_share_extend_percentage=0,
|
reserved_share_extend_percentage=0,
|
||||||
provisioned_capacity_gb=10,
|
provisioned_capacity_gb=10,
|
||||||
max_over_subscription_ratio=1.0,
|
max_over_subscription_ratio=1.0,
|
||||||
thin_provisioning=False)]),
|
thin_provisioning=False,
|
||||||
|
mount_point_name_support=False,
|
||||||
|
)]),
|
||||||
'host2@BBB': dict(share_backend_name='BBB',
|
'host2@BBB': dict(share_backend_name='BBB',
|
||||||
timestamp=None, reserved_percentage=0,
|
timestamp=None, reserved_percentage=0,
|
||||||
reserved_snapshot_percentage=0,
|
reserved_snapshot_percentage=0,
|
||||||
@ -142,7 +147,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
|||||||
reserved_share_extend_percentage=0,
|
reserved_share_extend_percentage=0,
|
||||||
provisioned_capacity_gb=60,
|
provisioned_capacity_gb=60,
|
||||||
max_over_subscription_ratio=2.0,
|
max_over_subscription_ratio=2.0,
|
||||||
thin_provisioning=True)]),
|
thin_provisioning=True,
|
||||||
|
mount_point_name_support=False,
|
||||||
|
)]),
|
||||||
'host3@CCC': dict(share_backend_name='CCC',
|
'host3@CCC': dict(share_backend_name='CCC',
|
||||||
timestamp=None, reserved_percentage=0,
|
timestamp=None, reserved_percentage=0,
|
||||||
reserved_snapshot_percentage=0,
|
reserved_snapshot_percentage=0,
|
||||||
@ -160,7 +167,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
|||||||
reserved_share_extend_percentage=0,
|
reserved_share_extend_percentage=0,
|
||||||
provisioned_capacity_gb=100,
|
provisioned_capacity_gb=100,
|
||||||
max_over_subscription_ratio=20.0,
|
max_over_subscription_ratio=20.0,
|
||||||
thin_provisioning=True)]),
|
thin_provisioning=True,
|
||||||
|
mount_point_name_support=False,
|
||||||
|
)]),
|
||||||
'host4@DDD': dict(share_backend_name='DDD',
|
'host4@DDD': dict(share_backend_name='DDD',
|
||||||
timestamp=None, reserved_percentage=0,
|
timestamp=None, reserved_percentage=0,
|
||||||
reserved_snapshot_percentage=0,
|
reserved_snapshot_percentage=0,
|
||||||
@ -178,7 +187,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
|||||||
reserved_share_extend_percentage=0,
|
reserved_share_extend_percentage=0,
|
||||||
provisioned_capacity_gb=800,
|
provisioned_capacity_gb=800,
|
||||||
max_over_subscription_ratio=2.0,
|
max_over_subscription_ratio=2.0,
|
||||||
thin_provisioning=True),
|
thin_provisioning=True,
|
||||||
|
mount_point_name_support=False,
|
||||||
|
),
|
||||||
dict(pool_name='pool4b',
|
dict(pool_name='pool4b',
|
||||||
total_capacity_gb=542,
|
total_capacity_gb=542,
|
||||||
free_capacity_gb=442,
|
free_capacity_gb=442,
|
||||||
@ -187,7 +198,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
|||||||
reserved_share_extend_percentage=0,
|
reserved_share_extend_percentage=0,
|
||||||
provisioned_capacity_gb=2000,
|
provisioned_capacity_gb=2000,
|
||||||
max_over_subscription_ratio=10.0,
|
max_over_subscription_ratio=10.0,
|
||||||
thin_provisioning=True)]),
|
thin_provisioning=True,
|
||||||
|
mount_point_name_support=False,
|
||||||
|
)]),
|
||||||
'host5@EEE': dict(share_backend_name='EEE',
|
'host5@EEE': dict(share_backend_name='EEE',
|
||||||
timestamp=None, reserved_percentage=0,
|
timestamp=None, reserved_percentage=0,
|
||||||
reserved_snapshot_percentage=0,
|
reserved_snapshot_percentage=0,
|
||||||
@ -205,7 +218,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
|||||||
reserved_share_extend_percentage=0,
|
reserved_share_extend_percentage=0,
|
||||||
provisioned_capacity_gb=100,
|
provisioned_capacity_gb=100,
|
||||||
max_over_subscription_ratio=1.0,
|
max_over_subscription_ratio=1.0,
|
||||||
thin_provisioning=False),
|
thin_provisioning=False,
|
||||||
|
mount_point_name_support=False,
|
||||||
|
),
|
||||||
dict(pool_name='pool5b',
|
dict(pool_name='pool5b',
|
||||||
total_capacity_gb=552,
|
total_capacity_gb=552,
|
||||||
free_capacity_gb=452,
|
free_capacity_gb=452,
|
||||||
@ -214,7 +229,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
|||||||
reserved_share_extend_percentage=0,
|
reserved_share_extend_percentage=0,
|
||||||
provisioned_capacity_gb=100,
|
provisioned_capacity_gb=100,
|
||||||
max_over_subscription_ratio=1.0,
|
max_over_subscription_ratio=1.0,
|
||||||
thin_provisioning=False)]),
|
thin_provisioning=False,
|
||||||
|
mount_point_name_support=False,
|
||||||
|
)]),
|
||||||
'host6@FFF': dict(share_backend_name='FFF',
|
'host6@FFF': dict(share_backend_name='FFF',
|
||||||
timestamp=None, reserved_percentage=0,
|
timestamp=None, reserved_percentage=0,
|
||||||
reserved_snapshot_percentage=0,
|
reserved_snapshot_percentage=0,
|
||||||
@ -232,7 +249,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
|||||||
reserved_share_extend_percentage=0,
|
reserved_share_extend_percentage=0,
|
||||||
provisioned_capacity_gb=100,
|
provisioned_capacity_gb=100,
|
||||||
max_over_subscription_ratio=1.0,
|
max_over_subscription_ratio=1.0,
|
||||||
thin_provisioning=False),
|
thin_provisioning=False,
|
||||||
|
mount_point_name_support=False,
|
||||||
|
),
|
||||||
dict(pool_name='pool6b',
|
dict(pool_name='pool6b',
|
||||||
total_capacity_gb='unknown',
|
total_capacity_gb='unknown',
|
||||||
free_capacity_gb='unknown',
|
free_capacity_gb='unknown',
|
||||||
@ -241,7 +260,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
|||||||
reserved_share_extend_percentage=0,
|
reserved_share_extend_percentage=0,
|
||||||
provisioned_capacity_gb=100,
|
provisioned_capacity_gb=100,
|
||||||
max_over_subscription_ratio=1.0,
|
max_over_subscription_ratio=1.0,
|
||||||
thin_provisioning=False)]),
|
thin_provisioning=False,
|
||||||
|
mount_point_name_support=False,
|
||||||
|
)]),
|
||||||
}
|
}
|
||||||
|
|
||||||
FAKE_ACTIVE_IQ_WEIGHER_LIST = [
|
FAKE_ACTIVE_IQ_WEIGHER_LIST = [
|
||||||
|
@ -45,6 +45,24 @@ class HostFiltersTestCase(test.TestCase):
|
|||||||
assertion = self.assertTrue if passes else self.assertFalse
|
assertion = self.assertTrue if passes else self.assertFalse
|
||||||
assertion(self.filter.host_passes(host, filter_properties))
|
assertion(self.filter.host_passes(host, filter_properties))
|
||||||
|
|
||||||
|
def test_mount_point_name_support_pass(self):
|
||||||
|
capabilities = {'mount_point_name_support': True}
|
||||||
|
service = {'disabled': False}
|
||||||
|
filter_properties = {
|
||||||
|
'resource_type': {
|
||||||
|
'request_spec': {
|
||||||
|
'share_properties': {
|
||||||
|
'mount_point_name': 'fake_mp',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
host = fakes.FakeHostState('host1',
|
||||||
|
{'free_capacity_gb': 1024,
|
||||||
|
'capabilities': capabilities,
|
||||||
|
'service': service})
|
||||||
|
self.assertTrue(self.filter.host_passes(host, filter_properties))
|
||||||
|
|
||||||
def test_capability_filter_passes_extra_specs_simple(self):
|
def test_capability_filter_passes_extra_specs_simple(self):
|
||||||
self._do_test_type_filter_extra_specs(
|
self._do_test_type_filter_extra_specs(
|
||||||
ecaps={'opt1': '1', 'opt2': '2'},
|
ecaps={'opt1': '1', 'opt2': '2'},
|
||||||
|
@ -217,6 +217,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
'network_allocation_update_support': False,
|
'network_allocation_update_support': False,
|
||||||
'share_server_multiple_subnet_support': False,
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host2@back1#BBB',
|
'name': 'host2@back1#BBB',
|
||||||
@ -250,6 +251,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
'network_allocation_update_support': False,
|
'network_allocation_update_support': False,
|
||||||
'share_server_multiple_subnet_support': False,
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host2@back2#CCC',
|
'name': 'host2@back2#CCC',
|
||||||
@ -283,6 +285,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
'network_allocation_update_support': False,
|
'network_allocation_update_support': False,
|
||||||
'share_server_multiple_subnet_support': False,
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -338,6 +341,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
'network_allocation_update_support': False,
|
'network_allocation_update_support': False,
|
||||||
'share_server_multiple_subnet_support': False,
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host2@BBB#pool2',
|
'name': 'host2@BBB#pool2',
|
||||||
@ -372,6 +376,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
'network_allocation_update_support': False,
|
'network_allocation_update_support': False,
|
||||||
'share_server_multiple_subnet_support': False,
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host3@CCC#pool3',
|
'name': 'host3@CCC#pool3',
|
||||||
@ -406,6 +411,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
'network_allocation_update_support': False,
|
'network_allocation_update_support': False,
|
||||||
'share_server_multiple_subnet_support': False,
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host4@DDD#pool4a',
|
'name': 'host4@DDD#pool4a',
|
||||||
@ -440,6 +446,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
'network_allocation_update_support': False,
|
'network_allocation_update_support': False,
|
||||||
'share_server_multiple_subnet_support': False,
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host4@DDD#pool4b',
|
'name': 'host4@DDD#pool4b',
|
||||||
@ -474,6 +481,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
'network_allocation_update_support': False,
|
'network_allocation_update_support': False,
|
||||||
'share_server_multiple_subnet_support': False,
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -541,6 +549,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
'network_allocation_update_support': False,
|
'network_allocation_update_support': False,
|
||||||
'share_server_multiple_subnet_support': False,
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host2@back1#BBB',
|
'name': 'host2@back1#BBB',
|
||||||
@ -574,6 +583,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
'network_allocation_update_support': False,
|
'network_allocation_update_support': False,
|
||||||
'share_server_multiple_subnet_support': False,
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -635,6 +645,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
'network_allocation_update_support': False,
|
'network_allocation_update_support': False,
|
||||||
'share_server_multiple_subnet_support': False,
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -114,6 +114,8 @@ class ContainerShareDriverTestCase(test.TestCase):
|
|||||||
self.assertEqual('test-pool', self._driver._stats['pools'])
|
self.assertEqual('test-pool', self._driver._stats['pools'])
|
||||||
self.assertTrue(self._driver._stats['ipv4_support'])
|
self.assertTrue(self._driver._stats['ipv4_support'])
|
||||||
self.assertFalse(self._driver._stats['ipv6_support'])
|
self.assertFalse(self._driver._stats['ipv6_support'])
|
||||||
|
self.assertFalse(self._driver.
|
||||||
|
_stats['mount_point_name_support'])
|
||||||
|
|
||||||
def test_create_share(self):
|
def test_create_share(self):
|
||||||
|
|
||||||
|
@ -166,6 +166,7 @@ class EMCShareFrameworkTestCase(test.TestCase):
|
|||||||
data['replication_domain'] = None
|
data['replication_domain'] = None
|
||||||
data['filter_function'] = None
|
data['filter_function'] = None
|
||||||
data['goodness_function'] = None
|
data['goodness_function'] = None
|
||||||
|
data['mount_point_name_support'] = False
|
||||||
data['snapshot_support'] = True
|
data['snapshot_support'] = True
|
||||||
data['create_share_from_snapshot_support'] = True
|
data['create_share_from_snapshot_support'] = True
|
||||||
data['ipv4_support'] = True
|
data['ipv4_support'] = True
|
||||||
|
@ -181,6 +181,9 @@ class DummyDriver(driver.ShareDriver):
|
|||||||
))
|
))
|
||||||
|
|
||||||
def _get_share_name(self, share):
|
def _get_share_name(self, share):
|
||||||
|
mount_point_name = share.get('mount_point_name')
|
||||||
|
if mount_point_name is not None:
|
||||||
|
return mount_point_name
|
||||||
return "share_%(s_id)s_%(si_id)s" % {
|
return "share_%(s_id)s_%(si_id)s" % {
|
||||||
"s_id": share["share_id"].replace("-", "_"),
|
"s_id": share["share_id"].replace("-", "_"),
|
||||||
"si_id": share["id"].replace("-", "_")}
|
"si_id": share["id"].replace("-", "_")}
|
||||||
@ -516,6 +519,7 @@ class DummyDriver(driver.ShareDriver):
|
|||||||
"consistent_snapshot_support": "pool",
|
"consistent_snapshot_support": "pool",
|
||||||
},
|
},
|
||||||
'share_server_multiple_subnet_support': True,
|
'share_server_multiple_subnet_support': True,
|
||||||
|
'mount_point_name_support': True,
|
||||||
}
|
}
|
||||||
if self.configuration.replication_domain:
|
if self.configuration.replication_domain:
|
||||||
data["replication_type"] = "readable"
|
data["replication_type"] = "readable"
|
||||||
|
@ -268,6 +268,7 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'filter_function': None,
|
'filter_function': None,
|
||||||
'goodness_function': None,
|
'goodness_function': None,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'ipv4_support': True,
|
'ipv4_support': True,
|
||||||
'ipv6_support': False,
|
'ipv6_support': False,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
@ -746,6 +746,7 @@ class HPE3ParDriverTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'filter_function': None,
|
'filter_function': None,
|
||||||
'goodness_function': None,
|
'goodness_function': None,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'ipv4_support': True,
|
'ipv4_support': True,
|
||||||
'ipv6_support': False,
|
'ipv6_support': False,
|
||||||
'max_share_server_size': -1,
|
'max_share_server_size': -1,
|
||||||
@ -839,6 +840,7 @@ class HPE3ParDriverTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'filter_function': None,
|
'filter_function': None,
|
||||||
'goodness_function': None,
|
'goodness_function': None,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'ipv4_support': True,
|
'ipv4_support': True,
|
||||||
'ipv6_support': False,
|
'ipv6_support': False,
|
||||||
}
|
}
|
||||||
@ -890,6 +892,7 @@ class HPE3ParDriverTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'filter_function': None,
|
'filter_function': None,
|
||||||
'goodness_function': None,
|
'goodness_function': None,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'ipv4_support': True,
|
'ipv4_support': True,
|
||||||
'ipv6_support': False,
|
'ipv6_support': False,
|
||||||
}
|
}
|
||||||
|
@ -2431,6 +2431,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
"replication_domain": None,
|
"replication_domain": None,
|
||||||
"filter_function": None,
|
"filter_function": None,
|
||||||
"goodness_function": None,
|
"goodness_function": None,
|
||||||
|
'mount_point_name_support': False,
|
||||||
"pools": [],
|
"pools": [],
|
||||||
"share_group_stats": {"consistent_snapshot_support": None},
|
"share_group_stats": {"consistent_snapshot_support": None},
|
||||||
"ipv4_support": True,
|
"ipv4_support": True,
|
||||||
|
@ -186,6 +186,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
|||||||
CONF.lvm_share_volume_group, 0, 0]
|
CONF.lvm_share_volume_group, 0, 0]
|
||||||
self.mock_object(privsep_common, 'execute_with_retries')
|
self.mock_object(privsep_common, 'execute_with_retries')
|
||||||
self.mock_object(filesystem, 'make_filesystem')
|
self.mock_object(filesystem, 'make_filesystem')
|
||||||
|
self.mock_object(self._driver, '_get_mount_point_name',
|
||||||
|
mock.Mock(return_value=self.share['name']))
|
||||||
|
|
||||||
ret = self._driver.create_share(self._context, self.share,
|
ret = self._driver.create_share(self._context, self.share,
|
||||||
self.share_server)
|
self.share_server)
|
||||||
@ -222,6 +224,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
|||||||
self.mock_object(filesystem, 'make_filesystem')
|
self.mock_object(filesystem, 'make_filesystem')
|
||||||
self.mock_object(filesystem, 'e2fsck')
|
self.mock_object(filesystem, 'e2fsck')
|
||||||
self.mock_object(filesystem, 'tune2fs')
|
self.mock_object(filesystem, 'tune2fs')
|
||||||
|
self.mock_object(self._driver, '_get_mount_point_name',
|
||||||
|
mock.Mock(return_value=self.share['name']))
|
||||||
|
|
||||||
self._driver.create_share_from_snapshot(self._context,
|
self._driver.create_share_from_snapshot(self._context,
|
||||||
self.share,
|
self.share,
|
||||||
@ -256,6 +260,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
|||||||
self._driver._mount_device = mock.Mock()
|
self._driver._mount_device = mock.Mock()
|
||||||
self.mock_object(privsep_common, 'execute_with_retries')
|
self.mock_object(privsep_common, 'execute_with_retries')
|
||||||
self.mock_object(filesystem, 'make_filesystem')
|
self.mock_object(filesystem, 'make_filesystem')
|
||||||
|
self.mock_object(self._driver, '_get_mount_point_name',
|
||||||
|
mock.Mock(return_value=self.share['name']))
|
||||||
|
|
||||||
ret = self._driver.create_share(self._context, share,
|
ret = self._driver.create_share(self._context, share,
|
||||||
self.share_server)
|
self.share_server)
|
||||||
@ -402,6 +408,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
def test_ensure_share(self):
|
def test_ensure_share(self):
|
||||||
device_name = '/dev/mapper/fakevg-fakename'
|
device_name = '/dev/mapper/fakevg-fakename'
|
||||||
|
self.mock_object(self._driver, '_get_mount_point_name',
|
||||||
|
mock.Mock(return_value=self.share['name']))
|
||||||
with mock.patch.object(self._driver,
|
with mock.patch.object(self._driver,
|
||||||
'_mount_device',
|
'_mount_device',
|
||||||
mock.Mock(return_value='fake_location')):
|
mock.Mock(return_value='fake_location')):
|
||||||
@ -413,6 +421,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
|||||||
self.server, self.share['name'], recreate=True)
|
self.server, self.share['name'], recreate=True)
|
||||||
|
|
||||||
def test_delete_share(self):
|
def test_delete_share(self):
|
||||||
|
self.mock_object(self._driver, '_get_mount_point_name',
|
||||||
|
mock.Mock(return_value=self.share['name']))
|
||||||
mount_path = self._get_mount_path(self.share)
|
mount_path = self._get_mount_path(self.share)
|
||||||
self._helper_nfs.remove_export(mount_path, self.share['name'])
|
self._helper_nfs.remove_export(mount_path, self.share['name'])
|
||||||
self._driver._delete_share(self._context, self.share)
|
self._driver._delete_share(self._context, self.share)
|
||||||
@ -437,6 +447,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
|||||||
self.mock_object(self._driver, '_deallocate_container')
|
self.mock_object(self._driver, '_deallocate_container')
|
||||||
self._driver._get_helper = mock.Mock(
|
self._driver._get_helper = mock.Mock(
|
||||||
side_effect=exception.InvalidShare(reason='fake'))
|
side_effect=exception.InvalidShare(reason='fake'))
|
||||||
|
self.mock_object(self._driver, '_get_mount_point_name',
|
||||||
|
mock.Mock(return_value=self.share['name']))
|
||||||
|
|
||||||
self._driver.delete_share(self._context, self.share, self.share_server)
|
self._driver.delete_share(self._context, self.share, self.share_server)
|
||||||
|
|
||||||
@ -450,6 +462,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
|||||||
self._helper_nfs,
|
self._helper_nfs,
|
||||||
'remove_export',
|
'remove_export',
|
||||||
mock.Mock(side_effect=exception.ProcessExecutionError))
|
mock.Mock(side_effect=exception.ProcessExecutionError))
|
||||||
|
self.mock_object(self._driver, '_get_mount_point_name',
|
||||||
|
mock.Mock(return_value=self.share['name']))
|
||||||
|
|
||||||
self._driver._delete_share(self._context, self.share)
|
self._driver._delete_share(self._context, self.share)
|
||||||
self._helper_nfs.remove_exports.assert_called_once_with(
|
self._helper_nfs.remove_exports.assert_called_once_with(
|
||||||
@ -464,6 +478,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
|||||||
'2.2.2.2', access_level), ]
|
'2.2.2.2', access_level), ]
|
||||||
delete_rules = [test_generic.get_fake_access_rule(
|
delete_rules = [test_generic.get_fake_access_rule(
|
||||||
'3.3.3.3', access_level), ]
|
'3.3.3.3', access_level), ]
|
||||||
|
self.mock_object(self._driver, '_get_mount_point_name',
|
||||||
|
mock.Mock(return_value=self.share['name']))
|
||||||
self._driver.update_access(self._context, self.share, access_rules,
|
self._driver.update_access(self._context, self.share, access_rules,
|
||||||
add_rules=add_rules,
|
add_rules=add_rules,
|
||||||
delete_rules=delete_rules,
|
delete_rules=delete_rules,
|
||||||
@ -609,6 +625,7 @@ class LVMShareDriverTestCase(test.TestCase):
|
|||||||
'reserved_percentage': 0,
|
'reserved_percentage': 0,
|
||||||
'reserved_snapshot_percentage': 0,
|
'reserved_snapshot_percentage': 0,
|
||||||
'reserved_share_extend_percentage': 0,
|
'reserved_share_extend_percentage': 0,
|
||||||
|
'mount_point_name_support': True,
|
||||||
}, ]
|
}, ]
|
||||||
out, err = "VSize 33g VFree 22g", None
|
out, err = "VSize 33g VFree 22g", None
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
@ -669,6 +686,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
|||||||
mock_get_local_path = self.mock_object(
|
mock_get_local_path = self.mock_object(
|
||||||
self._driver, '_get_local_path',
|
self._driver, '_get_local_path',
|
||||||
mock.Mock(side_effect=[share_local_path, snapshot_local_path]))
|
mock.Mock(side_effect=[share_local_path, snapshot_local_path]))
|
||||||
|
self.mock_object(self._driver, '_get_mount_point_name',
|
||||||
|
mock.Mock(return_value=self.snapshot['name']))
|
||||||
snapshot_parent_share = self.snapshot['share']
|
snapshot_parent_share = self.snapshot['share']
|
||||||
|
|
||||||
self._driver.revert_to_snapshot(self._context, self.snapshot,
|
self._driver.revert_to_snapshot(self._context, self.snapshot,
|
||||||
@ -784,3 +803,28 @@ class LVMShareDriverTestCase(test.TestCase):
|
|||||||
{'export_ips': ','.join(self.server['public_addresses']),
|
{'export_ips': ','.join(self.server['public_addresses']),
|
||||||
'db_version': mock.ANY},
|
'db_version': mock.ANY},
|
||||||
backend_info)
|
backend_info)
|
||||||
|
|
||||||
|
def test_get_mount_point_name_with_mount_point_name(self):
|
||||||
|
share = {'mount_point_name': 'fake_mp_name', 'name': 'fakename'}
|
||||||
|
result = self._driver._get_mount_point_name(share)
|
||||||
|
self.assertEqual(result, 'fake_mp_name')
|
||||||
|
|
||||||
|
def test_get_mount_point_name_without_mount_point_name(self):
|
||||||
|
share = {'name': 'fakename'}
|
||||||
|
result = self._driver._get_mount_point_name(share)
|
||||||
|
self.assertEqual(result, 'fakename')
|
||||||
|
|
||||||
|
def test_get_mount_point_name_with_empty_mount_point_name(self):
|
||||||
|
share = {'mount_point_name': '', 'name': 'fakename'}
|
||||||
|
result = self._driver._get_mount_point_name(share)
|
||||||
|
self.assertEqual(result, 'fakename')
|
||||||
|
|
||||||
|
def test_get_mount_point_name_with_none_mount_point_name(self):
|
||||||
|
share = {'mount_point_name': None, 'name': 'fakename'}
|
||||||
|
result = self._driver._get_mount_point_name(share)
|
||||||
|
self.assertEqual(result, 'fakename')
|
||||||
|
|
||||||
|
def test_get_mount_point_name_without_name(self):
|
||||||
|
share = {'mount_point_name': 'fake_mp_name'}
|
||||||
|
result = self._driver._get_mount_point_name(share)
|
||||||
|
self.assertEqual(result, 'fake_mp_name')
|
||||||
|
@ -438,6 +438,7 @@ class ACCESSShareDriverTestCase(test.TestCase):
|
|||||||
'driver_handles_share_servers': False,
|
'driver_handles_share_servers': False,
|
||||||
'filter_function': 'Disable',
|
'filter_function': 'Disable',
|
||||||
'goodness_function': 'Disable',
|
'goodness_function': 'Disable',
|
||||||
|
'mount_point_name_support': False,
|
||||||
'ipv4_support': True,
|
'ipv4_support': True,
|
||||||
'ipv6_support': False,
|
'ipv6_support': False,
|
||||||
'mount_snapshot_support': False,
|
'mount_snapshot_support': False,
|
||||||
|
@ -376,6 +376,7 @@ class ZFSonLinuxShareDriverTestCase(test.TestCase):
|
|||||||
'vendor_name': 'Open Source',
|
'vendor_name': 'Open Source',
|
||||||
'filter_function': None,
|
'filter_function': None,
|
||||||
'goodness_function': None,
|
'goodness_function': None,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'ipv4_support': True,
|
'ipv4_support': True,
|
||||||
'ipv6_support': False,
|
'ipv6_support': False,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
@ -166,7 +166,10 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
share_instance = db_utils.create_share_instance(
|
share_instance = db_utils.create_share_instance(
|
||||||
share_id=share['id'],
|
share_id=share['id'],
|
||||||
share_type_id=share_type_id)
|
share_type_id=share_type_id)
|
||||||
share_type = {'fake': 'fake'}
|
share_type = {
|
||||||
|
'fake': 'fake',
|
||||||
|
'mount_point_name_support': False
|
||||||
|
}
|
||||||
self.mock_object(db_api, 'share_instance_create',
|
self.mock_object(db_api, 'share_instance_create',
|
||||||
mock.Mock(return_value=share_instance))
|
mock.Mock(return_value=share_instance))
|
||||||
self.mock_object(db_api, 'share_type_get',
|
self.mock_object(db_api, 'share_type_get',
|
||||||
@ -801,7 +804,7 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
availability_zones=expected_azs,
|
availability_zones=expected_azs,
|
||||||
az_request_multiple_subnet_support_map=compatible_azs_multiple,
|
az_request_multiple_subnet_support_map=compatible_azs_multiple,
|
||||||
snapshot_host=None,
|
snapshot_host=None,
|
||||||
scheduler_hints=None
|
scheduler_hints=None, mount_point_name=None,
|
||||||
)
|
)
|
||||||
db_api.share_get.assert_called_once()
|
db_api.share_get.assert_called_once()
|
||||||
|
|
||||||
@ -840,6 +843,85 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
get_all_azs_sns.assert_called_once_with(
|
get_all_azs_sns.assert_called_once_with(
|
||||||
self.context, fake_share_network_id)
|
self.context, fake_share_network_id)
|
||||||
|
|
||||||
|
def test_prefix_with_missing_extra_spec_mount_point_name_support(self):
|
||||||
|
share, share_data = self._setup_create_mocks(is_public=True)
|
||||||
|
az = share_data.pop('availability_zone')
|
||||||
|
extra_specs = {'replication_type': 'readable',
|
||||||
|
'mount_point_name_support': False}
|
||||||
|
self.mock_object(
|
||||||
|
self.api, 'get_share_attributes_from_share_type',
|
||||||
|
mock.Mock(return_value=extra_specs))
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exception.InvalidInput,
|
||||||
|
self.api.create,
|
||||||
|
self.context, share_data['share_proto'], share_data['size'],
|
||||||
|
share_data['display_name'], share_data['display_description'],
|
||||||
|
availability_zones=az,
|
||||||
|
mount_point_name='fake_mp')
|
||||||
|
|
||||||
|
def test_prefix_with_valid_mount_point_name(self):
|
||||||
|
share_type = {
|
||||||
|
'extra_specs': {
|
||||||
|
constants.ExtraSpecs.PROVISIONING_MOUNT_POINT_PREFIX: 'prefix',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.context.project_id = 'project_id'
|
||||||
|
mount_point_name = 'mount_point'
|
||||||
|
result = self.api._prefix_mount_point_name(
|
||||||
|
share_type, self.context, mount_point_name
|
||||||
|
)
|
||||||
|
self.assertEqual(result, 'prefix_mount_point')
|
||||||
|
|
||||||
|
def test_prefix_with_valid_missing_extra_spec_mount_point_name(self):
|
||||||
|
share_type = {
|
||||||
|
'extra_specs': {},
|
||||||
|
}
|
||||||
|
self.context.project_id = 'project_id'
|
||||||
|
mount_point_name = 'mount_point'
|
||||||
|
result = self.api._prefix_mount_point_name(
|
||||||
|
share_type, self.context, mount_point_name
|
||||||
|
)
|
||||||
|
self.assertEqual(result, 'project_id_mount_point')
|
||||||
|
|
||||||
|
def test_prefix_with_invalid_mount_point_name(self):
|
||||||
|
share_type = \
|
||||||
|
{
|
||||||
|
'extra_specs':
|
||||||
|
{
|
||||||
|
constants.ExtraSpecs.PROVISIONING_MOUNT_POINT_PREFIX:
|
||||||
|
'prefix',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.context.project_id = 'project_id'
|
||||||
|
mount_point_name = 'invalid*name'
|
||||||
|
self.assertRaises(
|
||||||
|
exception.InvalidInput,
|
||||||
|
self.api._prefix_mount_point_name,
|
||||||
|
share_type,
|
||||||
|
self.context,
|
||||||
|
mount_point_name
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_prefix_with_too_long_mount_point_name(self):
|
||||||
|
share_type = \
|
||||||
|
{
|
||||||
|
'extra_specs':
|
||||||
|
{
|
||||||
|
constants.ExtraSpecs.PROVISIONING_MOUNT_POINT_PREFIX:
|
||||||
|
'prefix',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.context.project_id = 'project_id'
|
||||||
|
mount_point_name = 'a' * 256
|
||||||
|
self.assertRaises(
|
||||||
|
exception.InvalidInput,
|
||||||
|
self.api._prefix_mount_point_name,
|
||||||
|
share_type,
|
||||||
|
self.context,
|
||||||
|
mount_point_name
|
||||||
|
)
|
||||||
|
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
None, '', 'fake', 'nfsfake', 'cifsfake', 'glusterfsfake', 'hdfsfake')
|
None, '', 'fake', 'nfsfake', 'cifsfake', 'glusterfsfake', 'hdfsfake')
|
||||||
def test_create_share_invalid_protocol(self, proto):
|
def test_create_share_invalid_protocol(self, proto):
|
||||||
@ -984,6 +1066,7 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
'availability_zone_id': 'fake_id',
|
'availability_zone_id': 'fake_id',
|
||||||
'share_type_id': 'fake_share_type',
|
'share_type_id': 'fake_share_type',
|
||||||
'cast_rules_to_readonly': False,
|
'cast_rules_to_readonly': False,
|
||||||
|
'mount_point_name': None,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
db_api.share_type_get.assert_called_once_with(
|
db_api.share_type_get.assert_called_once_with(
|
||||||
@ -999,6 +1082,28 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
self.api.scheduler_rpcapi.create_share_instance.called)
|
self.api.scheduler_rpcapi.create_share_instance.called)
|
||||||
|
|
||||||
|
def test_create_share_instance_with_mount_point_name(self):
|
||||||
|
host, share, share_instance = self._setup_create_instance_mocks()
|
||||||
|
|
||||||
|
self.api.create_instance(self.context, share, host=host,
|
||||||
|
availability_zone='fake',
|
||||||
|
share_type_id='fake_share_type',
|
||||||
|
mount_point_name='fake_mp')
|
||||||
|
|
||||||
|
db_api.share_instance_create.assert_called_once_with(
|
||||||
|
self.context, share['id'],
|
||||||
|
{
|
||||||
|
'share_network_id': None,
|
||||||
|
'status': constants.STATUS_CREATING,
|
||||||
|
'scheduled_at': self.dt_utc,
|
||||||
|
'host': host,
|
||||||
|
'availability_zone_id': 'fake_id',
|
||||||
|
'share_type_id': 'fake_share_type',
|
||||||
|
'cast_rules_to_readonly': False,
|
||||||
|
'mount_point_name': 'fake_mp',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def test_create_share_instance_without_host(self):
|
def test_create_share_instance_without_host(self):
|
||||||
_, share, share_instance = self._setup_create_instance_mocks()
|
_, share, share_instance = self._setup_create_instance_mocks()
|
||||||
|
|
||||||
@ -1072,6 +1177,7 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
'create_share_from_snapshot_support': False,
|
'create_share_from_snapshot_support': False,
|
||||||
'revert_to_snapshot_support': False,
|
'revert_to_snapshot_support': False,
|
||||||
'mount_snapshot_support': False,
|
'mount_snapshot_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'replication_type': 'dr',
|
'replication_type': 'dr',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1090,6 +1196,7 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
'create_share_from_snapshot_support': False,
|
'create_share_from_snapshot_support': False,
|
||||||
'revert_to_snapshot_support': False,
|
'revert_to_snapshot_support': False,
|
||||||
'mount_snapshot_support': False,
|
'mount_snapshot_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'replication_type': None,
|
'replication_type': None,
|
||||||
}
|
}
|
||||||
self.assertEqual(expected, result)
|
self.assertEqual(expected, result)
|
||||||
@ -1140,6 +1247,7 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
'create_share_from_snapshot_support': False,
|
'create_share_from_snapshot_support': False,
|
||||||
'revert_to_snapshot_support': False,
|
'revert_to_snapshot_support': False,
|
||||||
'mount_snapshot_support': False,
|
'mount_snapshot_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'driver_handles_share_servers': dhss,
|
'driver_handles_share_servers': dhss,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1176,6 +1284,8 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
fake_type['extra_specs']['revert_to_snapshot_support'],
|
fake_type['extra_specs']['revert_to_snapshot_support'],
|
||||||
'mount_snapshot_support':
|
'mount_snapshot_support':
|
||||||
fake_type['extra_specs']['mount_snapshot_support'],
|
fake_type['extra_specs']['mount_snapshot_support'],
|
||||||
|
'mount_point_name_support':
|
||||||
|
fake_type['extra_specs']['mount_point_name_support'],
|
||||||
'replication_type': replication_type,
|
'replication_type': replication_type,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1231,6 +1341,7 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
'create_share_from_snapshot_support': False,
|
'create_share_from_snapshot_support': False,
|
||||||
'revert_to_snapshot_support': False,
|
'revert_to_snapshot_support': False,
|
||||||
'mount_snapshot_support': False,
|
'mount_snapshot_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'driver_handles_share_servers': dhss,
|
'driver_handles_share_servers': dhss,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1278,6 +1389,7 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
'create_share_from_snapshot_support': False,
|
'create_share_from_snapshot_support': False,
|
||||||
'revert_to_snapshot_support': False,
|
'revert_to_snapshot_support': False,
|
||||||
'mount_snapshot_support': False,
|
'mount_snapshot_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'driver_handles_share_servers': True,
|
'driver_handles_share_servers': True,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1329,6 +1441,7 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
'create_share_from_snapshot_support': False,
|
'create_share_from_snapshot_support': False,
|
||||||
'revert_to_snapshot_support': False,
|
'revert_to_snapshot_support': False,
|
||||||
'mount_snapshot_support': False,
|
'mount_snapshot_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'driver_handles_share_servers': True,
|
'driver_handles_share_servers': True,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1412,6 +1525,9 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
'mount_snapshot_support': kwargs.get(
|
'mount_snapshot_support': kwargs.get(
|
||||||
'mount_snapshot_support',
|
'mount_snapshot_support',
|
||||||
share_type['extra_specs'].get('mount_snapshot_support')),
|
share_type['extra_specs'].get('mount_snapshot_support')),
|
||||||
|
'mount_point_name_support': kwargs.get(
|
||||||
|
'mount_point_name_support',
|
||||||
|
share_type['extra_specs'].get('mount_point_name_support')),
|
||||||
'share_proto': kwargs.get('share_proto', share.get('share_proto')),
|
'share_proto': kwargs.get('share_proto', share.get('share_proto')),
|
||||||
'share_type_id': share_type['id'],
|
'share_type_id': share_type['id'],
|
||||||
'is_public': kwargs.get('is_public', share.get('is_public')),
|
'is_public': kwargs.get('is_public', share.get('is_public')),
|
||||||
@ -2356,7 +2472,7 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
availability_zones=None,
|
availability_zones=None,
|
||||||
az_request_multiple_subnet_support_map=None,
|
az_request_multiple_subnet_support_map=None,
|
||||||
snapshot_host=snapshot['share']['instance']['host'],
|
snapshot_host=snapshot['share']['instance']['host'],
|
||||||
scheduler_hints=None)
|
scheduler_hints=None, mount_point_name=None)
|
||||||
share_api.policy.check_policy.assert_called_once_with(
|
share_api.policy.check_policy.assert_called_once_with(
|
||||||
self.context, 'share_snapshot', 'get_snapshot')
|
self.context, 'share_snapshot', 'get_snapshot')
|
||||||
quota.QUOTAS.reserve.assert_called_once_with(
|
quota.QUOTAS.reserve.assert_called_once_with(
|
||||||
@ -3508,6 +3624,7 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
'create_share_from_snapshot_support': False,
|
'create_share_from_snapshot_support': False,
|
||||||
'revert_to_snapshot_support': False,
|
'revert_to_snapshot_support': False,
|
||||||
'mount_snapshot_support': False,
|
'mount_snapshot_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'driver_handles_share_servers': dhss,
|
'driver_handles_share_servers': dhss,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -3520,6 +3637,7 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
'create_share_from_snapshot_support': False,
|
'create_share_from_snapshot_support': False,
|
||||||
'revert_to_snapshot_support': False,
|
'revert_to_snapshot_support': False,
|
||||||
'mount_snapshot_support': False,
|
'mount_snapshot_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'driver_handles_share_servers': dhss,
|
'driver_handles_share_servers': dhss,
|
||||||
'availability_zones': 'fake_az1,fake_az2',
|
'availability_zones': 'fake_az1,fake_az2',
|
||||||
},
|
},
|
||||||
@ -3603,6 +3721,7 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
'create_share_from_snapshot_support': False,
|
'create_share_from_snapshot_support': False,
|
||||||
'revert_to_snapshot_support': False,
|
'revert_to_snapshot_support': False,
|
||||||
'mount_snapshot_support': False,
|
'mount_snapshot_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'driver_handles_share_servers': 'true',
|
'driver_handles_share_servers': 'true',
|
||||||
'availability_zones': 'fake_az3'
|
'availability_zones': 'fake_az3'
|
||||||
},
|
},
|
||||||
@ -3615,6 +3734,7 @@ class ShareAPITestCase(test.TestCase):
|
|||||||
'create_share_from_snapshot_support': False,
|
'create_share_from_snapshot_support': False,
|
||||||
'revert_to_snapshot_support': False,
|
'revert_to_snapshot_support': False,
|
||||||
'mount_snapshot_support': False,
|
'mount_snapshot_support': False,
|
||||||
|
'mount_point_name_support': False,
|
||||||
'driver_handles_share_servers': 'true',
|
'driver_handles_share_servers': 'true',
|
||||||
'availability_zones': 'fake_az1,fake_az2',
|
'availability_zones': 'fake_az1,fake_az2',
|
||||||
},
|
},
|
||||||
|
@ -144,6 +144,7 @@ class ShareDriverTestCase(test.TestCase):
|
|||||||
'reserved_share_extend_percentage',
|
'reserved_share_extend_percentage',
|
||||||
'vendor_name', 'storage_protocol',
|
'vendor_name', 'storage_protocol',
|
||||||
'snapshot_support', 'mount_snapshot_support',
|
'snapshot_support', 'mount_snapshot_support',
|
||||||
|
'mount_point_name_support',
|
||||||
]
|
]
|
||||||
share_driver = driver.ShareDriver(True, configuration=conf)
|
share_driver = driver.ShareDriver(True, configuration=conf)
|
||||||
fake_stats = {'fake_key': 'fake_value'}
|
fake_stats = {'fake_key': 'fake_value'}
|
||||||
|
@ -406,14 +406,18 @@ class ShareTypesTestCase(test.TestCase):
|
|||||||
(constants.ExtraSpecs.SNAPSHOT_SUPPORT,
|
(constants.ExtraSpecs.SNAPSHOT_SUPPORT,
|
||||||
constants.ExtraSpecs.CREATE_SHARE_FROM_SNAPSHOT_SUPPORT,
|
constants.ExtraSpecs.CREATE_SHARE_FROM_SNAPSHOT_SUPPORT,
|
||||||
constants.ExtraSpecs.REVERT_TO_SNAPSHOT_SUPPORT,
|
constants.ExtraSpecs.REVERT_TO_SNAPSHOT_SUPPORT,
|
||||||
constants.ExtraSpecs.MOUNT_SNAPSHOT_SUPPORT),
|
constants.ExtraSpecs.MOUNT_SNAPSHOT_SUPPORT,
|
||||||
|
constants.ExtraSpecs.MOUNT_POINT_NAME_SUPPORT),
|
||||||
strutils.TRUE_STRINGS + strutils.FALSE_STRINGS)) +
|
strutils.TRUE_STRINGS + strutils.FALSE_STRINGS)) +
|
||||||
list(itertools.product(
|
list(itertools.product(
|
||||||
(constants.ExtraSpecs.REPLICATION_TYPE_SPEC,),
|
(constants.ExtraSpecs.REPLICATION_TYPE_SPEC,),
|
||||||
constants.ExtraSpecs.REPLICATION_TYPES)) +
|
constants.ExtraSpecs.REPLICATION_TYPES)) +
|
||||||
[(constants.ExtraSpecs.AVAILABILITY_ZONES, 'zone a, zoneb$c'),
|
[(constants.ExtraSpecs.AVAILABILITY_ZONES, 'zone a, zoneb$c'),
|
||||||
(constants.ExtraSpecs.AVAILABILITY_ZONES, ' zonea, zoneb'),
|
(constants.ExtraSpecs.AVAILABILITY_ZONES, ' zonea, zoneb'),
|
||||||
(constants.ExtraSpecs.AVAILABILITY_ZONES, 'zone1')]
|
(constants.ExtraSpecs.AVAILABILITY_ZONES, 'zone1')] +
|
||||||
|
[(constants.ExtraSpecs.PROVISIONING_MOUNT_POINT_PREFIX, 'gold'),
|
||||||
|
(constants.ExtraSpecs.PROVISIONING_MOUNT_POINT_PREFIX, 'silver'),
|
||||||
|
(constants.ExtraSpecs.PROVISIONING_MOUNT_POINT_PREFIX, 'bronze')]
|
||||||
))
|
))
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_is_valid_optional_extra_spec_valid(self, key, value):
|
def test_is_valid_optional_extra_spec_valid(self, key, value):
|
||||||
@ -422,6 +426,18 @@ class ShareTypesTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
|
|
||||||
|
def test_valid_string(self):
|
||||||
|
self.assertTrue(share_types.is_valid_string("This is a valid string"))
|
||||||
|
|
||||||
|
def test_empty_string(self):
|
||||||
|
self.assertFalse(share_types.is_valid_string(""))
|
||||||
|
|
||||||
|
def test_string_too_long(self):
|
||||||
|
self.assertFalse(share_types.is_valid_string("a" * 256))
|
||||||
|
|
||||||
|
def test_non_string_input(self):
|
||||||
|
self.assertFalse(share_types.is_valid_string(123))
|
||||||
|
|
||||||
def test_is_valid_optional_extra_spec_valid_unknown_key(self):
|
def test_is_valid_optional_extra_spec_valid_unknown_key(self):
|
||||||
|
|
||||||
result = share_types.is_valid_optional_extra_spec('fake', 'fake')
|
result = share_types.is_valid_optional_extra_spec('fake', 'fake')
|
||||||
|
@ -168,6 +168,17 @@ class API(base.Base):
|
|||||||
policy.check_policy(context, "share_transfer", "create",
|
policy.check_policy(context, "share_transfer", "create",
|
||||||
target_obj=share_ref)
|
target_obj=share_ref)
|
||||||
share_instance = share_ref['instance']
|
share_instance = share_ref['instance']
|
||||||
|
|
||||||
|
mount_point_name = share_instance['mount_point_name']
|
||||||
|
if (mount_point_name and
|
||||||
|
mount_point_name.startswith(share_ref['project_id'])):
|
||||||
|
msg = _('Share %s has a custom mount_point_name %s.'
|
||||||
|
' This has the project_id encoded in it.'
|
||||||
|
' Transferring such'
|
||||||
|
' a share isn\'t supported') % (share_ref['name'],
|
||||||
|
mount_point_name)
|
||||||
|
raise exception.Invalid(reason=msg)
|
||||||
|
|
||||||
if share_ref['status'] != "available":
|
if share_ref['status'] != "available":
|
||||||
raise exception.InvalidShare(reason=_("Share's status must be "
|
raise exception.InvalidShare(reason=_("Share's status must be "
|
||||||
"available"))
|
"available"))
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- A human readable ``mount_point_name`` can now be specified
|
||||||
|
while creating shares through the mount_point_name parameter.
|
||||||
|
Manila will prepend a prefix to the mount point name which
|
||||||
|
can be configured through the ``provisioning:mount_point_prefix``
|
||||||
|
share type extra spec. In case this extra spec is not available
|
||||||
|
in the share type, Manila will prepend a project identification
|
||||||
|
to the mount point name. Project id will be added to this friendly
|
||||||
|
name ``provisioning:mount_point_prefix`` share type is not
|
||||||
|
provided during provisioning. The LVM driver now supports
|
||||||
|
human readable export locations.
|
Loading…
Reference in New Issue
Block a user