Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
====================================
=====================
Vastdata Share Driver
====================================
=====================

VAST Share Driver integrates OpenStack with
`VAST Data <https://www.vastdata.com>`__'s Storage System.
Expand Down Expand Up @@ -46,14 +46,21 @@ share driver.


VAST Share Driver configuration example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The following example shows parameters in the ``manila.conf`` file
that are used to configure VAST Share Driver.
They include two options under ``[DEFAULT]`` and parameters under ``[vast]``.
Note that a real ``manila.conf`` file would also include
other parameters that are not specific to VAST Share Driver.

.. note::

The ``vast_vippool_name`` parameter can be omitted from ``manila.conf``
if you plan to specify different VIP pools per share type using the
``vast:vippool_name`` extra spec. See the Multitenancy support section
for more details.

.. code-block:: ini

[DEFAULT]
Expand All @@ -69,6 +76,7 @@ other parameters that are not specific to VAST Share Driver.
vast_mgmt_port = {vms_port}
vast_mgmt_user = {mgmt_user}
vast_mgmt_password = {mgmt_password}
vast_api_token = {vast_api_token}
vast_vippool_name = {vip_pool}
vast_root_export = {root_export}

Expand All @@ -78,7 +86,7 @@ changes to take effect.


Pre-configurations for share support
--------------------------------------------------
------------------------------------

To create a file share, you need to:

Expand All @@ -95,8 +103,75 @@ Create an NFS share:

openstack share create NFS ${size} --name ${share_name} --share-type ${share_type_name}

Multitenancy support via Share Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The VAST Share Driver supports multitenancy by allowing different share types
to use different VIP pools. This enables tenant isolation and provides
flexibility in network configuration.

VIP Pool Configuration
----------------------

The VIP pool can be specified in two ways:

1. **Global default** in ``manila.conf`` using ``vast_vippool_name``
2. **Per share type** using the ``vast:vippool_name`` extra spec

When both are specified, the share type extra spec takes precedence over
the configuration file setting.

Creating Share Types with Different VIP Pools
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can create multiple share types, each using a different VIP pool for
multitenancy:

.. code-block:: console

# Tenant A with dedicated VIP pool
openstack share type create vast-tenant-a false \
--extra-specs share_backend_name=vast \
--extra-specs vast:vippool_name=vippool-tenant-a

# Tenant B with dedicated VIP pool
openstack share type create vast-tenant-b false \
--extra-specs share_backend_name=vast \
--extra-specs vast:vippool_name=vippool-tenant-b

Creating Shares with Specific VIP Pools
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When creating a share, specify the share type to determine which VIP pool
will be used:

.. code-block:: console

# Create a share for Tenant A (uses vippool-tenant-a)
openstack share create NFS 100 \
--name tenant-a-share \
--share-type vast-tenant-a

# Create a share for Tenant B (uses vippool-tenant-b)
openstack share create NFS 50 \
--name tenant-b-share \
--share-type vast-tenant-b

This approach enables:

- **Network isolation** between different tenants or projects
- **Service differentiation** with different network configurations per tenant or environment
- **Flexible deployment** without modifying ``manila.conf``

.. note::

If ``vast_vippool_name`` is not specified in ``manila.conf`` and a share
is created without a share type that specifies ``vast:vippool_name``,
the share creation will fail with an error indicating that a VIP pool
must be specified.

Pre-Configurations for Snapshot support
--------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The share type must have the following parameter specified:

Expand All @@ -118,7 +193,7 @@ Or you can add it to an existing share type:


To snapshot a share and create share from the snapshot
------------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Create a share using a share type with snapshot_support=True.
Then, create a snapshot of the share using the command:
Expand Down
2 changes: 2 additions & 0 deletions doc/source/configuration/tables/manila-vastdata.inc
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@
- (String) Username for VAST management API.
* - ``vast_mgmt_password`` =
- (String) Password for VAST management API.
* - ``vast_api_token`` =
- (String) API token for accessing VAST mgmt. If provided, it will be used instead of 'vast_mgmt_user' and 'vast_mgmt_password'.
116 changes: 96 additions & 20 deletions manila/share/drivers/vastdata/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@
),
cfg.StrOpt(
"vast_vippool_name",
help="Name of Virtual IP pool"
help="Default name of Virtual IP pool. Can be overridden per share "
"using share type extra spec 'vast:vippool_name'."
),
cfg.StrOpt(
"vast_root_export",
Expand All @@ -79,6 +80,16 @@
help="Password for VAST management",
secret=True
),
cfg.StrOpt(
"vast_api_token",
default="",
secret=True,
help=(
"API token for accessing VAST mgmt. "
"If provided, it will be used instead "
"of 'san_login' and 'san_password'."
)
),
]

CONF = cfg.CONF
Expand All @@ -94,9 +105,21 @@
driver_util.verbose_driver_trace
)
class VASTShareDriver(driver.ShareDriver):
"""Driver for the VastData Filesystem."""
"""Driver for the VastData Filesystem.

Version history::

1.0 - Initial version.
- Support for NFS shares.
- Support for snapshots (create, delete, revert).
- Support for share creation from snapshots.
- Support for share access rules (IP-based).
- Support for share resize (extend/shrink).
1.1 - Added multi-tenancy support.
- Support for per-share VIP pool selection via extra specs.
"""

