Graduate share replication feature

Removes the experimental mentions from share replication feature
commands.

Partially-implements: bp graduate-share-replication-feature
Depends-On: Idf8af1c96df373fbcbb4024db490cb4dab42faf7
Change-Id: Ie7f823dfc86f4d8e4545228dab48cd5cb26a257c
This commit is contained in:
silvacarloss 2020-08-23 17:51:26 +00:00
parent a68aaab172
commit afcedeb840
6 changed files with 119 additions and 30 deletions

View File

@ -27,7 +27,7 @@ from manilaclient import utils
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
MAX_VERSION = '2.55' MAX_VERSION = '2.56'
MIN_VERSION = '2.0' MIN_VERSION = '2.0'
DEPRECATED_VERSION = '1.0' DEPRECATED_VERSION = '1.0'
_VERSIONED_METHOD_MAP = {} _VERSIONED_METHOD_MAP = {}

View File

@ -109,3 +109,6 @@ BOOL_SPECS = (
REVERT_TO_SNAPSHOT_SUPPORT, REVERT_TO_SNAPSHOT_SUPPORT,
MOUNT_SNAPSHOT_SUPPORT MOUNT_SNAPSHOT_SUPPORT
) )
REPLICA_GRADUATION_VERSION = '2.56'
REPLICA_PRE_GRADUATION_VERSION = '2.55'

View File

@ -15,6 +15,7 @@
from manilaclient import api_versions from manilaclient import api_versions
from manilaclient import base from manilaclient import base
from manilaclient.common.apiclient import base as common_base from manilaclient.common.apiclient import base as common_base
from manilaclient.common import constants
class ShareReplicaExportLocation(common_base.Resource): class ShareReplicaExportLocation(common_base.Resource):
@ -31,7 +32,7 @@ class ShareReplicaExportLocationManager(base.ManagerWithFind):
"""Manage :class:`ShareInstanceExportLocation` resources.""" """Manage :class:`ShareInstanceExportLocation` resources."""
resource_class = ShareReplicaExportLocation resource_class = ShareReplicaExportLocation
@api_versions.wraps("2.47") @api_versions.wraps("2.47", constants.REPLICA_PRE_GRADUATION_VERSION)
@api_versions.experimental_api @api_versions.experimental_api
def list(self, share_replica, search_opts=None): def list(self, share_replica, search_opts=None):
"""List all share replica export locations.""" """List all share replica export locations."""
@ -40,9 +41,26 @@ class ShareReplicaExportLocationManager(base.ManagerWithFind):
"/share-replicas/%s/export-locations" % share_replica_id, "/share-replicas/%s/export-locations" % share_replica_id,
"export_locations") "export_locations")
@api_versions.wraps("2.47") @api_versions.wraps(constants.REPLICA_GRADUATION_VERSION) # noqa
def list(self, share_replica, search_opts=None):
"""List all share replica export locations."""
share_replica_id = common_base.getid(share_replica)
return self._list(
"/share-replicas/%s/export-locations" % share_replica_id,
"export_locations")
@api_versions.wraps("2.47", constants.REPLICA_PRE_GRADUATION_VERSION)
@api_versions.experimental_api @api_versions.experimental_api
def get(self, share_replica, export_location): def get(self, share_replica, export_location):
return self._get_replica_export_location(
share_replica, export_location)
@api_versions.wraps(constants.REPLICA_GRADUATION_VERSION) # noqa
def get(self, share_replica, export_location):
return self._get_replica_export_location(
share_replica, export_location)
def _get_replica_export_location(self, share_replica, export_location):
"""Get a share replica export location.""" """Get a share replica export location."""
share_replica_id = common_base.getid(share_replica) share_replica_id = common_base.getid(share_replica)
export_location_id = common_base.getid(export_location) export_location_id = common_base.getid(export_location)

View File

