Merge "Human readable export location core implementation"
This commit is contained in:
commit
a230ea511e
@ -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…
x
Reference in New Issue
Block a user