VERSION = "1.0" # driver version
VERSION = "1.1"

def __init__(self, *args, **kwargs):
super().__init__(False, *args, config_opts=[OPTS], **kwargs)
Expand All @@ -106,29 +129,36 @@ def do_setup(self, context):
backend_name = self.configuration.safe_get("share_backend_name")
root_export = self.configuration.vast_root_export
vip_pool_name = self.configuration.safe_get("vast_vippool_name")
if not vip_pool_name:
raise exception.VastDriverException(
reason="vast_vippool_name must be set"
)

self._backend_name = backend_name or self.__class__.__name__
self._vippool_name = vip_pool_name
self._root_export = "/" + root_export.strip("/")

username = self.configuration.safe_get("vast_mgmt_user")
password = self.configuration.safe_get("vast_mgmt_password")
api_token = self.configuration.safe_get("vast_api_token")
host = self.configuration.safe_get("vast_mgmt_host")
port = self.configuration.safe_get("vast_mgmt_port")
if not all((username, password, port)):
if not host:
raise exception.VastDriverException(
reason="`vast_mgmt_host` must be set in manila.conf."
)
# Require either (username & password) OR (API token)
if not ((username and password) or api_token):
raise exception.VastDriverException(
reason="Not all required parameters are present."
" Make sure you specified `vast_mgmt_host`,"
" `vast_mgmt_port`, and `vast_mgmt_user` "
"in manila.conf."
reason="Authentication failed: You must specify either "
"`vast_mgmt_user` and `vast_mgmt_password`, "
"or provide `vast_api_token` in manila.conf."
)
if port:
host = f"{host}:{port}"
self.rest = vast_rest.RestApi(
host, username, password, False, self.VERSION
host=host,
username=username,
password=password,
api_token=api_token,
ssl_verify=False,
plugin_version=self.VERSION,
)
LOG.debug("VAST Data driver setup is complete.")

Expand Down Expand Up @@ -256,9 +286,14 @@ def shrink_share(self, share, new_size, share_server=None):
self._resize_share(share, new_size)

def create_snapshot(self, context, snapshot, share_server=None):
"""Is called to create snapshot."""
"""Is called to create a snapshot."""
path = self._to_volume_path(snapshot["share_instance_id"])
self.rest.snapshots.create(path=path, name=snapshot["name"])
tenant_id = self._get_tenant_id_for_share(snapshot["share"])
self.rest.snapshots.create(
name=snapshot["name"],
path=path,
tenant_id=tenant_id,
)

def delete_snapshot(self, context, snapshot, share_server=None):
"""Is called to remove share."""
Expand Down Expand Up @@ -296,6 +331,33 @@ def _resize_share(self, share, new_size):
share_id=share['id'])
self.rest.quotas.update(quota.id, hard_limit=requested_capacity)

def _get_vip_pool_for_share(self, share):
# Get extra specs from share type
extra_specs = driver_util.get_share_extra_specs_params(share)
# Use vippool_name from extra specs if provided, otherwise use config
vippool_name = extra_specs.get('vippool_name') or self._vippool_name

if not vippool_name:
raise exception.VastDriverException(
reason="VIP pool name must be specified either in manila.conf "
"(vast_vippool_name) or in share type extra specs "
"(vast:vippool_name)"
)

LOG.debug(
"Using VIP pool '%s' for share %s (from %s)",
vippool_name, share["id"],
"extra_specs" if extra_specs.get('vippool_name') else "config"
)

return self.rest.vip_pools.one(
name=vippool_name,
fail_if_missing=True,
)

def _get_tenant_id_for_share(self, share):
return self._get_vip_pool_for_share(share).tenant_id

def _ensure_share(self, share):
share_proto = share["share_proto"]
if share_proto != "NFS":
Expand All @@ -305,23 +367,37 @@ def _ensure_share(self, share):
)
)

vips = self.rest.vip_pools.vips(pool_name=self._vippool_name)
vippool = self._get_vip_pool_for_share(share)
vips = driver_util.generate_ip_range(vippool.ip_ranges)
if not vips:
raise exception.VastDriverException(
reason=f"Pool {vippool.name} has no available vips"
)

share_id = share["id"]
requested_capacity = share["size"] * units.Gi
path = self._to_volume_path(share_id)
policy = self.rest.view_policies.ensure(name=share_id)
policy = self.rest.view_policies.ensure(
name=share_id,
tenant_id=vippool.tenant_id,
)
quota = self.rest.quotas.ensure(
name=share_id, path=path,
create_dir=True, hard_limit=requested_capacity
name=share_id,
path=path,
create_dir=True,
hard_limit=requested_capacity,
tenant_id=vippool.tenant_id,
)
if quota.hard_limit != requested_capacity:
raise exception.VastDriverException(
reason=f"Share already exists with different capacity"
f" (requested={requested_capacity}, exists={quota.hard_limit})"
)
view = self.rest.views.ensure(
name=share_id, path=path, policy_id=policy.id
name=share_id,
path=path,
policy_id=policy.id,
tenant_id=vippool.tenant_id,
)
if view.policy != share_id:
self.rest.views.update(view.id, policy_id=policy.id)
Expand Down
Loading
Loading