@ -16,6 +16,7 @@
from manilaclient import api_versions from manilaclient import api_versions
from manilaclient import base from manilaclient import base
from manilaclient.common.apiclient import base as common_base from manilaclient.common.apiclient import base as common_base
from manilaclient.common import constants
RESOURCES_PATH = '/share-replicas' RESOURCES_PATH = '/share-replicas'
RESOURCE_PATH = '/share-replicas/%s' RESOURCE_PATH = '/share-replicas/%s'
@ -50,9 +51,16 @@ class ShareReplicaManager(base.ManagerWithFind):
"""Manage :class:`ShareReplica` resources.""" """Manage :class:`ShareReplica` resources."""
resource_class = ShareReplica resource_class = ShareReplica
@api_versions.wraps("2.11") @api_versions.wraps("2.11", constants.REPLICA_PRE_GRADUATION_VERSION)
@api_versions.experimental_api @api_versions.experimental_api
def get(self, replica): def get(self, replica):
return self._get_share_replica(replica)
@api_versions.wraps(constants.REPLICA_GRADUATION_VERSION) # noqa
def get(self, replica):
return self._get_share_replica(replica)
def _get_share_replica(self, replica):
"""Get a share replica. """Get a share replica.
:param replica: either replica object or its UUID. :param replica: either replica object or its UUID.
@ -61,9 +69,16 @@ class ShareReplicaManager(base.ManagerWithFind):
replica_id = common_base.getid(replica) replica_id = common_base.getid(replica)
return self._get(RESOURCE_PATH % replica_id, RESOURCE_NAME) return self._get(RESOURCE_PATH % replica_id, RESOURCE_NAME)
@api_versions.wraps("2.11") @api_versions.wraps("2.11", constants.REPLICA_PRE_GRADUATION_VERSION)
@api_versions.experimental_api @api_versions.experimental_api
def list(self, share=None, search_opts=None): def list(self, share=None, search_opts=None):
return self._list_share_replicas(share=share, search_opts=search_opts)
@api_versions.wraps(constants.REPLICA_GRADUATION_VERSION) # noqa
def list(self, share=None, search_opts=None):
return self._list_share_replicas(share=share, search_opts=search_opts)
def _list_share_replicas(self, share=None, search_opts=None):
"""List all share replicas or list replicas belonging to a share. """List all share replicas or list replicas belonging to a share.
:param share: either share object or its UUID. :param share: either share object or its UUID.
@ -78,7 +93,7 @@ class ShareReplicaManager(base.ManagerWithFind):
else: else:
return self._list(RESOURCES_PATH + '/detail', RESOURCES_NAME) return self._list(RESOURCES_PATH + '/detail', RESOURCES_NAME)
@api_versions.wraps("2.11") @api_versions.wraps("2.11", constants.REPLICA_PRE_GRADUATION_VERSION)
@api_versions.experimental_api @api_versions.experimental_api
def promote(self, replica): def promote(self, replica):
"""Promote the provided replica. """Promote the provided replica.
@ -87,9 +102,26 @@ class ShareReplicaManager(base.ManagerWithFind):
""" """
return self._action('promote', replica) return self._action('promote', replica)
@api_versions.wraps("2.11") @api_versions.wraps(constants.REPLICA_GRADUATION_VERSION) # noqa
def promote(self, replica):
"""Promote the provided replica.
:param replica: either replica object or its UUID.
"""
return self._action('promote', replica)
@api_versions.wraps("2.11", constants.REPLICA_PRE_GRADUATION_VERSION)
@api_versions.experimental_api @api_versions.experimental_api
def create(self, share, availability_zone=None): def create(self, share, availability_zone=None):
return self._create_share_replica(
share, availability_zone=availability_zone)
@api_versions.wraps(constants.REPLICA_GRADUATION_VERSION) # noqa
def create(self, share, availability_zone=None):
return self._create_share_replica(
share, availability_zone=availability_zone)
def _create_share_replica(self, share, availability_zone=None):
"""Create a replica for a share. """Create a replica for a share.
:param share: The share to create the replica of. Can be the share :param share: The share to create the replica of. Can be the share
@ -107,7 +139,7 @@ class ShareReplicaManager(base.ManagerWithFind):
{RESOURCE_NAME: body}, {RESOURCE_NAME: body},
RESOURCE_NAME) RESOURCE_NAME)
@api_versions.wraps("2.11") @api_versions.wraps("2.11", constants.REPLICA_PRE_GRADUATION_VERSION)
@api_versions.experimental_api @api_versions.experimental_api
def delete(self, replica, force=False): def delete(self, replica, force=False):
"""Delete a replica. """Delete a replica.
@ -117,7 +149,16 @@ class ShareReplicaManager(base.ManagerWithFind):
""" """
self._do_delete(replica, force=force) self._do_delete(replica, force=force)
@api_versions.wraps("2.11") @api_versions.wraps(constants.REPLICA_GRADUATION_VERSION) # noqa
def delete(self, replica, force=False):
"""Delete a replica.
:param replica: either replica object or its UUID.
:param force: optional 'force' flag.
"""
self._do_delete(replica, force=force)
@api_versions.wraps("2.11", constants.REPLICA_PRE_GRADUATION_VERSION)
@api_versions.experimental_api @api_versions.experimental_api
def reset_state(self, replica, state): def reset_state(self, replica, state):
"""Reset the 'status' attr of the replica. """Reset the 'status' attr of the replica.
@ -127,7 +168,16 @@ class ShareReplicaManager(base.ManagerWithFind):
""" """
return self._do_reset_state(replica, state, "reset_status") return self._do_reset_state(replica, state, "reset_status")
@api_versions.wraps("2.11") @api_versions.wraps(constants.REPLICA_GRADUATION_VERSION) # noqa
def reset_state(self, replica, state):
"""Reset the 'status' attr of the replica.
:param replica: either replica object or its UUID.
:param state: state to set the replica's 'status' attr to.
"""
return self._do_reset_state(replica, state, "reset_status")
@api_versions.wraps("2.11", constants.REPLICA_PRE_GRADUATION_VERSION)
@api_versions.experimental_api @api_versions.experimental_api
def reset_replica_state(self, replica, state): def reset_replica_state(self, replica, state):
"""Reset the 'replica_state' attr of the replica. """Reset the 'replica_state' attr of the replica.
@ -137,7 +187,16 @@ class ShareReplicaManager(base.ManagerWithFind):
""" """
return self._do_reset_state(replica, state, "reset_replica_state") return self._do_reset_state(replica, state, "reset_replica_state")
@api_versions.wraps("2.11") @api_versions.wraps(constants.REPLICA_GRADUATION_VERSION) # noqa
def reset_replica_state(self, replica, state):
"""Reset the 'replica_state' attr of the replica.
:param replica: either replica object or its UUID.
:param state: state to set the replica's 'replica_state' attr to.
"""
return self._do_reset_state(replica, state, "reset_replica_state")
@api_versions.wraps("2.11", constants.REPLICA_PRE_GRADUATION_VERSION)
@api_versions.experimental_api @api_versions.experimental_api
def resync(self, replica): def resync(self, replica):
"""Re-sync the provided replica. """Re-sync the provided replica.
@ -146,6 +205,14 @@ class ShareReplicaManager(base.ManagerWithFind):
""" """
return self._action('resync', replica) return self._action('resync', replica)
@api_versions.wraps(constants.REPLICA_GRADUATION_VERSION) # noqa
def resync(self, replica):
"""Re-sync the provided replica.
:param replica: either replica object or its UUID.
"""
return self._action('resync', replica)
def _action(self, action, replica, info=None, **kwargs): def _action(self, action, replica, info=None, **kwargs):
"""Perform a share replica 'action'. """Perform a share replica 'action'.

