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
|
||||
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:
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
@ -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
|
||||
is ignored for regular users and the "provisioning:max_share_size" is the
|
||||
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`
|
||||
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| 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 |
|
||||
+========================================+===========+============+========+=============+===================+====================+=====+============================+====================+====================+==============+==============+=========================+
|
||||
| ZFSonLinux | \- | M | M | M | M | \- | \- | M | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Container | N | \- | \- | \- | \- | N | \- | \- | \- | \- | P | \- | Y |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| 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 | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Dell EMC PowerMax | O | \- | \- | \- | \- | \- | \- | O | \- | \- | P | R | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| EMC VNX | J | \- | \- | \- | \- | L | \- | J | \- | \- | P | Q | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| EMC Unity | N | T | \- | \- | N | \- | \- | N | S | \- | P | Q | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| EMC Isilon | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Dell EMC PowerStore | \- | B | \- | \- | B | \- | \- | B | B | \- | B | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Dell EMC PowerFlex | \- | B | \- | \- | B | \- | \- | \- | \- | \- | B | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| GlusterFS | \- | J | \- | \- | \- | L | \- | volume layout (L) | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| GlusterFS-Native | \- | J | \- | \- | \- | L | \- | L | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| HDFS | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Hitachi HNAS | \- | L | N | \- | L | \- | \- | L | O | O | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Hitachi HSP | \- | N | \- | \- | N | \- | \- | \- | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| HPE 3PAR | L | K | L | \- | L | L | \- | K | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Huawei | M | K | L | L | L | L | M | M | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| INFINIDAT | \- | Q | \- | \- | Q | Q | \- | Q | Q | Q | Q | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Infortrend | \- | T | \- | \- | \- | \- | \- | \- | \- | \- | T | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| LVM | \- | M | \- | \- | \- | M | \- | K | O | O | P | P | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Macrosan | \- | Z | \- | \- | \- | Z | \- | \- | \- | \- | Z | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Quobyte | \- | K | \- | \- | \- | L | \- | M | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Windows SMB | L | L | \- | \- | \- | L | \- | \- | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| IBM GPFS | \- | K | \- | \- | \- | L | \- | L | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Oracle ZFSSA | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| CephFS | \- | M | \- | \- | \- | M | \- | \- | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Tegile | \- | M | M | M | M | \- | \- | M | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| NexentaStor4 | \- | N | N | N | N | N | \- | N | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| NexentaStor5 | \- | N | \- | N | N | N | \- | N | T | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| MapRFS | \- | N | \- | \- | \- | N | \- | O | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| QNAP | \- | O | Q | Q | O | Q | \- | O | \- | \- | P | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| INSPUR AS13000 | \- | R | \- | \- | R | \- | \- | R | \- | \- | R | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| INSPUR InStorage | \- | T | \- | \- | \- | T | \- | \- | \- | \- | T | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
| Pure Storage FlashBlade | \- | X | \- | \- | X | \- | \- | \- | X | \- | X | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| 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 | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Container | N | \- | \- | \- | \- | N | \- | \- | \- | \- | P | \- | Y | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| 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 | \- | Y |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Dell EMC PowerMax | O | \- | \- | \- | \- | \- | \- | O | \- | \- | P | R | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| EMC VNX | J | \- | \- | \- | \- | L | \- | J | \- | \- | P | Q | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| EMC Unity | N | T | \- | \- | N | \- | \- | N | S | \- | P | Q | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| EMC Isilon | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Dell EMC PowerStore | \- | B | \- | \- | B | \- | \- | B | B | \- | B | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Dell EMC PowerFlex | \- | B | \- | \- | B | \- | \- | \- | \- | \- | B | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| GlusterFS | \- | J | \- | \- | \- | L | \- | volume layout (L) | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| GlusterFS-Native | \- | J | \- | \- | \- | L | \- | L | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| HDFS | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Hitachi HNAS | \- | L | N | \- | L | \- | \- | L | O | O | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Hitachi HSP | \- | N | \- | \- | N | \- | \- | \- | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| HPE 3PAR | L | K | L | \- | L | L | \- | K | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Huawei | M | K | L | L | L | L | M | M | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| INFINIDAT | \- | Q | \- | \- | Q | Q | \- | Q | Q | Q | Q | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Infortrend | \- | T | \- | \- | \- | \- | \- | \- | \- | \- | T | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| LVM | \- | M | \- | \- | \- | M | \- | K | O | O | P | P | \- | Y |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Macrosan | \- | Z | \- | \- | \- | Z | \- | \- | \- | \- | Z | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Quobyte | \- | K | \- | \- | \- | L | \- | M | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Windows SMB | L | L | \- | \- | \- | L | \- | \- | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| IBM GPFS | \- | K | \- | \- | \- | L | \- | L | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Oracle ZFSSA | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| CephFS | \- | M | \- | \- | \- | M | \- | \- | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Tegile | \- | M | M | M | M | \- | \- | M | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| NexentaStor4 | \- | N | N | N | N | N | \- | N | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| NexentaStor5 | \- | N | \- | N | N | N | \- | N | T | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| MapRFS | \- | N | \- | \- | \- | N | \- | O | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| QNAP | \- | O | Q | Q | O | Q | \- | O | \- | \- | P | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| INSPUR AS13000 | \- | R | \- | \- | R | \- | \- | R | \- | \- | R | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| INSPUR InStorage | \- | T | \- | \- | \- | T | \- | \- | \- | \- | T | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
| Pure Storage FlashBlade | \- | X | \- | \- | X | \- | \- | \- | X | \- | X | \- | \- | \- |
|
||||
+----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+-------------------------+--------------------------+
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -201,13 +201,14 @@ REST_API_VERSION_HISTORY = """
|
||||
* 2.81 - Added API methods, endpoint /resource-locks.
|
||||
* 2.82 - Added lock and restriction to share access rules.
|
||||
* 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 default api version request is defined to be the
|
||||
# minimum version of the API supported.
|
||||
_MIN_API_VERSION = "2.0"
|
||||
_MAX_API_VERSION = "2.83"
|
||||
_MAX_API_VERSION = "2.84"
|
||||
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 user disabled the service. ``disabled`` field will be replaced by
|
||||
``status`` field.
|
||||
|
||||
2.84
|
||||
----
|
||||
Added optional ``mount_point_name`` field to share.
|
||||
|
@ -25,6 +25,7 @@ import webob
|
||||
from webob import exc
|
||||
|
||||
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.views import share_accesses as share_access_views
|
||||
from manila.api.views import shares as share_views
|
||||
@ -445,6 +446,9 @@ class ShareMixin(object):
|
||||
|
||||
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,
|
||||
share_proto,
|
||||
size,
|
||||
|
@ -300,10 +300,12 @@ class ExtraSpecs(object):
|
||||
CREATE_SHARE_FROM_SNAPSHOT_SUPPORT = "create_share_from_snapshot_support"
|
||||
REVERT_TO_SNAPSHOT_SUPPORT = "revert_to_snapshot_support"
|
||||
MOUNT_SNAPSHOT_SUPPORT = "mount_snapshot_support"
|
||||
MOUNT_POINT_NAME_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 = "provisioning:mount_point_prefix"
|
||||
|
||||
# Extra specs containers
|
||||
REQUIRED = (
|
||||
@ -316,10 +318,12 @@ class ExtraSpecs(object):
|
||||
REVERT_TO_SNAPSHOT_SUPPORT,
|
||||
REPLICATION_TYPE_SPEC,
|
||||
MOUNT_SNAPSHOT_SUPPORT,
|
||||
MOUNT_POINT_NAME_SUPPORT,
|
||||
AVAILABILITY_ZONES,
|
||||
PROVISIONING_MAX_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
|
||||
|
@ -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',
|
||||
'share_server_id', 'share_network_id', 'availability_zone_id',
|
||||
'replica_state', 'share_type_id', 'share_type', 'access_rules_status',
|
||||
'mount_point_name',
|
||||
]
|
||||
share_instance_values, share_values = (
|
||||
_extract_subdict_by_fields(values, share_instance_model_fields)
|
||||
|
@ -371,7 +371,7 @@ class ShareInstance(BASE, ManilaBase):
|
||||
host = Column(String(255))
|
||||
status = Column(String(255))
|
||||
progress = Column(String(32))
|
||||
|
||||
mount_point_name = Column(String(255))
|
||||
ACCESS_STATUS_PRIORITIES = {
|
||||
constants.STATUS_ACTIVE: 0,
|
||||
constants.SHARE_INSTANCE_RULES_SYNCING: 1,
|
||||
|
@ -39,6 +39,7 @@ class CapabilitiesFilter(base_host.BaseHostFilter):
|
||||
def host_passes(self, host_state, filter_properties):
|
||||
"""Return a list of hosts that can create resource_type."""
|
||||
resource_type = filter_properties.get('resource_type')
|
||||
|
||||
if not self._satisfies_extra_specs(host_state.capabilities,
|
||||
resource_type):
|
||||
LOG.debug("%(host_state)s fails resource_type extra_specs "
|
||||
|
@ -162,6 +162,7 @@ class HostState(object):
|
||||
self.security_service_update_support = False
|
||||
self.network_allocation_update_support = False
|
||||
self.share_server_multiple_subnet_support = False
|
||||
self.mount_point_name_support = False
|
||||
|
||||
# PoolState for all pools
|
||||
self.pools = {}
|
||||
|
@ -66,7 +66,9 @@ def generate_stats(host_state, properties):
|
||||
'network_allocation_update_support': (
|
||||
host_state.network_allocation_update_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
|
||||
|
@ -21,6 +21,7 @@ Handles all requests relating to shares.
|
||||
"""
|
||||
import functools
|
||||
import json
|
||||
import re
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
@ -270,7 +271,8 @@ class API(base.Base):
|
||||
share_network_id=None, share_type=None, is_public=False,
|
||||
share_group_id=None, share_group_snapshot_member=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."""
|
||||
|
||||
api_common.check_metadata_properties(metadata)
|
||||
@ -348,6 +350,18 @@ class API(base.Base):
|
||||
deltas = {'shares': 1, 'gigabytes': size}
|
||||
share_type_attributes = self.get_share_attributes_from_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(
|
||||
'replication_type', None)
|
||||
if share_type_supports_replication:
|
||||
@ -482,7 +496,8 @@ class API(base.Base):
|
||||
share_type_id=share_type_id, availability_zones=availability_zones,
|
||||
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),
|
||||
mount_point_name=mount_point_name)
|
||||
|
||||
# Retrieve the share with instance details
|
||||
share = self.db.share_get(context, share['id'])
|
||||
@ -505,6 +520,9 @@ class API(base.Base):
|
||||
constants.ExtraSpecs.REVERT_TO_SNAPSHOT_SUPPORT)
|
||||
mount_snapshot_support_key = (
|
||||
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)
|
||||
create_share_from_snapshot_support_default = inferred_map.get(
|
||||
@ -513,6 +531,7 @@ class API(base.Base):
|
||||
revert_to_snapshot_key)
|
||||
mount_snapshot_support_default = inferred_map.get(
|
||||
constants.ExtraSpecs.MOUNT_SNAPSHOT_SUPPORT)
|
||||
mount_point_name_support_default = False
|
||||
|
||||
if share_type:
|
||||
snapshot_support = share_types.parse_boolean_extra_spec(
|
||||
@ -536,6 +555,11 @@ class API(base.Base):
|
||||
'extra_specs', {}).get(
|
||||
mount_snapshot_support_key,
|
||||
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')
|
||||
else:
|
||||
@ -544,6 +568,7 @@ class API(base.Base):
|
||||
create_share_from_snapshot_support_default)
|
||||
revert_to_snapshot_support = revert_to_snapshot_support_default
|
||||
mount_snapshot_support = mount_snapshot_support_default
|
||||
mount_point_name_support = mount_point_name_support_default
|
||||
replication_type = None
|
||||
|
||||
return {
|
||||
@ -553,6 +578,7 @@ class API(base.Base):
|
||||
'revert_to_snapshot_support': revert_to_snapshot_support,
|
||||
'replication_type': replication_type,
|
||||
'mount_snapshot_support': mount_snapshot_support,
|
||||
'mount_point_name_support': mount_point_name_support,
|
||||
}
|
||||
|
||||
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_type_id=None, availability_zones=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 = (
|
||||
self.create_share_instance_and_get_request_spec(
|
||||
context, share, availability_zone=availability_zone,
|
||||
@ -570,7 +597,8 @@ class API(base.Base):
|
||||
availability_zones=availability_zones,
|
||||
snapshot_host=snapshot_host,
|
||||
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:
|
||||
# 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_type_id=None, cast_rules_to_readonly=False,
|
||||
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
|
||||
if availability_zone:
|
||||
@ -633,6 +662,7 @@ class API(base.Base):
|
||||
'availability_zone_id': availability_zone_id,
|
||||
'share_type_id': share_type_id,
|
||||
'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'],
|
||||
'status': share_instance['status'],
|
||||
'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
|
||||
@ -686,7 +716,7 @@ class API(base.Base):
|
||||
'availability_zone_id': availability_zone_id,
|
||||
'availability_zones': availability_zones,
|
||||
'az_request_multiple_subnet_support_map': (
|
||||
az_request_multiple_subnet_support_map),
|
||||
az_request_multiple_subnet_support_map)
|
||||
}
|
||||
return request_spec, share_instance
|
||||
|
||||
@ -1063,6 +1093,11 @@ class API(base.Base):
|
||||
share_type.get('extra_specs', {}).get(
|
||||
'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_type_id': share_type['id'],
|
||||
'is_public': kwargs.get('is_public', share.get('is_public')),
|
||||
@ -1094,6 +1129,25 @@ class API(base.Base):
|
||||
}
|
||||
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')
|
||||
def unmanage(self, context, share):
|
||||
policy.check_policy(context, 'share', 'unmanage')
|
||||
|
@ -1356,6 +1356,7 @@ class ShareDriver(object):
|
||||
network_allocation_update_support=(
|
||||
self.network_allocation_update_support),
|
||||
share_server_multiple_subnet_support=False,
|
||||
mount_point_name_support=False,
|
||||
)
|
||||
if isinstance(data, dict):
|
||||
common.update(data)
|
||||
|
@ -137,6 +137,7 @@ class ContainerShareDriver(driver.ShareDriver, driver.ExecuteMixin):
|
||||
'pools': self.storage.get_share_server_pools(),
|
||||
'security_service_update_support': True,
|
||||
'share_server_multiple_subnet_support': True,
|
||||
'mount_point_name_support': False,
|
||||
}
|
||||
super(ContainerShareDriver, self)._update_share_stats(data)
|
||||
|
||||
|
@ -116,6 +116,9 @@ class LVMMixin(driver.ExecuteMixin):
|
||||
except processutils.ProcessExecutionError:
|
||||
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):
|
||||
privsep_common.execute_with_retries(
|
||||
privsep_lvm.lvextend, [device_name, size],
|
||||
@ -267,14 +270,16 @@ class LVMShareDriver(LVMMixin, driver.ShareDriver):
|
||||
'reserved_percentage': 0,
|
||||
'reserved_snapshot_percentage': 0,
|
||||
'reserved_share_extend_percentage': 0,
|
||||
'mount_point_name_support': True,
|
||||
}, ]
|
||||
|
||||
def create_share(self, context, share, share_server=None):
|
||||
self._allocate_container(share)
|
||||
# create file system
|
||||
device_name = self._get_local_path(share)
|
||||
share_export_location = self._get_mount_point_name(share)
|
||||
location = self._get_helper(share).create_exports(
|
||||
self.share_server, share['name'])
|
||||
self.share_server, share_export_location)
|
||||
self._mount_device(share, device_name)
|
||||
return location
|
||||
|
||||
@ -287,8 +292,9 @@ class LVMShareDriver(LVMMixin, driver.ShareDriver):
|
||||
self._set_random_uuid_to_device(share)
|
||||
self._copy_volume(
|
||||
snapshot_device_name, share_device_name, share['size'])
|
||||
share_export_location = self._get_mount_point_name(share)
|
||||
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)
|
||||
return location
|
||||
|
||||
@ -342,14 +348,19 @@ class LVMShareDriver(LVMMixin, driver.ShareDriver):
|
||||
"""Ensure that storage are mounted and exported."""
|
||||
device_name = self._get_local_path(share)
|
||||
self._mount_device(share, device_name)
|
||||
share_export_location = self._get_mount_point_name(share)
|
||||
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):
|
||||
share_export_location = self._get_mount_point_name(share)
|
||||
"""Delete a share."""
|
||||
try:
|
||||
self._get_helper(share).remove_exports(
|
||||
self.share_server, share['name'])
|
||||
self.share_server, share_export_location)
|
||||
except exception.ProcessExecutionError:
|
||||
LOG.warning("Can't remove share %r", share['id'])
|
||||
except exception.InvalidShare as exc:
|
||||
@ -379,8 +390,10 @@ class LVMShareDriver(LVMMixin, driver.ShareDriver):
|
||||
removed. access_rules doesn't contain these rules.
|
||||
: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,
|
||||
share['name'], access_rules,
|
||||
share_export_location,
|
||||
access_rules,
|
||||
add_rules=add_rules,
|
||||
delete_rules=delete_rules)
|
||||
|
||||
@ -434,11 +447,15 @@ class LVMShareDriver(LVMMixin, driver.ShareDriver):
|
||||
def revert_to_snapshot(self, context, snapshot, share_access_rules,
|
||||
snapshot_access_rules, share_server=None):
|
||||
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
|
||||
self._get_helper(share).update_access(self.share_server,
|
||||
snapshot['name'], [], [], [])
|
||||
snapshot_export_location,
|
||||
[], [], [])
|
||||
self._get_helper(share).update_access(self.share_server,
|
||||
share['name'], [], [], [])
|
||||
share_export_location,
|
||||
[], [], [])
|
||||
# Unmount the snapshot filesystem
|
||||
self._unmount_device(snapshot)
|
||||
# Unmount the share filesystem
|
||||
@ -459,15 +476,17 @@ class LVMShareDriver(LVMMixin, driver.ShareDriver):
|
||||
# Also remount the snapshot
|
||||
device_name = self._get_local_path(snapshot)
|
||||
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
|
||||
self._get_helper(share).update_access(self.share_server,
|
||||
share['name'],
|
||||
share_export_location,
|
||||
share_access_rules,
|
||||
[], [])
|
||||
snapshot_access_rules, __, __ = share_utils.change_rules_to_readonly(
|
||||
snapshot_access_rules, [], [])
|
||||
self._get_helper(share).update_access(self.share_server,
|
||||
snapshot['name'],
|
||||
snapshot_export_location,
|
||||
snapshot_access_rules,
|
||||
[], [])
|
||||
|
||||
|
@ -330,6 +330,10 @@ def is_valid_csv(extra_spec_value):
|
||||
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):
|
||||
return ','.join(value.strip() for value in csv_string.split(',')
|
||||
if (csv_string and value))
|
||||
@ -356,8 +360,12 @@ def is_valid_optional_extra_spec(key, value):
|
||||
return value in constants.ExtraSpecs.REPLICATION_TYPES
|
||||
elif key == constants.ExtraSpecs.MOUNT_SNAPSHOT_SUPPORT:
|
||||
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:
|
||||
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,
|
||||
constants.ExtraSpecs.PROVISIONING_MIN_SHARE_SIZE,
|
||||
constants.ExtraSpecs.PROVISIONING_MAX_SHARE_EXTEND_SIZE]:
|
||||
|
@ -261,6 +261,37 @@ class ShareAPITest(test.TestCase):
|
||||
self.assertEqual("fakenetid",
|
||||
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):
|
||||
shr = {
|
||||
"size": 100,
|
||||
@ -459,6 +490,53 @@ class ShareAPITest(test.TestCase):
|
||||
self.mock_policy_check.assert_called_once_with(
|
||||
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(
|
||||
{'name': 'name1', 'description': 'x' * 256},
|
||||
{'name': 'x' * 256, 'description': 'description1'},
|
||||
|
@ -61,17 +61,40 @@ class ShareTransferAPITestCase(test.TestCase):
|
||||
size=1,
|
||||
project_id='fake_project_id',
|
||||
user_id='fake_user_id',
|
||||
share_network_id=None):
|
||||
share_network_id=None,
|
||||
mount_point_name=None):
|
||||
"""Create a share object."""
|
||||
share_type = db_utils.create_share_type()
|
||||
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
|
||||
)
|
||||
if mount_point_name:
|
||||
instance_list = [
|
||||
db_utils.create_share_instance(
|
||||
status=status,
|
||||
share_id='fake_id',
|
||||
mount_point_name=mount_point_name
|
||||
)
|
||||
]
|
||||
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']
|
||||
return share_id
|
||||
|
||||
@ -232,6 +255,35 @@ class ShareTransferAPITestCase(test.TestCase):
|
||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
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):
|
||||
share_id = self._create_share(share_network_id='fake_id')
|
||||
body = {"transfer": {"name": "transfer1",
|
||||
|
@ -393,6 +393,7 @@ class ShareTypesAPITest(test.TestCase):
|
||||
constants.ExtraSpecs.CREATE_SHARE_FROM_SNAPSHOT_SUPPORT: False,
|
||||
constants.ExtraSpecs.REVERT_TO_SNAPSHOT_SUPPORT: True,
|
||||
constants.ExtraSpecs.MOUNT_SNAPSHOT_SUPPORT: True,
|
||||
constants.ExtraSpecs.MOUNT_POINT_NAME_SUPPORT: True,
|
||||
}
|
||||
|
||||
now = timeutils.utcnow().isoformat()
|
||||
|
@ -94,7 +94,8 @@ def create_share(**kwargs):
|
||||
'availability_zone': 'fake_availability_zone',
|
||||
'status': constants.STATUS_CREATING,
|
||||
'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)
|
||||
|
||||
@ -112,7 +113,8 @@ def create_share_without_instance(**kwargs):
|
||||
'availability_zone': 'fake_availability_zone',
|
||||
'status': constants.STATUS_CREATING,
|
||||
'host': 'fake_host',
|
||||
'is_soft_deleted': False
|
||||
'is_soft_deleted': False,
|
||||
'mount_point_name': None,
|
||||
}
|
||||
share.update(copy.deepcopy(kwargs))
|
||||
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_server_id': 'fakeshareserverid',
|
||||
'share_type_id': '1',
|
||||
'mount_point_name': None,
|
||||
}
|
||||
|
||||
for attr in models.ShareInstance._proxified_properties:
|
||||
@ -82,7 +83,8 @@ def fake_share_type(**kwargs):
|
||||
'is_public': False,
|
||||
'extra_specs': {
|
||||
'driver_handles_share_servers': 'False',
|
||||
}
|
||||
},
|
||||
'mount_point_name_support': False
|
||||
}
|
||||
|
||||
extra_specs = kwargs.pop('extra_specs', {})
|
||||
|
@ -55,7 +55,8 @@ SERVICE_STATES_NO_POOLS = {
|
||||
create_share_from_snapshot_support=False,
|
||||
revert_to_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',
|
||||
total_capacity_gb=256, free_capacity_gb=100,
|
||||
timestamp=None, reserved_percentage=0,
|
||||
@ -68,7 +69,8 @@ SERVICE_STATES_NO_POOLS = {
|
||||
create_share_from_snapshot_support=True,
|
||||
revert_to_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',
|
||||
total_capacity_gb=10000, free_capacity_gb=700,
|
||||
timestamp=None, reserved_percentage=0,
|
||||
@ -81,7 +83,8 @@ SERVICE_STATES_NO_POOLS = {
|
||||
create_share_from_snapshot_support=True,
|
||||
revert_to_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 = [
|
||||
@ -124,7 +127,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
||||
reserved_share_extend_percentage=0,
|
||||
provisioned_capacity_gb=10,
|
||||
max_over_subscription_ratio=1.0,
|
||||
thin_provisioning=False)]),
|
||||
thin_provisioning=False,
|
||||
mount_point_name_support=False,
|
||||
)]),
|
||||
'host2@BBB': dict(share_backend_name='BBB',
|
||||
timestamp=None, reserved_percentage=0,
|
||||
reserved_snapshot_percentage=0,
|
||||
@ -142,7 +147,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
||||
reserved_share_extend_percentage=0,
|
||||
provisioned_capacity_gb=60,
|
||||
max_over_subscription_ratio=2.0,
|
||||
thin_provisioning=True)]),
|
||||
thin_provisioning=True,
|
||||
mount_point_name_support=False,
|
||||
)]),
|
||||
'host3@CCC': dict(share_backend_name='CCC',
|
||||
timestamp=None, reserved_percentage=0,
|
||||
reserved_snapshot_percentage=0,
|
||||
@ -160,7 +167,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
||||
reserved_share_extend_percentage=0,
|
||||
provisioned_capacity_gb=100,
|
||||
max_over_subscription_ratio=20.0,
|
||||
thin_provisioning=True)]),
|
||||
thin_provisioning=True,
|
||||
mount_point_name_support=False,
|
||||
)]),
|
||||
'host4@DDD': dict(share_backend_name='DDD',
|
||||
timestamp=None, reserved_percentage=0,
|
||||
reserved_snapshot_percentage=0,
|
||||
@ -178,7 +187,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
||||
reserved_share_extend_percentage=0,
|
||||
provisioned_capacity_gb=800,
|
||||
max_over_subscription_ratio=2.0,
|
||||
thin_provisioning=True),
|
||||
thin_provisioning=True,
|
||||
mount_point_name_support=False,
|
||||
),
|
||||
dict(pool_name='pool4b',
|
||||
total_capacity_gb=542,
|
||||
free_capacity_gb=442,
|
||||
@ -187,7 +198,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
||||
reserved_share_extend_percentage=0,
|
||||
provisioned_capacity_gb=2000,
|
||||
max_over_subscription_ratio=10.0,
|
||||
thin_provisioning=True)]),
|
||||
thin_provisioning=True,
|
||||
mount_point_name_support=False,
|
||||
)]),
|
||||
'host5@EEE': dict(share_backend_name='EEE',
|
||||
timestamp=None, reserved_percentage=0,
|
||||
reserved_snapshot_percentage=0,
|
||||
@ -205,7 +218,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
||||
reserved_share_extend_percentage=0,
|
||||
provisioned_capacity_gb=100,
|
||||
max_over_subscription_ratio=1.0,
|
||||
thin_provisioning=False),
|
||||
thin_provisioning=False,
|
||||
mount_point_name_support=False,
|
||||
),
|
||||
dict(pool_name='pool5b',
|
||||
total_capacity_gb=552,
|
||||
free_capacity_gb=452,
|
||||
@ -214,7 +229,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
||||
reserved_share_extend_percentage=0,
|
||||
provisioned_capacity_gb=100,
|
||||
max_over_subscription_ratio=1.0,
|
||||
thin_provisioning=False)]),
|
||||
thin_provisioning=False,
|
||||
mount_point_name_support=False,
|
||||
)]),
|
||||
'host6@FFF': dict(share_backend_name='FFF',
|
||||
timestamp=None, reserved_percentage=0,
|
||||
reserved_snapshot_percentage=0,
|
||||
@ -232,7 +249,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
||||
reserved_share_extend_percentage=0,
|
||||
provisioned_capacity_gb=100,
|
||||
max_over_subscription_ratio=1.0,
|
||||
thin_provisioning=False),
|
||||
thin_provisioning=False,
|
||||
mount_point_name_support=False,
|
||||
),
|
||||
dict(pool_name='pool6b',
|
||||
total_capacity_gb='unknown',
|
||||
free_capacity_gb='unknown',
|
||||
@ -241,7 +260,9 @@ SHARE_SERVICE_STATES_WITH_POOLS = {
|
||||
reserved_share_extend_percentage=0,
|
||||
provisioned_capacity_gb=100,
|
||||
max_over_subscription_ratio=1.0,
|
||||
thin_provisioning=False)]),
|
||||
thin_provisioning=False,
|
||||
mount_point_name_support=False,
|
||||
)]),
|
||||
}
|
||||
|
||||
FAKE_ACTIVE_IQ_WEIGHER_LIST = [
|
||||
|
@ -45,6 +45,24 @@ class HostFiltersTestCase(test.TestCase):
|
||||
assertion = self.assertTrue if passes else self.assertFalse
|
||||
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):
|
||||
self._do_test_type_filter_extra_specs(
|
||||
ecaps={'opt1': '1', 'opt2': '2'},
|
||||
|
@ -217,6 +217,7 @@ class HostManagerTestCase(test.TestCase):
|
||||
'security_service_update_support': False,
|
||||
'network_allocation_update_support': False,
|
||||
'share_server_multiple_subnet_support': False,
|
||||
'mount_point_name_support': False,
|
||||
},
|
||||
}, {
|
||||
'name': 'host2@back1#BBB',
|
||||
@ -250,6 +251,7 @@ class HostManagerTestCase(test.TestCase):
|
||||
'security_service_update_support': False,
|
||||
'network_allocation_update_support': False,
|
||||
'share_server_multiple_subnet_support': False,
|
||||
'mount_point_name_support': False,
|
||||
},
|
||||
}, {
|
||||
'name': 'host2@back2#CCC',
|
||||
@ -283,6 +285,7 @@ class HostManagerTestCase(test.TestCase):
|
||||
'security_service_update_support': False,
|
||||
'network_allocation_update_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,
|
||||
'network_allocation_update_support': False,
|
||||
'share_server_multiple_subnet_support': False,
|
||||
'mount_point_name_support': False,
|
||||
},
|
||||
}, {
|
||||
'name': 'host2@BBB#pool2',
|
||||
@ -372,6 +376,7 @@ class HostManagerTestCase(test.TestCase):
|
||||
'security_service_update_support': False,
|
||||
'network_allocation_update_support': False,
|
||||
'share_server_multiple_subnet_support': False,
|
||||
'mount_point_name_support': False,
|
||||
},
|
||||
}, {
|
||||
'name': 'host3@CCC#pool3',
|
||||
@ -406,6 +411,7 @@ class HostManagerTestCase(test.TestCase):
|
||||
'security_service_update_support': False,
|
||||
'network_allocation_update_support': False,
|
||||
'share_server_multiple_subnet_support': False,
|
||||
'mount_point_name_support': False,
|
||||
},
|
||||
}, {
|
||||
'name': 'host4@DDD#pool4a',
|
||||
@ -440,6 +446,7 @@ class HostManagerTestCase(test.TestCase):
|
||||
'security_service_update_support': False,
|
||||
'network_allocation_update_support': False,
|
||||
'share_server_multiple_subnet_support': False,
|
||||
'mount_point_name_support': False,
|
||||
},
|
||||
}, {
|
||||
'name': 'host4@DDD#pool4b',
|
||||
@ -474,6 +481,7 @@ class HostManagerTestCase(test.TestCase):
|
||||
'security_service_update_support': False,
|
||||
'network_allocation_update_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,
|
||||
'network_allocation_update_support': False,
|
||||
'share_server_multiple_subnet_support': False,
|
||||
'mount_point_name_support': False,
|
||||
},
|
||||
}, {
|
||||
'name': 'host2@back1#BBB',
|
||||
@ -574,6 +583,7 @@ class HostManagerTestCase(test.TestCase):
|
||||
'security_service_update_support': False,
|
||||
'network_allocation_update_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,
|
||||
'network_allocation_update_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.assertTrue(self._driver._stats['ipv4_support'])
|
||||
self.assertFalse(self._driver._stats['ipv6_support'])
|
||||
self.assertFalse(self._driver.
|
||||
_stats['mount_point_name_support'])
|
||||
|
||||
def test_create_share(self):
|
||||
|
||||
|
@ -166,6 +166,7 @@ class EMCShareFrameworkTestCase(test.TestCase):
|
||||
data['replication_domain'] = None
|
||||
data['filter_function'] = None
|
||||
data['goodness_function'] = None
|
||||
data['mount_point_name_support'] = False
|
||||
data['snapshot_support'] = True
|
||||
data['create_share_from_snapshot_support'] = True
|
||||
data['ipv4_support'] = True
|
||||
|
@ -181,6 +181,9 @@ class DummyDriver(driver.ShareDriver):
|
||||
))
|
||||
|
||||
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" % {
|
||||
"s_id": share["share_id"].replace("-", "_"),
|
||||
"si_id": share["id"].replace("-", "_")}
|
||||
@ -516,6 +519,7 @@ class DummyDriver(driver.ShareDriver):
|
||||
"consistent_snapshot_support": "pool",
|
||||
},
|
||||
'share_server_multiple_subnet_support': True,
|
||||
'mount_point_name_support': True,
|
||||
}
|
||||
if self.configuration.replication_domain:
|
||||
data["replication_type"] = "readable"
|
||||
|
@ -268,6 +268,7 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
||||
'replication_domain': None,
|
||||
'filter_function': None,
|
||||
'goodness_function': None,
|
||||
'mount_point_name_support': False,
|
||||
'ipv4_support': True,
|
||||
'ipv6_support': False,
|
||||
'security_service_update_support': False,
|
||||
|
@ -746,6 +746,7 @@ class HPE3ParDriverTestCase(test.TestCase):
|
||||
'replication_domain': None,
|
||||
'filter_function': None,
|
||||
'goodness_function': None,
|
||||
'mount_point_name_support': False,
|
||||
'ipv4_support': True,
|
||||
'ipv6_support': False,
|
||||
'max_share_server_size': -1,
|
||||
@ -839,6 +840,7 @@ class HPE3ParDriverTestCase(test.TestCase):
|
||||
'replication_domain': None,
|
||||
'filter_function': None,
|
||||
'goodness_function': None,
|
||||
'mount_point_name_support': False,
|
||||
'ipv4_support': True,
|
||||
'ipv6_support': False,
|
||||
}
|
||||
@ -890,6 +892,7 @@ class HPE3ParDriverTestCase(test.TestCase):
|
||||
'replication_domain': None,
|
||||
'filter_function': None,
|
||||
'goodness_function': None,
|
||||
'mount_point_name_support': False,
|
||||
'ipv4_support': True,
|
||||
'ipv6_support': False,
|
||||
}
|
||||
|
@ -2431,6 +2431,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
||||
"replication_domain": None,
|
||||
"filter_function": None,
|
||||
"goodness_function": None,
|
||||
'mount_point_name_support': False,
|
||||
"pools": [],
|
||||
"share_group_stats": {"consistent_snapshot_support": None},
|
||||
"ipv4_support": True,
|
||||
|
@ -186,6 +186,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
||||
CONF.lvm_share_volume_group, 0, 0]
|
||||
self.mock_object(privsep_common, 'execute_with_retries')
|
||||
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,
|
||||
self.share_server)
|
||||
@ -222,6 +224,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
||||
self.mock_object(filesystem, 'make_filesystem')
|
||||
self.mock_object(filesystem, 'e2fsck')
|
||||
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.share,
|
||||
@ -256,6 +260,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
||||
self._driver._mount_device = mock.Mock()
|
||||
self.mock_object(privsep_common, 'execute_with_retries')
|
||||
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,
|
||||
self.share_server)
|
||||
@ -402,6 +408,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
||||
|
||||
def test_ensure_share(self):
|
||||
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,
|
||||
'_mount_device',
|
||||
mock.Mock(return_value='fake_location')):
|
||||
@ -413,6 +421,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
||||
self.server, self.share['name'], recreate=True)
|
||||
|
||||
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)
|
||||
self._helper_nfs.remove_export(mount_path, self.share['name'])
|
||||
self._driver._delete_share(self._context, self.share)
|
||||
@ -437,6 +447,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
||||
self.mock_object(self._driver, '_deallocate_container')
|
||||
self._driver._get_helper = mock.Mock(
|
||||
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)
|
||||
|
||||
@ -450,6 +462,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
||||
self._helper_nfs,
|
||||
'remove_export',
|
||||
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._helper_nfs.remove_exports.assert_called_once_with(
|
||||
@ -464,6 +478,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
||||
'2.2.2.2', access_level), ]
|
||||
delete_rules = [test_generic.get_fake_access_rule(
|
||||
'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,
|
||||
add_rules=add_rules,
|
||||
delete_rules=delete_rules,
|
||||
@ -609,6 +625,7 @@ class LVMShareDriverTestCase(test.TestCase):
|
||||
'reserved_percentage': 0,
|
||||
'reserved_snapshot_percentage': 0,
|
||||
'reserved_share_extend_percentage': 0,
|
||||
'mount_point_name_support': True,
|
||||
}, ]
|
||||
out, err = "VSize 33g VFree 22g", None
|
||||
self.mock_object(
|
||||
@ -669,6 +686,8 @@ class LVMShareDriverTestCase(test.TestCase):
|
||||
mock_get_local_path = self.mock_object(
|
||||
self._driver, '_get_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']
|
||||
|
||||
self._driver.revert_to_snapshot(self._context, self.snapshot,
|
||||
@ -784,3 +803,28 @@ class LVMShareDriverTestCase(test.TestCase):
|
||||
{'export_ips': ','.join(self.server['public_addresses']),
|
||||
'db_version': mock.ANY},
|
||||
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,
|
||||
'filter_function': 'Disable',
|
||||
'goodness_function': 'Disable',
|
||||
'mount_point_name_support': False,
|
||||
'ipv4_support': True,
|
||||
'ipv6_support': False,
|
||||
'mount_snapshot_support': False,
|
||||
|
@ -376,6 +376,7 @@ class ZFSonLinuxShareDriverTestCase(test.TestCase):
|
||||
'vendor_name': 'Open Source',
|
||||
'filter_function': None,
|
||||
'goodness_function': None,
|
||||
'mount_point_name_support': False,
|
||||
'ipv4_support': True,
|
||||
'ipv6_support': False,
|
||||
'security_service_update_support': False,
|
||||
|
@ -166,7 +166,10 @@ class ShareAPITestCase(test.TestCase):
|
||||
share_instance = db_utils.create_share_instance(
|
||||
share_id=share['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',
|
||||
mock.Mock(return_value=share_instance))
|
||||
self.mock_object(db_api, 'share_type_get',
|
||||
@ -801,7 +804,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
availability_zones=expected_azs,
|
||||
az_request_multiple_subnet_support_map=compatible_azs_multiple,
|
||||
snapshot_host=None,
|
||||
scheduler_hints=None
|
||||
scheduler_hints=None, mount_point_name=None,
|
||||
)
|
||||
db_api.share_get.assert_called_once()
|
||||
|
||||
@ -840,6 +843,85 @@ class ShareAPITestCase(test.TestCase):
|
||||
get_all_azs_sns.assert_called_once_with(
|
||||
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(
|
||||
None, '', 'fake', 'nfsfake', 'cifsfake', 'glusterfsfake', 'hdfsfake')
|
||||
def test_create_share_invalid_protocol(self, proto):
|
||||
@ -984,6 +1066,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
'availability_zone_id': 'fake_id',
|
||||
'share_type_id': 'fake_share_type',
|
||||
'cast_rules_to_readonly': False,
|
||||
'mount_point_name': None,
|
||||
}
|
||||
)
|
||||
db_api.share_type_get.assert_called_once_with(
|
||||
@ -999,6 +1082,28 @@ class ShareAPITestCase(test.TestCase):
|
||||
self.assertFalse(
|
||||
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):
|
||||
_, share, share_instance = self._setup_create_instance_mocks()
|
||||
|
||||
@ -1072,6 +1177,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
'create_share_from_snapshot_support': False,
|
||||
'revert_to_snapshot_support': False,
|
||||
'mount_snapshot_support': False,
|
||||
'mount_point_name_support': False,
|
||||
'replication_type': 'dr',
|
||||
}
|
||||
}
|
||||
@ -1090,6 +1196,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
'create_share_from_snapshot_support': False,
|
||||
'revert_to_snapshot_support': False,
|
||||
'mount_snapshot_support': False,
|
||||
'mount_point_name_support': False,
|
||||
'replication_type': None,
|
||||
}
|
||||
self.assertEqual(expected, result)
|
||||
@ -1140,6 +1247,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
'create_share_from_snapshot_support': False,
|
||||
'revert_to_snapshot_support': False,
|
||||
'mount_snapshot_support': False,
|
||||
'mount_point_name_support': False,
|
||||
'driver_handles_share_servers': dhss,
|
||||
},
|
||||
}
|
||||
@ -1176,6 +1284,8 @@ class ShareAPITestCase(test.TestCase):
|
||||
fake_type['extra_specs']['revert_to_snapshot_support'],
|
||||
'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,
|
||||
})
|
||||
|
||||
@ -1231,6 +1341,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
'create_share_from_snapshot_support': False,
|
||||
'revert_to_snapshot_support': False,
|
||||
'mount_snapshot_support': False,
|
||||
'mount_point_name_support': False,
|
||||
'driver_handles_share_servers': dhss,
|
||||
},
|
||||
}
|
||||
@ -1278,6 +1389,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
'create_share_from_snapshot_support': False,
|
||||
'revert_to_snapshot_support': False,
|
||||
'mount_snapshot_support': False,
|
||||
'mount_point_name_support': False,
|
||||
'driver_handles_share_servers': True,
|
||||
},
|
||||
}
|
||||
@ -1329,6 +1441,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
'create_share_from_snapshot_support': False,
|
||||
'revert_to_snapshot_support': False,
|
||||
'mount_snapshot_support': False,
|
||||
'mount_point_name_support': False,
|
||||
'driver_handles_share_servers': True,
|
||||
},
|
||||
}
|
||||
@ -1412,6 +1525,9 @@ class ShareAPITestCase(test.TestCase):
|
||||
'mount_snapshot_support': kwargs.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_type_id': share_type['id'],
|
||||
'is_public': kwargs.get('is_public', share.get('is_public')),
|
||||
@ -2356,7 +2472,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
availability_zones=None,
|
||||
az_request_multiple_subnet_support_map=None,
|
||||
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(
|
||||
self.context, 'share_snapshot', 'get_snapshot')
|
||||
quota.QUOTAS.reserve.assert_called_once_with(
|
||||
@ -3508,6 +3624,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
'create_share_from_snapshot_support': False,
|
||||
'revert_to_snapshot_support': False,
|
||||
'mount_snapshot_support': False,
|
||||
'mount_point_name_support': False,
|
||||
'driver_handles_share_servers': dhss,
|
||||
},
|
||||
}
|
||||
@ -3520,6 +3637,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
'create_share_from_snapshot_support': False,
|
||||
'revert_to_snapshot_support': False,
|
||||
'mount_snapshot_support': False,
|
||||
'mount_point_name_support': False,
|
||||
'driver_handles_share_servers': dhss,
|
||||
'availability_zones': 'fake_az1,fake_az2',
|
||||
},
|
||||
@ -3603,6 +3721,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
'create_share_from_snapshot_support': False,
|
||||
'revert_to_snapshot_support': False,
|
||||
'mount_snapshot_support': False,
|
||||
'mount_point_name_support': False,
|
||||
'driver_handles_share_servers': 'true',
|
||||
'availability_zones': 'fake_az3'
|
||||
},
|
||||
@ -3615,6 +3734,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
'create_share_from_snapshot_support': False,
|
||||
'revert_to_snapshot_support': False,
|
||||
'mount_snapshot_support': False,
|
||||
'mount_point_name_support': False,
|
||||
'driver_handles_share_servers': 'true',
|
||||
'availability_zones': 'fake_az1,fake_az2',
|
||||
},
|
||||
|
@ -144,6 +144,7 @@ class ShareDriverTestCase(test.TestCase):
|
||||
'reserved_share_extend_percentage',
|
||||
'vendor_name', 'storage_protocol',
|
||||
'snapshot_support', 'mount_snapshot_support',
|
||||
'mount_point_name_support',
|
||||
]
|
||||
share_driver = driver.ShareDriver(True, configuration=conf)
|
||||
fake_stats = {'fake_key': 'fake_value'}
|
||||
|
@ -406,14 +406,18 @@ class ShareTypesTestCase(test.TestCase):
|
||||
(constants.ExtraSpecs.SNAPSHOT_SUPPORT,
|
||||
constants.ExtraSpecs.CREATE_SHARE_FROM_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)) +
|
||||
list(itertools.product(
|
||||
(constants.ExtraSpecs.REPLICATION_TYPE_SPEC,),
|
||||
constants.ExtraSpecs.REPLICATION_TYPES)) +
|
||||
[(constants.ExtraSpecs.AVAILABILITY_ZONES, 'zone a, zoneb$c'),
|
||||
(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
|
||||
def test_is_valid_optional_extra_spec_valid(self, key, value):
|
||||
@ -422,6 +426,18 @@ class ShareTypesTestCase(test.TestCase):
|
||||
|
||||
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):
|
||||
|
||||
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",
|
||||
target_obj=share_ref)
|
||||
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":
|
||||
raise exception.InvalidShare(reason=_("Share's status must be "
|
||||
"available"))
|
||||
|
@ -0,0 +1,12 @@
|
||||
---
|
||||
features:
|
||||
- A human readable ``mount_point_name`` can now be specified
|
||||
while creating shares through the mount_point_name parameter.
|
||||
Manila will prepend a prefix to the mount point name which
|
||||
can be configured through the ``provisioning:mount_point_prefix``
|
||||
share type extra spec. In case this extra spec is not available
|
||||
in the share type, Manila will prepend a project identification
|
||||
to the mount point name. Project id will be added to this friendly
|
||||
name ``provisioning:mount_point_prefix`` share type is not
|
||||
provided during provisioning. The LVM driver now supports
|
||||
human readable export locations.
|
Loading…
Reference in New Issue
Block a user