# Copyright 2015 NEC Corporation. All rights reserved. # # 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 json import os from osc_lib.command import command from osc_lib import utils from oslo_log import log as logging from zaqarclient._i18n import _ from zaqarclient.queues.v1 import cli def _get_client(obj, parsed_args): obj.log.debug("take_action(%s)" % parsed_args) return obj.app.client_manager.messaging class CreateQueue(cli.CreateQueue): """Create a queue""" pass class OldCreateQueue(cli.OldCreateQueue): """Create a queue""" pass class DeleteQueue(cli.DeleteQueue): """Delete a queue""" pass class OldDeleteQueue(cli.OldDeleteQueue): """Delete a queue""" pass class ListQueues(command.Lister): """List available queues""" _description = _("List available queues") log = logging.getLogger(__name__ + ".ListQueues") def get_parser(self, prog_name): parser = super(ListQueues, self).get_parser(prog_name) parser.add_argument( "--marker", metavar="", help="Queue's paging marker") parser.add_argument( "--limit", metavar="", help="Page size limit") parser.add_argument( "--detailed", action="store_true", help="If show detailed information of queue") parser.add_argument( "--with_count", action="store_true", help="If show amount information of queue") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) kwargs = {} columns = ["Name"] if parsed_args.marker is not None: kwargs["marker"] = parsed_args.marker if parsed_args.limit is not None: kwargs["limit"] = parsed_args.limit if parsed_args.detailed is not None and parsed_args.detailed: kwargs["detailed"] = parsed_args.detailed columns.extend(["Metadata_Dict", "Href"]) if parsed_args.with_count is not None and parsed_args.with_count: kwargs["with_count"] = parsed_args.with_count data, count = client.queues(**kwargs) if count: print("Queues in total: %s" % count) columns = tuple(columns) return (columns, (utils.get_item_properties(s, columns) for s in data)) class OldListQueues(cli.OldListQueues): """List available queues""" pass class GetQueueStats(cli.GetQueueStats): """Get queue stats""" pass class OldGetQueueStats(cli.OldGetQueueStats): """Get queue stats""" pass class SetQueueMetadata(command.Command): """Set queue metadata""" _description = _("Set queue metadata") log = logging.getLogger(__name__ + ".SetQueueMetadata") def get_parser(self, prog_name): parser = super(SetQueueMetadata, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") parser.add_argument( "queue_metadata", metavar="", help="Queue metadata, All the metadata of " "the queue will be replaced by queue_metadata") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) queue_name = parsed_args.queue_name queue_metadata = parsed_args.queue_metadata if (client.api_version == 1 and not client.queue(queue_name, auto_create=False).exists()): raise RuntimeError("Queue(%s) does not exist." % queue_name) try: valid_metadata = json.loads(queue_metadata) except ValueError: raise RuntimeError("Queue metadata(%s) is not a valid json." % queue_metadata) client.queue(queue_name, auto_create=False).\ metadata(new_meta=valid_metadata) class OldSetQueueMetadata(cli.OldSetQueueMetadata): """Set queue metadata""" pass class GetQueueMetadata(cli.GetQueueMetadata): """Get queue metadata""" pass class OldGetQueueMetadata(cli.OldGetQueueMetadata): """Get queue metadata""" pass class PostMessages(command.Command): """Post messages for a given queue""" _description = _("Post messages for a given queue") log = logging.getLogger(__name__ + ".PostMessages") def get_parser(self, prog_name): parser = super(PostMessages, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") parser.add_argument( "messages", type=json.loads, metavar="", help="Messages to be posted.") parser.add_argument( "--client-id", metavar="", default=os.environ.get("OS_MESSAGE_CLIENT_ID"), help="A UUID for each client instance.") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) if not parsed_args.client_id: raise AttributeError("<--client-id> option is missing and " "environment variable OS_MESSAGE_CLIENT_ID " "is not set. Please at least either pass in " "the client id or set the environment " "variable") else: client.client_uuid = parsed_args.client_id queue = client.queue(parsed_args.queue_name) queue.post(parsed_args.messages) class OldPostMessages(PostMessages): """Post messages for a given queue""" _description = _("Post messages for a given queue") # TODO(wanghao): Remove this class and ``message post`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging message post" ' 'instead.')) return super(OldPostMessages, self).take_action(parsed_args) class ListMessages(command.Lister): """List all messages for a given queue""" _description = _("List all messages for a given queue") log = logging.getLogger(__name__ + ".ListMessages") def get_parser(self, prog_name): parser = super(ListMessages, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") parser.add_argument( "--message-ids", metavar="", help="List of messages' ids to retrieve") parser.add_argument( "--limit", metavar="", type=int, help="Maximum number of messages to get") parser.add_argument( "--echo", action="store_true", help="Whether to get this client's own messages") parser.add_argument( "--include-claimed", action="store_true", help="Whether to include claimed messages") parser.add_argument( "--include-delayed", action="store_true", help="Whether to include delayed messages") parser.add_argument( "--client-id", metavar="", default=os.environ.get("OS_MESSAGE_CLIENT_ID"), help="A UUID for each client instance.") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) if not parsed_args.client_id: raise AttributeError("<--client-id> option is missing and " "environment variable OS_MESSAGE_CLIENT_ID " "is not set. Please at least either pass in " "the client id or set the environment " "variable") else: client.client_uuid = parsed_args.client_id kwargs = {} if parsed_args.limit is not None: kwargs["limit"] = parsed_args.limit if parsed_args.echo is not None: kwargs["echo"] = parsed_args.echo if parsed_args.include_claimed is not None: kwargs["include_claimed"] = parsed_args.include_claimed if parsed_args.include_delayed is not None: kwargs["include_delayed"] = parsed_args.include_delayed queue = client.queue(parsed_args.queue_name) if parsed_args.message_ids: messages = queue.messages(parsed_args.message_ids.split(','), **kwargs) else: messages = queue.messages(**kwargs) columns = ("ID", "Body", "TTL", "Age", "Claim ID", "Checksum") return (columns, (utils.get_item_properties(s, columns) for s in messages)) class OldListMessages(ListMessages): """List all messages for a given queue""" _description = _("List all messages for a given queue") # TODO(wanghao): Remove this class and ``message list`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging message list" ' 'instead.')) return super(OldListMessages, self).take_action(parsed_args) class PurgeQueue(command.Command): """Purge a queue""" _description = _("Purge a queue") log = logging.getLogger(__name__ + ".PurgeQueue") def get_parser(self, prog_name): parser = super(PurgeQueue, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") parser.add_argument( "--resource_types", metavar="", action='append', choices=['messages', 'subscriptions'], help="Resource types want to be purged.") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) queue_name = parsed_args.queue_name client.queue(queue_name).purge( resource_types=parsed_args.resource_types) class OldPurgeQueue(PurgeQueue): """Purge a queue""" _description = _("Purge a queue") # TODO(wanghao): Remove this class and ``queue purge`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging queue purge" ' 'instead.')) return super(OldPurgeQueue, self).take_action(parsed_args) class CreatePool(cli.CreatePool): """Create a pool""" pass class OldCreatePool(cli.OldCreatePool): """Create a pool""" pass class ShowPool(cli.ShowPool): """Display pool details""" pass class OldShowPool(cli.OldShowPool): """Display pool details""" pass class UpdatePool(cli.UpdatePool): """Update a pool attribute""" pass class OldUpdatePool(cli.OldUpdatePool): """Update a pool attribute""" pass class DeletePool(cli.DeletePool): """Delete a pool""" pass class OldDeletePool(cli.OldDeletePool): """Delete a pool""" pass class ListPools(cli.ListPools): """List available Pools""" pass class OldListPools(cli.OldListPools): """List available Pools""" pass class DeleteFlavor(cli.DeleteFlavor): """Delete a flavor""" pass class ShowFlavor(cli.ShowFlavor): """Display flavor details""" pass class UpdateFlavor(cli.UpdateFlavor): """Update a flavor's attributes""" pass class CreateFlavor(cli.CreateFlavor): """Create a pool flavor""" def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) client = self.app.client_manager.messaging kwargs = {} if parsed_args.capabilities != {}: raise AttributeError("<--capabilities> option is only\ available in client api version < 2") pool_list = None if parsed_args.pool_list: pool_list = parsed_args.pool_list.split(',') data = client.flavor(parsed_args.flavor_name, pool_list=pool_list, **kwargs) columns = ('Name', 'Pool list', 'Capabilities') return columns, utils.get_item_properties(data, columns) class ListFlavors(cli.ListFlavors): """List available flavors""" pass class CreateSubscription(command.ShowOne): """Create a subscription for queue""" _description = _("Create a subscription for queue") log = logging.getLogger(__name__ + ".CreateSubscription") def get_parser(self, prog_name): parser = super(CreateSubscription, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue to subscribe to") parser.add_argument( "subscriber", metavar="", help="Subscriber which will be notified") parser.add_argument( "ttl", metavar="", type=int, help="Time to live of the subscription in seconds") parser.add_argument( "--options", type=json.loads, default={}, metavar="", help="Metadata of the subscription in JSON format") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) kwargs = {'options': parsed_args.options} if parsed_args.subscriber: kwargs['subscriber'] = parsed_args.subscriber if parsed_args.subscriber: kwargs['ttl'] = parsed_args.ttl data = client.subscription(parsed_args.queue_name, **kwargs) if not data: raise RuntimeError('Failed to create subscription for (%s).' % parsed_args.subscriber) columns = ('ID', 'Subscriber', 'TTL', 'Options') return columns, utils.get_item_properties(data, columns) class OldCreateSubscription(CreateSubscription): """Create a subscription for queue""" _description = _("Create a subscription for queue") # TODO(wanghao): Remove this class and ``subscription create`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging subscription create" ' 'instead.')) return super(OldCreateSubscription, self).take_action(parsed_args) class UpdateSubscription(command.ShowOne): """Update a subscription""" _description = _("Update a subscription") log = logging.getLogger(__name__ + ".UpdateSubscription") def get_parser(self, prog_name): parser = super(UpdateSubscription, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue to subscribe to") parser.add_argument( "subscription_id", metavar="", help="ID of the subscription" ) parser.add_argument( "--subscriber", metavar="", help="Subscriber which will be notified") parser.add_argument( "--ttl", metavar="", type=int, help="Time to live of the subscription in seconds") parser.add_argument( "--options", type=json.loads, default={}, metavar="", help="Metadata of the subscription in JSON format") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) data = {'subscriber': parsed_args.subscriber, 'ttl': parsed_args.ttl, 'options': parsed_args.options} kwargs = {'id': parsed_args.subscription_id} subscription = client.subscription(parsed_args.queue_name, auto_create=False, **kwargs) subscription.update(data) columns = ('ID', 'Subscriber', 'TTL', 'Options') return columns, utils.get_item_properties(data, columns) class OldUpdateSubscription(UpdateSubscription): """Update a subscription""" _description = _("Update a subscription") # TODO(wanghao): Remove this class and ``subscription update`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging subscription update" ' 'instead.')) return super(OldUpdateSubscription, self).take_action(parsed_args) class DeleteSubscription(command.Command): """Delete a subscription""" _description = _("Delete a subscription") log = logging.getLogger(__name__ + ".DeleteSubscription") def get_parser(self, prog_name): parser = super(DeleteSubscription, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue for the subscription") parser.add_argument( "subscription_id", metavar="", help="ID of the subscription" ) return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) client.subscription(parsed_args.queue_name, id=parsed_args.subscription_id, auto_create=False).delete() class OldDeleteSubscription(DeleteSubscription): """Delete a subscription""" _description = _("Delete a subscription") # TODO(wanghao): Remove this class and ``subscription delete`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging subscription delete" ' 'instead.')) return super(OldDeleteSubscription, self).take_action(parsed_args) class ShowSubscription(command.ShowOne): """Display subscription details""" _description = _("Display subscription details") log = logging.getLogger(__name__ + ".ShowSubscription") def get_parser(self, prog_name): parser = super(ShowSubscription, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue to subscribe to" ) parser.add_argument( "subscription_id", metavar="", help="ID of the subscription" ) return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) kwargs = {'id': parsed_args.subscription_id} pool_data = client.subscription(parsed_args.queue_name, **kwargs) columns = ('ID', 'Subscriber', 'TTL', 'Age', 'Confirmed', 'Options') return columns, utils.get_dict_properties(pool_data.__dict__, columns) class OldShowSubscription(ShowSubscription): """Display subscription details""" _description = _("Display subscription details") # TODO(wanghao): Remove this class and ``subscription show`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging subscription show" ' 'instead.')) return super(OldShowSubscription, self).take_action(parsed_args) class ListSubscriptions(command.Lister): """List available subscriptions""" _description = _("List available subscriptions") log = logging.getLogger(__name__ + ".ListSubscriptions") def get_parser(self, prog_name): parser = super(ListSubscriptions, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue to subscribe to") parser.add_argument( "--marker", metavar="", help="Subscription's paging marker, " "the ID of the last subscription of the previous page") parser.add_argument( "--limit", metavar="", help="Page size limit, default value is 20") return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) client = self.app.client_manager.messaging kwargs = {'queue_name': parsed_args.queue_name} if parsed_args.marker is not None: kwargs["marker"] = parsed_args.marker if parsed_args.limit is not None: kwargs["limit"] = parsed_args.limit data = client.subscriptions(**kwargs) columns = ('ID', 'Subscriber', 'TTL', 'Age', 'Confirmed', 'Options') return (columns, (utils.get_item_properties(s, columns) for s in data)) class OldListSubscriptions(ListSubscriptions): """List available subscriptions""" _description = _("List available subscriptions") # TODO(wanghao): Remove this class and ``subscription list`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging subscription list" ' 'instead.')) return super(OldListSubscriptions, self).take_action(parsed_args) class CreateClaim(cli.CreateClaim): """Create claim and return a list of claimed messages""" def take_action(self, parsed_args): client = _get_client(self, parsed_args) kwargs = {} if parsed_args.ttl is not None: kwargs["ttl"] = parsed_args.ttl if parsed_args.grace is not None: kwargs["grace"] = parsed_args.grace if parsed_args.limit is not None: kwargs["limit"] = parsed_args.limit queue = client.queue(parsed_args.queue_name, auto_create=False) keys = ("claim_id", "id", "ttl", "age", 'body', "checksum") columns = ("Claim_ID", "Message_ID", "TTL", "Age", "Messages", "Checksum") data = queue.claim(**kwargs) return (columns, (utils.get_item_properties(s, keys) for s in data)) class OldCreateClaim(cli.OldCreateClaim): """Create claim and return a list of claimed messages""" pass class QueryClaim(cli.QueryClaim): """Display claim details""" pass class OldQueryClaim(cli.OldQueryClaim): """Display claim details""" pass class RenewClaim(cli.RenewClaim): """Renew a claim""" pass class OldRenewClaim(cli.OldRenewClaim): """Renew a claim""" pass class ReleaseClaim(cli.ReleaseClaim): """Delete a claim""" pass class OldReleaseClaim(cli.OldReleaseClaim): """Delete a claim""" pass class CreateSignedUrl(command.ShowOne): """Create a pre-signed url""" _description = _("Create a pre-signed url") log = logging.getLogger(__name__ + ".CreateSignedUrl") def get_parser(self, prog_name): parser = super(CreateSignedUrl, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") parser.add_argument( "--paths", metavar="", default="messages", help="Allowed paths in a comma-separated list. " "Options: messages, subscriptions, claims") parser.add_argument( "--ttl-seconds", metavar="", type=int, help="Length of time (in seconds) until the signature expires") parser.add_argument( "--methods", metavar="", default="GET", help="HTTP methods to allow as a comma-separated list. " "Options: GET, HEAD, OPTIONS, POST, PUT, DELETE") return parser allowed_paths = ("messages", "subscriptions", "claims") def take_action(self, parsed_args): client = self.app.client_manager.messaging queue = client.queue(parsed_args.queue_name, auto_create=False) paths = parsed_args.paths.split(',') if not all([p in self.allowed_paths for p in paths]): print("Invalid path supplied! Received {}. " "Valid paths are: messages, subscriptions, " "claims".format(','.join(paths))) kwargs = { 'methods': parsed_args.methods.split(','), 'paths': paths, } if parsed_args.ttl_seconds: kwargs['ttl_seconds'] = parsed_args.ttl_seconds data = queue.signed_url(**kwargs) fields = ('Paths', 'Methods', 'Expires', 'Signature', 'Project ID') return fields, ( ','.join(data['paths']), ','.join(data['methods']), data['expires'], data['signature'], data['project'] ) class OldCreateSignedUrl(CreateSignedUrl): """Create a pre-signed url""" _description = _("Create a pre-signed url") # TODO(wanghao): Remove this class and ``queue signed url`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging queue signed url" ' 'instead.')) return super(OldCreateSignedUrl, self).take_action(parsed_args) class Ping(command.ShowOne): """Check if Zaqar server is alive or not""" _description = _("Check if Zaqar server is alive or not") log = logging.getLogger(__name__ + ".Ping") def take_action(self, parsed_args): client = _get_client(self, parsed_args) columns = ('Pingable', ) return columns, utils.get_dict_properties({'pingable': client.ping()}, columns) class Health(command.Command): """Display detailed health status of Zaqar server""" _description = _("Display detailed health status of Zaqar server") log = logging.getLogger(__name__ + ".Health") def take_action(self, parsed_args): client = _get_client(self, parsed_args) health = client.health() print(json.dumps(health, indent=4, sort_keys=True)) class HomeDoc(command.Command): """Display the resource doc of Zaqar server""" _description = _("Display detailed resource doc of Zaqar server") log = logging.getLogger(__name__ + ".HomeDoc") def take_action(self, parsed_args): client = _get_client(self, parsed_args) homedoc = client.homedoc() print(json.dumps(homedoc, indent=4, sort_keys=True))