View File

@ -5351,7 +5351,7 @@ def do_share_group_snapshot_delete(cs, args):
'example --columns "replica_state,id".') 'example --columns "replica_state,id".')
@api_versions.wraps("2.11") @api_versions.wraps("2.11")
def do_share_replica_list(cs, args): def do_share_replica_list(cs, args):
"""List share replicas (Experimental).""" """List share replicas."""
share = _find_share(cs, args.share_id) if args.share_id else None share = _find_share(cs, args.share_id) if args.share_id else None
if args.columns is not None: if args.columns is not None:
@ -5389,7 +5389,7 @@ def do_share_replica_list(cs, args):
help='Optional Availability zone in which replica should be created.') help='Optional Availability zone in which replica should be created.')
@api_versions.wraps("2.11") @api_versions.wraps("2.11")
def do_share_replica_create(cs, args): def do_share_replica_create(cs, args):
"""Create a share replica (Experimental).""" """Create a share replica."""
share = _find_share(cs, args.share) share = _find_share(cs, args.share)
replica = cs.share_replicas.create(share, args.availability_zone) replica = cs.share_replicas.create(share, args.availability_zone)
@ -5402,7 +5402,7 @@ def do_share_replica_create(cs, args):
help='ID of the share replica.') help='ID of the share replica.')
@api_versions.wraps("2.11", "2.46") @api_versions.wraps("2.11", "2.46")
def do_share_replica_show(cs, args): def do_share_replica_show(cs, args):
"""Show details about a replica (Experimental).""" """Show details about a replica."""
replica = cs.share_replicas.get(args.replica) replica = cs.share_replicas.get(args.replica)
_print_share_replica(cs, replica) _print_share_replica(cs, replica)
@ -5414,7 +5414,7 @@ def do_share_replica_show(cs, args):
metavar='<replica>', metavar='<replica>',
help='ID of the share replica.') help='ID of the share replica.')
def do_share_replica_show(cs, args): # noqa def do_share_replica_show(cs, args): # noqa
"""Show details about a replica (Experimental).""" """Show details about a replica."""
replica = cs.share_replicas.get(args.replica) replica = cs.share_replicas.get(args.replica)
export_locations = cs.share_replica_export_locations.list(replica) export_locations = cs.share_replica_export_locations.list(replica)
@ -5436,7 +5436,7 @@ def do_share_replica_show(cs, args): # noqa
'is not cleaned up on the backend. Defaults to False.') 'is not cleaned up on the backend. Defaults to False.')
@api_versions.wraps("2.11") @api_versions.wraps("2.11")
def do_share_replica_delete(cs, args): def do_share_replica_delete(cs, args):
"""Remove one or more share replicas (Experimental).""" """Remove one or more share replicas."""
failure_count = 0 failure_count = 0
kwargs = { kwargs = {
"force": args.force "force": args.force
@ -5462,13 +5462,12 @@ def do_share_replica_delete(cs, args):
help='ID of the share replica.') help='ID of the share replica.')
@api_versions.wraps("2.11") @api_versions.wraps("2.11")
def do_share_replica_promote(cs, args): def do_share_replica_promote(cs, args):
"""Promote specified replica to 'active' replica_state (Experimental).""" """Promote specified replica to 'active' replica_state."""
replica = _find_share_replica(cs, args.replica) replica = _find_share_replica(cs, args.replica)
cs.share_replicas.promote(replica) cs.share_replicas.promote(replica)
@api_versions.wraps("2.47") @api_versions.wraps("2.47")
@api_versions.experimental_api
@cliutils.arg( @cliutils.arg(
'replica', 'replica',
metavar='<replica>', metavar='<replica>',
@ -5481,7 +5480,7 @@ def do_share_replica_promote(cs, args):
help='Comma separated list of columns to be displayed ' help='Comma separated list of columns to be displayed '
'example --columns "id,path,replica_state".') 'example --columns "id,path,replica_state".')
def do_share_replica_export_location_list(cs, args): def do_share_replica_export_location_list(cs, args):
"""List export locations of a share replica (Experimental).""" """List export locations of a share replica."""
if args.columns is not None: if args.columns is not None:
list_of_keys = _split_columns(columns=args.columns) list_of_keys = _split_columns(columns=args.columns)
else: else:
@ -5498,7 +5497,6 @@ def do_share_replica_export_location_list(cs, args):
@api_versions.wraps("2.47") @api_versions.wraps("2.47")
@api_versions.experimental_api
@cliutils.arg( @cliutils.arg(
'replica', 'replica',
metavar='<replica>', metavar='<replica>',
@ -5508,7 +5506,7 @@ def do_share_replica_export_location_list(cs, args):
metavar='<export_location>', metavar='<export_location>',
help='ID of the share instance export location.') help='ID of the share instance export location.')
def do_share_replica_export_location_show(cs, args): def do_share_replica_export_location_show(cs, args):
"""Show details of a share replica's export location (Experimental).""" """Show details of a share replica's export location."""
replica = _find_share_replica(cs, args.replica) replica = _find_share_replica(cs, args.replica)
export_location = cs.share_replica_export_locations.get( export_location = cs.share_replica_export_locations.get(
replica, args.export_location) replica, args.export_location)
@ -5529,7 +5527,7 @@ def do_share_replica_export_location_show(cs, args):
'state is provided, available will be used.')) 'state is provided, available will be used.'))
@api_versions.wraps("2.11") @api_versions.wraps("2.11")
def do_share_replica_reset_state(cs, args): def do_share_replica_reset_state(cs, args):
"""Explicitly update the 'status' of a share replica (Experimental).""" """Explicitly update the 'status' of a share replica."""
replica = _find_share_replica(cs, args.replica) replica = _find_share_replica(cs, args.replica)
cs.share_replicas.reset_state(replica, args.state) cs.share_replicas.reset_state(replica, args.state)
@ -5550,10 +5548,7 @@ def do_share_replica_reset_state(cs, args):
'state is provided, out_of_sync will be used.')) 'state is provided, out_of_sync will be used.'))
@api_versions.wraps("2.11") @api_versions.wraps("2.11")
def do_share_replica_reset_replica_state(cs, args): def do_share_replica_reset_replica_state(cs, args):
"""Explicitly update the 'replica_state' of a share replica """Explicitly update the 'replica_state' of a share replica."""
(Experimental).
"""
replica = _find_share_replica(cs, args.replica) replica = _find_share_replica(cs, args.replica)
cs.share_replicas.reset_replica_state(replica, args.replica_state) cs.share_replicas.reset_replica_state(replica, args.replica_state)
@ -5564,10 +5559,7 @@ def do_share_replica_reset_replica_state(cs, args):
help='ID of the share replica to resync.') help='ID of the share replica to resync.')
@api_versions.wraps("2.11") @api_versions.wraps("2.11")
def do_share_replica_resync(cs, args): def do_share_replica_resync(cs, args):
"""Attempt to update the share replica with its 'active' mirror """Attempt to update the share replica with its 'active' mirror."""
(Experimental).
"""
replica = _find_share_replica(cs, args.replica) replica = _find_share_replica(cs, args.replica)
cs.share_replicas.resync(replica) cs.share_replicas.resync(replica)

View File

@ -0,0 +1,9 @@
---
prelude: >
- |
Share replication APIs have graduated from their `experimental feature
state <https://docs.openstack.org/manila/latest/contributor/experimental_apis.html>`_
from API version ``2.56``. One or more share replicas can be created from a
given share. They can also be promoted to be considered the active share,
resynchronized and deleted. These actions no longer require the inclusion of
``X-OpenStack-Manila-API-Experimental`` header in the API requests.