# 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. import logging from openstackclient.identity import common as identity_common from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils as osc_utils from oslo_utils import uuidutils from manilaclient.common._i18n import _ from manilaclient.common.apiclient import utils as apiutils from manilaclient.common import constants LOG = logging.getLogger(__name__) LOCK_DETAIL_ATTRIBUTES = [ 'ID', 'Resource Id', 'Resource Type', 'Resource Action', 'Lock Context', 'User Id', 'Project Id', 'Created At', 'Updated At', 'Lock Reason', ] LOCK_SUMMARY_ATTRIBUTES = [ 'ID', 'Resource Id', 'Resource Type', 'Resource Action', ] RESOURCE_TYPE_MANAGERS = { 'share': 'shares', 'access_rule': 'share_access_rules' } class CreateResourceLock(command.ShowOne): """Create a new resource lock.""" _description = _("Lock a resource action from occurring on a resource") def get_parser(self, prog_name): parser = super(CreateResourceLock, self).get_parser(prog_name) parser.add_argument( 'resource', metavar='', help='Name or ID of resource to lock.') parser.add_argument( 'resource_type', metavar='', help='Type of the resource (e.g.: share, access).') parser.add_argument( '--resource-action', '--resource_action', metavar='', default='delete', help='Action to lock on the resource (default="delete")') parser.add_argument( '--lock-reason', '--lock_reason', '--reason', metavar='', help='Reason for the resource lock.') return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share resource_type = parsed_args.resource_type if resource_type not in RESOURCE_TYPE_MANAGERS: raise exceptions.CommandError(_("Unsupported resource type")) res_manager = RESOURCE_TYPE_MANAGERS[resource_type] resource = osc_utils.find_resource(getattr(share_client, res_manager), parsed_args.resource) resource_lock = share_client.resource_locks.create( resource.id, resource_type, parsed_args.resource_action, parsed_args.lock_reason ) resource_lock._info.pop('links', None) return self.dict2columns(resource_lock._info) class DeleteResourceLock(command.Command): """Remove one or more resource locks.""" _description = _("Remove one or more resource locks") def get_parser(self, prog_name): parser = super(DeleteResourceLock, self).get_parser(prog_name) parser.add_argument( 'lock', metavar='', nargs='+', help='ID(s) of the lock(s).') return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share failure_count = 0 for lock in parsed_args.lock: try: lock = apiutils.find_resource( share_client.resource_locks, lock ) lock.delete() except Exception as e: failure_count += 1 LOG.error(_( "Failed to delete %(lock)s: %(e)s"), {'lock': lock, 'e': e}) if failure_count > 0: raise exceptions.CommandError(_( "Unable to delete some or all of the specified locks.")) class ListResourceLock(command.Lister): """Lists all resource locks.""" _description = _("Lists all resource locks") def get_parser(self, prog_name): parser = super(ListResourceLock, self).get_parser(prog_name) parser.add_argument( '--all-projects', action='store_true', help=_("Filter resource locks for all projects. (Admin only).") ) parser.add_argument( '--project', default=None, help=_("Filter resource locks for specific project by name or ID, " "combine with --all-projects (Admin only).") ) parser.add_argument( '--user', default=None, help=_("Filter resource locks for specific user by name or ID, " "combine with --all-projects to search across projects " "(Admin only).") ) parser.add_argument( '--id', metavar='', default=None, help='Filter resource locks by ID. Default=None.') parser.add_argument( '--resource', '--resource-id', '--resource_id', default=None, metavar='', dest='resource', help=_("Filter resource locks for a resource by ID, specify " "--resource-type to look up by name.") ) parser.add_argument( '--resource-type', '--resource_type', default=None, metavar='', help=_("Filter resource locks by type of resource.") ) parser.add_argument( '--resource-action', '--resource_action', default=None, metavar='', help=_("Filter resource locks by resource action.") ) parser.add_argument( '--lock-context', '--lock_context', '--context', default=None, choices=['user', 'admin', 'service'], metavar='', help=_("Filter resource locks by context.") ) parser.add_argument( '--since', default=None, metavar='', help=_("Filter resource locks created since given date. " "The date format must be conforming to ISO8601. ") ) parser.add_argument( '--before', default=None, metavar='', help=_("Filter resource locks created before given date. " "The date format must be conforming to ISO8601. ") ) parser.add_argument( '--limit', metavar='', type=int, default=None, help=_("Number of resource locks to list. (Default=None)")) parser.add_argument( '--offset', metavar="", default=None, help='Starting position of resource lock records ' 'in a paginated list.') parser.add_argument( '--sort-key', '--sort_key', metavar='', type=str, default=None, choices=constants.RESOURCE_LOCK_SORT_KEY_VALUES, help='Key to be sorted, available keys are %(keys)s. ' 'Default=None.' % {'keys': constants.RESOURCE_LOCK_SORT_KEY_VALUES}) parser.add_argument( '--sort-dir', '--sort_dir', metavar='', type=str, default=None, choices=constants.SORT_DIR_VALUES, help='Sort direction, available values are %(values)s. ' 'OPTIONAL: Default=None.' % { 'values': constants.SORT_DIR_VALUES}) parser.add_argument( '--detailed', dest='detailed', metavar='<0|1>', nargs='?', type=int, const=1, default=0, help="Show detailed information about filtered resource locks.") return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share columns = ( LOCK_SUMMARY_ATTRIBUTES if not parsed_args.detailed else LOCK_DETAIL_ATTRIBUTES ) project_id = None user_id = None if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain).id if parsed_args.user: user_id = identity_common.find_user(identity_client, parsed_args.user, parsed_args.user_domain).id # set all_projects when using project option all_projects = bool(parsed_args.project) or parsed_args.all_projects resource_id = parsed_args.resource resource_type = parsed_args.resource_type if resource_type is not None: if resource_type not in RESOURCE_TYPE_MANAGERS: raise exceptions.CommandError(_("Unsupported resource type")) if resource_id is not None: res_manager = RESOURCE_TYPE_MANAGERS[resource_type] resource_id = osc_utils.find_resource( getattr(share_client, res_manager), parsed_args.resource ).id elif resource_id and not uuidutils.is_uuid_like(resource_id): raise exceptions.CommandError( _("Provide resource ID or specify --resource-type.")) search_opts = { 'all_projects': all_projects, 'project_id': project_id, 'user_id': user_id, 'id': parsed_args.id, 'resource_id': resource_id, 'resource_type': parsed_args.resource_type, 'resource_action': parsed_args.resource_action, 'lock_context': parsed_args.lock_context, 'created_before': parsed_args.before, 'created_since': parsed_args.since, 'limit': parsed_args.limit, 'offset': parsed_args.offset, } resource_locks = share_client.resource_locks.list( search_opts=search_opts, sort_key=parsed_args.sort_key, sort_dir=parsed_args.sort_dir ) return (columns, (osc_utils.get_item_properties (m, columns) for m in resource_locks)) class ShowResourceLock(command.ShowOne): """Show details about a resource lock.""" _description = _("Show details about a resource lock") def get_parser(self, prog_name): parser = super(ShowResourceLock, self).get_parser(prog_name) parser.add_argument( 'lock', metavar='', help=_('ID of resource lock to show.')) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share resource_lock = apiutils.find_resource( share_client.resource_locks, parsed_args.lock) return ( LOCK_DETAIL_ATTRIBUTES, osc_utils.get_dict_properties(resource_lock._info, LOCK_DETAIL_ATTRIBUTES) ) class SetResourceLock(command.Command): """Set resource lock properties.""" _description = _("Update resource lock properties") def get_parser(self, prog_name): parser = super(SetResourceLock, self).get_parser(prog_name) parser.add_argument( 'lock', metavar='', help='ID of lock to update.') parser.add_argument( '--resource-action', '--resource_action', metavar='', help='Resource action to set in the resource lock') parser.add_argument( '--lock-reason', '--lock_reason', '--reason', dest='lock_reason', help="Reason for the resource lock") return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share update_kwargs = {} if parsed_args.resource_action is not None: update_kwargs['resource_action'] = parsed_args.resource_action if parsed_args.lock_reason is not None: update_kwargs['lock_reason'] = parsed_args.lock_reason if update_kwargs: share_client.resource_locks.update( parsed_args.lock, **update_kwargs ) class UnsetResourceLock(command.Command): """Unsets a property on a resource lock.""" _description = _("Remove resource lock properties") def get_parser(self, prog_name): parser = super(UnsetResourceLock, self).get_parser(prog_name) parser.add_argument( 'lock', metavar='', help='ID of resource lock to update.') parser.add_argument( '--lock-reason', '--lock_reason', '--reason', dest='lock_reason', action='store_true', default=False, help="Unset the lock reason. (Default=False)") return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share if parsed_args.lock_reason: share_client.resource_locks.update( parsed_args.lock, lock_reason=None )