def take_action(self, parsed_args): network_client = self.app.client_manager.network try: # Verify that the extension exists. network_client.find_extension('network-segment-range', ignore_missing=False) except Exception as e: msg = (_('Network segment range create not supported by ' 'Network API: %(e)s') % {'e': e}) raise exceptions.CommandError(msg) identity_client = self.app.client_manager.identity if not parsed_args.private and parsed_args.project: msg = _("--project is only allowed with --private") raise exceptions.CommandError(msg) if (parsed_args.network_type.lower() != 'vlan' and parsed_args.physical_network): msg = _("--physical-network is only allowed with --network-type " "vlan") raise exceptions.CommandError(msg) attrs = {} if parsed_args.shared or parsed_args.private: attrs['shared'] = parsed_args.shared else: # default to be ``shared`` if not specified attrs['shared'] = True attrs['network_type'] = parsed_args.network_type attrs['minimum'] = parsed_args.minimum attrs['maximum'] = parsed_args.maximum if parsed_args.name: attrs['name'] = parsed_args.name if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id if project_id: attrs['project_id'] = project_id else: msg = (_("Failed to create the network segment range for " "project %(project_id)s") % parsed_args.project_id) raise exceptions.CommandError(msg) elif not attrs['shared']: # default to the current project if no project specified and shared # is not specified. # Get the project id from the current auth. attrs['project_id'] = self.app.client_manager.auth_ref.project_id if parsed_args.physical_network: attrs['physical_network'] = parsed_args.physical_network obj = network_client.create_network_segment_range(**attrs) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) data = _update_additional_fields_from_props(columns, props=data) return (display_columns, data)
def get_parser(self, prog_name): parser = super(ListUser, self).get_parser(prog_name) parser.add_argument( '--domain', metavar='<domain>', help=_('Filter users by <domain> (name or ID)'), ) project_or_group = parser.add_mutually_exclusive_group() project_or_group.add_argument( '--group', metavar='<group>', help=_('Filter users by <group> membership (name or ID)'), ) project_or_group.add_argument( '--project', metavar='<project>', help=_('Filter users by <project> (name or ID)'), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) return parser
def get_parser(self, prog_name): parser = super(CreateAccessToken, self).get_parser(prog_name) parser.add_argument( '--consumer-key', metavar='<consumer-key>', help=_('Consumer key (required)'), required=True ) parser.add_argument( '--consumer-secret', metavar='<consumer-secret>', help=_('Consumer secret (required)'), required=True ) parser.add_argument( '--request-key', metavar='<request-key>', help=_('Request token to exchange for access token (required)'), required=True ) parser.add_argument( '--request-secret', metavar='<request-secret>', help=_('Secret associated with <request-key> (required)'), required=True ) parser.add_argument( '--verifier', metavar='<verifier>', help=_('Verifier associated with <request-key> (required)'), required=True ) return parser
def take_action(self, parsed_args): network_client = self.app.client_manager.network try: # Verify that the extension exists. network_client.find_extension('network-segment-range', ignore_missing=False) except Exception as e: msg = (_('Network segment range delete not supported by ' 'Network API: %(e)s') % {'e': e}) raise exceptions.CommandError(msg) result = 0 for network_segment_range in parsed_args.network_segment_range: try: obj = network_client.find_network_segment_range( network_segment_range, ignore_missing=False) network_client.delete_network_segment_range(obj) except Exception as e: result += 1 LOG.error(_("Failed to delete network segment range with " "ID '%(network_segment_range)s': %(e)s"), {'network_segment_range': network_segment_range, 'e': e}) if result > 0: total = len(parsed_args.network_segment_range) msg = (_("%(result)s of %(total)s network segment ranges failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg)
def get_parser(self, prog_name): parser = super(UpdateOvercloud, self).get_parser(prog_name) parser.add_argument('stack', nargs='?', help=_('Name or ID of heat stack to scale ' '(default=Env: OVERCLOUD_STACK_NAME)'), default=utils.env('OVERCLOUD_STACK_NAME')) parser.add_argument( '--templates', nargs='?', const=constants.TRIPLEO_HEAT_TEMPLATES, help=_("The directory containing the Heat templates to deploy"), ) parser.add_argument('-i', '--interactive', dest='interactive', action='store_true') parser.add_argument('-a', '--abort', dest='abort_update', action='store_true') parser.add_argument( '-e', '--environment-file', metavar='<HEAT ENVIRONMENT FILE>', action='append', dest='environment_files', help=_('Environment files to be passed to the heat stack-create ' 'or heat stack-update command. (Can be specified more than ' 'once.)') ) parser.add_argument( '--answers-file', help=_('Path to a YAML file with arguments and parameters.') ) return parser
def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume = utils.find_resource(volume_client.volumes, parsed_args.volume) if parsed_args.size: if volume.status != 'available': LOG.error(_("Volume is in %s state, it must be available " "before size can be extended"), volume.status) return if parsed_args.size <= volume.size: LOG.error(_("New size must be greater than %s GB"), volume.size) return volume_client.volumes.extend(volume.id, parsed_args.size) if parsed_args.property: volume_client.volumes.set_metadata(volume.id, parsed_args.property) if parsed_args.image_property: volume_client.volumes.set_image_metadata( volume.id, parsed_args.image_property) kwargs = {} if parsed_args.name: kwargs['display_name'] = parsed_args.name if parsed_args.description: kwargs['display_description'] = parsed_args.description if kwargs: volume_client.volumes.update(volume.id, **kwargs)
def get_parser(self, prog_name): parser = super(CreateRequestToken, self).get_parser(prog_name) parser.add_argument( '--consumer-key', metavar='<consumer-key>', help=_('Consumer key (required)'), required=True ) parser.add_argument( '--consumer-secret', metavar='<consumer-secret>', help=_('Consumer secret (required)'), required=True ) parser.add_argument( '--project', metavar='<project>', help=_('Project that consumer wants to access (name or ID)' ' (required)'), required=True ) parser.add_argument( '--domain', metavar='<domain>', help=_('Domain owning <project> (name or ID)'), ) return parser
def get_parser(self, prog_name): parser = super(SetNetworkQosPolicy, self).get_parser(prog_name) parser.add_argument( 'policy', metavar="<qos-policy>", help=_("QoS policy to modify (name or ID)") ) parser.add_argument( '--name', metavar="<name>", help=_('Set QoS policy name') ) parser.add_argument( '--description', metavar='<description>', help=_("Description of the QoS policy") ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--share', action='store_true', help=_('Make the QoS policy accessible by other projects'), ) enable_group.add_argument( '--no-share', action='store_true', help=_('Make the QoS policy not accessible by other projects'), ) return parser
def get_parser(self, prog_name): parser = super(CreateNetworkQosPolicy, self).get_parser(prog_name) parser.add_argument( 'name', metavar='<name>', help=_("Name of QoS policy to create") ) parser.add_argument( '--description', metavar='<description>', help=_("Description of the QoS policy") ) share_group = parser.add_mutually_exclusive_group() share_group.add_argument( '--share', action='store_true', default=None, help=_("Make the QoS policy accessible by other projects") ) share_group.add_argument( '--no-share', action='store_true', help=_("Make the QoS policy not accessible by other projects " "(default)") ) parser.add_argument( '--project', metavar='<project>', help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) return parser
def get_parser(self, prog_name): parser = super(SetDomain, self).get_parser(prog_name) parser.add_argument( 'domain', metavar='<domain>', help=_('Domain to modify (name or ID)'), ) parser.add_argument( '--name', metavar='<name>', help=_('New domain name'), ) parser.add_argument( '--description', metavar='<description>', help=_('New domain description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable domain'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable domain'), ) return parser
def get_parser(self, prog_name): parser = super(CreateDomain, self).get_parser(prog_name) parser.add_argument( 'name', metavar='<domain-name>', help=_('New domain name'), ) parser.add_argument( '--description', metavar='<description>', help=_('New domain description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable domain (default)'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable domain'), ) parser.add_argument( '--or-show', action='store_true', help=_('Return existing domain'), ) return parser
def get_parser(self, prog_name): parser = super(CreateService, self).get_parser(prog_name) parser.add_argument( 'type', metavar='<type>', help=_('New service type (compute, image, identity, volume, etc)'), ) parser.add_argument( '--name', metavar='<name>', help=_('New service name'), ) parser.add_argument( '--description', metavar='<description>', help=_('New service description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable service (default)'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable service'), ) return parser
def get_parser(self, prog_name): parser = super(ListVolumeBackup, self).get_parser(prog_name) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( "--name", metavar="<name>", help=_("Filters results by the backup name") ) parser.add_argument( "--status", metavar="<status>", choices=['creating', 'available', 'deleting', 'error', 'restoring', 'error_restoring'], help=_("Filters results by the backup status " "('creating', 'available', 'deleting', " "'error', 'restoring' or 'error_restoring')") ) parser.add_argument( "--volume", metavar="<volume>", help=_("Filters results by the volume which they " "backup (name or ID)") ) parser.add_argument( '--all-projects', action='store_true', default=False, help=_('Include all projects (admin only)'), ) return parser
def get_parser(self, prog_name): parser = super(UpgradeOvercloud, self).get_parser(prog_name) parser.add_argument( 'stage', metavar="<prepare|start|finish>", choices=['prepare', 'start', 'finish'], help=_('Stage of upgrade to perform.') ) parser.add_argument( '--stack', dest='stack', help=_('Name or ID of heat stack to upgrade ' '(default=Env: OVERCLOUD_STACK_NAME)'), default=utils.env('OVERCLOUD_STACK_NAME')) parser.add_argument( '-e', '--environment-file', metavar='<HEAT ENVIRONMENT FILE>', action='append', dest='environment_files', help=_('Environment files to be passed to the heat stack-update ' 'command. (Can be specified more than once.)') ) template_group = parser.add_mutually_exclusive_group(required=True) template_group.add_argument( '--templates', nargs='?', const=constants.TRIPLEO_HEAT_TEMPLATES, help=_("The directory containing the Heat templates used for " "the upgraded deployment. Cannot be specified with " "--answers-file."), ) template_group.add_argument( '--answers-file', help=_('Path to a YAML file with arguments and parameters. Cannot ' 'be used with --templates.') ) return parser
def take_action(self, parsed_args): ret = 0 resources = getattr(parsed_args, self.resource, []) for r in resources: self.r = r try: if self.app.client_manager.is_network_endpoint_enabled(): self.take_action_network(self.app.client_manager.network, parsed_args) else: self.take_action_compute(self.app.client_manager.compute, parsed_args) except Exception as e: msg = _("Failed to delete %(resource)s with name or ID " "'%(name_or_id)s': %(e)s") % { "resource": self.resource, "name_or_id": r, "e": e, } LOG.error(msg) ret += 1 if ret: total = len(resources) msg = _("%(num)s of %(total)s %(resource)ss failed to delete.") % { "num": ret, "total": total, "resource": self.resource, } raise exceptions.CommandError(msg)
def take_action(self, parsed_args): identity_client = self.app.client_manager.identity domain = None if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain) errors = 0 for user in parsed_args.users: try: if domain is not None: user_obj = utils.find_resource(identity_client.users, user, domain_id=domain.id) else: user_obj = utils.find_resource(identity_client.users, user) identity_client.users.delete(user_obj.id) except Exception as e: errors += 1 LOG.error(_("Failed to delete user with " "name or ID '%(user)s': %(e)s"), {'user': user, 'e': e}) if errors > 0: total = len(parsed_args.users) msg = (_("%(errors)s of %(total)s users failed " "to delete.") % {'errors': errors, 'total': total}) raise exceptions.CommandError(msg)
def add_deployment_plan_arguments(parser): """Add deployment plan arguments (flavors and scales) to a parser""" parser.add_argument('--control-scale', type=int, help=_('New number of control nodes.')) parser.add_argument('--compute-scale', type=int, help=_('New number of compute nodes.')) parser.add_argument('--ceph-storage-scale', type=int, help=_('New number of ceph storage nodes.')) parser.add_argument('--block-storage-scale', type=int, help=_('New number of cinder storage nodes.')) parser.add_argument('--swift-storage-scale', type=int, help=_('New number of swift storage nodes.')) parser.add_argument('--control-flavor', help=_("Nova flavor to use for control nodes.")) parser.add_argument('--compute-flavor', help=_("Nova flavor to use for compute nodes.")) parser.add_argument('--ceph-storage-flavor', help=_("Nova flavor to use for ceph storage " "nodes.")) parser.add_argument('--block-storage-flavor', help=_("Nova flavor to use for cinder storage " "nodes.")) parser.add_argument('--swift-storage-flavor', help=_("Nova flavor to use for swift storage " "nodes."))
def get_parser(self, prog_name): parser = super(ListPort, self).get_parser(prog_name) parser.add_argument( '--device-owner', metavar='<device-owner>', help=_("List only ports with the specified device owner. " "This is the entity that uses the port (for example, " "network:dhcp).") ) parser.add_argument( '--network', metavar='<network>', help=_("List only ports connected to this network (name or ID)")) device_group = parser.add_mutually_exclusive_group() device_group.add_argument( '--router', metavar='<router>', dest='router', help=_("List only ports attached to this router (name or ID)") ) device_group.add_argument( '--server', metavar='<server>', help=_("List only ports attached to this server (name or ID)"), ) parser.add_argument( '--long', action='store_true', default=False, help=_("List additional fields in output") ) return parser
def get_parser(self, prog_name): parser = super(UnsetPort, self).get_parser(prog_name) parser.add_argument( '--fixed-ip', metavar='subnet=<subnet>,ip-address=<ip-address>', action=parseractions.MultiKeyValueAction, optional_keys=['subnet', 'ip-address'], help=_("Desired IP and/or subnet (name or ID) which should be " "removed from this port: subnet=<subnet>," "ip-address=<ip-address> (repeat option to unset multiple " "fixed IP addresses)")) parser.add_argument( '--binding-profile', metavar='<binding-profile-key>', action='append', help=_("Desired key which should be removed from binding:profile" "(repeat option to unset multiple binding:profile data)")) parser.add_argument( '--security-group', metavar='<security-group>', action='append', dest='security_groups', help=_("Security group which should be removed this port (name " "or ID) (repeat option to unset multiple security groups)") ) parser.add_argument( 'port', metavar="<port>", help=_("Port to modify (name or ID)") ) return parser
def get_parser(self, prog_name): parser = super(SetQuota, self).get_parser(prog_name) parser.add_argument( 'project', metavar='<project/class>', help=_('Set quotas for this project or class (name/ID)'), ) parser.add_argument( '--class', dest='quota_class', action='store_true', default=False, help=_('Set quotas for <class>'), ) for k, v in self._build_options_list(): parser.add_argument( '--%s' % v, metavar='<%s>' % v, dest=k, type=int, help=_('New value for the %s quota') % v, ) parser.add_argument( '--volume-type', metavar='<volume-type>', help=_('Set quotas for a specific <volume-type>'), ) return parser
def get_parser(self, prog_name): parser = super(ListPort, self).get_parser(prog_name) parser.add_argument( '--device-owner', metavar='<device-owner>', help=_("List only ports with the specified device owner. " "This is the entity that uses the port (for example, " "network:dhcp).") ) parser.add_argument( '--network', metavar='<network>', help=_("List only ports connected to this network (name or ID)")) device_group = parser.add_mutually_exclusive_group() device_group.add_argument( '--router', metavar='<router>', dest='router', help=_("List only ports attached to this router (name or ID)") ) device_group.add_argument( '--server', metavar='<server>', help=_("List only ports attached to this server (name or ID)"), ) device_group.add_argument( '--device-id', metavar='<device-id>', help=_("List only ports with the specified device ID") ) parser.add_argument( '--mac-address', metavar='<mac-address>', help=_("List only ports with this MAC address") ) parser.add_argument( '--long', action='store_true', default=False, help=_("List additional fields in output") ) parser.add_argument( '--project', metavar='<project>', help=_("List ports according to their project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--fixed-ip', metavar=('subnet=<subnet>,ip-address=<ip-address>,' 'ip-substring=<ip-substring>'), action=parseractions.MultiKeyValueAction, optional_keys=['subnet', 'ip-address', 'ip-substring'], help=_("Desired IP and/or subnet for filtering ports " "(name or ID): subnet=<subnet>,ip-address=<ip-address>," "ip-substring=<ip-substring> " "(repeat option to set multiple fixed IP addresses)"), ) _tag.add_tag_filtering_option_to_parser(parser, _('ports')) return parser
def take_action(self, parsed_args): volume_client = self.app.client_manager.volume identity_client = self.app.client_manager.identity volume_type = utils.find_resource( volume_client.volume_types, parsed_args.volume_type, ) result = 0 if parsed_args.property: try: volume_type.unset_keys(parsed_args.property) except Exception as e: LOG.error(_("Failed to unset volume type property: %s"), e) result += 1 if parsed_args.project: project_info = None try: project_info = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain) volume_client.volume_type_access.remove_project_access( volume_type.id, project_info.id) except Exception as e: LOG.error(_("Failed to remove volume type access from " "project: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("Command Failed: One or more of" " the operations failed"))
def update_parser_compute(self, parser): parser.add_argument( '--dst-port', metavar='<port-range>', default=(0, 0), action=parseractions.RangeAction, help=_("Destination port, may be a single port or a starting and " "ending port range: 137:139. Required for IP protocols TCP " "and UDP. Ignored for ICMP IP protocols.") ) # NOTE(rtheis): Support either protocol option name for now. # However, consider deprecating and then removing --proto in # a future release. protocol_group = parser.add_mutually_exclusive_group() protocol_group.add_argument( '--protocol', metavar='<protocol>', choices=['icmp', 'tcp', 'udp'], type=_convert_to_lowercase, help=_("IP protocol (icmp, tcp, udp; default: tcp)") ) protocol_group.add_argument( '--proto', metavar='<proto>', choices=['icmp', 'tcp', 'udp'], type=_convert_to_lowercase, help=argparse.SUPPRESS ) return parser
def get_parser(self, prog_name): parser = super(SetAddressScope, self).get_parser(prog_name) parser.add_argument( 'address_scope', metavar="<address-scope>", help=_("Address scope to modify (name or ID)") ) parser.add_argument( '--name', metavar="<name>", help=_('Set address scope name') ) share_group = parser.add_mutually_exclusive_group() share_group.add_argument( '--share', action='store_true', help=_('Share the address scope between projects') ) share_group.add_argument( '--no-share', action='store_true', help=_('Do not share the address scope between projects') ) return parser
def get_parser(self, prog_name): parser = super(CreateAddressScope, self).get_parser(prog_name) parser.add_argument( 'name', metavar="<name>", help=_("New address scope name") ) parser.add_argument( '--ip-version', type=int, default=4, choices=[4, 6], help=_("IP version (default is 4)") ) parser.add_argument( '--project', metavar="<project>", help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) share_group = parser.add_mutually_exclusive_group() share_group.add_argument( '--share', action='store_true', help=_('Share the address scope between projects') ) share_group.add_argument( '--no-share', action='store_true', help=_('Do not share the address scope between projects (default)') ) return parser
def get_parser(self, prog_name): parser = super(SetNetworkSegmentRange, self).get_parser(prog_name) parser.add_argument( 'network_segment_range', metavar='<network-segment-range>', help=_('Network segment range to modify (name or ID)'), ) parser.add_argument( '--name', metavar='<name>', help=_('Set network segment name'), ) parser.add_argument( '--minimum', metavar='<minimum-segmentation-id>', type=int, help=_('Set network segment range minimum segment identifier'), ) parser.add_argument( '--maximum', metavar='<maximum-segmentation-id>', type=int, help=_('Set network segment range maximum segment identifier'), ) return parser
def take_action(self, parsed_args): network_client = self.app.client_manager.network try: # Verify that the extension exists. network_client.find_extension('network-segment-range', ignore_missing=False) except Exception as e: msg = (_('Network segment range set not supported by ' 'Network API: %(e)s') % {'e': e}) raise exceptions.CommandError(msg) if (parsed_args.minimum and not parsed_args.maximum) or \ (parsed_args.maximum and not parsed_args.minimum): msg = _("--minimum and --maximum are both required") raise exceptions.CommandError(msg) obj = network_client.find_network_segment_range( parsed_args.network_segment_range, ignore_missing=False) attrs = {} if parsed_args.name: attrs['name'] = parsed_args.name if parsed_args.minimum: attrs['minimum'] = parsed_args.minimum if parsed_args.maximum: attrs['maximum'] = parsed_args.maximum network_client.update_network_segment_range(obj, **attrs)
def get_parser(self, prog_name): parser = super(SetVolumeType, self).get_parser(prog_name) parser.add_argument( 'volume_type', metavar='<volume-type>', help=_('Volume type to modify (name or ID)'), ) parser.add_argument( '--name', metavar='<name>', help=_('Set volume type name'), ) parser.add_argument( '--description', metavar='<name>', help=_('Set volume type description'), ) parser.add_argument( '--property', metavar='<key=value>', action=parseractions.KeyValueAction, help=_('Set a property on this volume type ' '(repeat option to set multiple properties)'), ) parser.add_argument( '--project', metavar='<project>', help=_('Set volume type access to project (name or ID) ' '(admin only)'), ) identity_common.add_project_domain_option_to_parser(parser) return parser
def get_parser(self, prog_name): parser = super(ListNetworkSegmentRange, self).get_parser(prog_name) parser.add_argument( '--long', action='store_true', help=_('List additional fields in output'), ) used_group = parser.add_mutually_exclusive_group() used_group.add_argument( '--used', action='store_true', help=_('List network segment ranges that have segments in use'), ) used_group.add_argument( '--unused', action='store_true', help=_('List network segment ranges that have segments ' 'not in use'), ) available_group = parser.add_mutually_exclusive_group() available_group.add_argument( '--available', action='store_true', help=_('List network segment ranges that have available segments'), ) available_group.add_argument( '--unavailable', action='store_true', help=_('List network segment ranges without available segments'), ) return parser
def get_parser(self, prog_name): parser = super(CreateVolumeType, self).get_parser(prog_name) parser.add_argument( "name", metavar="<name>", help=_("Volume type name"), ) parser.add_argument( "--description", metavar="<description>", help=_("Volume type description"), ) public_group = parser.add_mutually_exclusive_group() public_group.add_argument( "--public", dest="public", action="store_true", default=False, help=_("Volume type is accessible to the public"), ) public_group.add_argument( "--private", dest="private", action="store_true", default=False, help=_("Volume type is not accessible to the public"), ) parser.add_argument( '--property', metavar='<key=value>', action=parseractions.KeyValueAction, help=_('Set a property on this volume type ' '(repeat option to set multiple properties)'), ) return parser
def update_parser_network(self, parser): admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument('--enable', action='store_true', default=True, help=_("Enable network (default)")) admin_group.add_argument('--disable', action='store_true', help=_("Disable network")) parser.add_argument('--project', metavar='<project>', help=_("Owner's project (name or ID)")) parser.add_argument('--description', metavar='<description>', help=_("Set network description")) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--availability-zone-hint', action='append', dest='availability_zone_hints', metavar='<availability-zone>', help=_("Availability Zone in which to create this network " "(Network Availability Zone extension required, " "repeat option to set multiple availability zones)")) port_security_group = parser.add_mutually_exclusive_group() port_security_group.add_argument( '--enable-port-security', action='store_true', help=_("Enable port security by default for ports created on " "this network (default)")) port_security_group.add_argument( '--disable-port-security', action='store_true', help=_("Disable port security by default for ports created on " "this network")) external_router_grp = parser.add_mutually_exclusive_group() external_router_grp.add_argument( '--external', action='store_true', help=_("Set this network as an external network " "(external-net extension required)")) external_router_grp.add_argument( '--internal', action='store_true', help=_("Set this network as an internal network (default)")) default_router_grp = parser.add_mutually_exclusive_group() default_router_grp.add_argument( '--default', action='store_true', help=_("Specify if this network should be used as " "the default external network")) default_router_grp.add_argument( '--no-default', action='store_true', help=_("Do not use the network as the default external network " "(default)")) parser.add_argument( '--qos-policy', metavar='<qos-policy>', help=_("QoS policy to attach to this network (name or ID)")) _add_additional_network_options(parser) return parser
def get_parser(self, prog_name): parser = super(SetVolume, self).get_parser(prog_name) parser.add_argument( 'volume', metavar='<volume>', help=_('Volume to modify (name or ID)'), ) parser.add_argument( '--name', metavar='<name>', help=_('New volume name'), ) parser.add_argument( '--size', metavar='<size>', type=int, help=_('Extend volume size in GB'), ) parser.add_argument( '--description', metavar='<description>', help=_('New volume description'), ) parser.add_argument( '--property', metavar='<key=value>', action=parseractions.KeyValueAction, help=_('Set a property on this volume ' '(repeat option to set multiple properties)'), ) parser.add_argument( '--image-property', metavar='<key=value>', action=parseractions.KeyValueAction, help=_('Set an image property on this volume ' '(repeat option to set multiple image properties)'), ) parser.add_argument( "--state", metavar="<state>", choices=['available', 'error', 'creating', 'deleting', 'in-use', 'attaching', 'detaching', 'error_deleting', 'maintenance'], help=_('New volume state ("available", "error", "creating", ' '"deleting", "in-use", "attaching", "detaching", ' '"error_deleting" or "maintenance") (admin only) ' '(This option simply changes the state of the volume ' 'in the database with no regard to actual status, ' 'exercise caution when using)'), ) bootable_group = parser.add_mutually_exclusive_group() bootable_group.add_argument( "--bootable", action="store_true", help=_("Mark volume as bootable") ) bootable_group.add_argument( "--non-bootable", action="store_true", help=_("Mark volume as non-bootable") ) return parser
def update_parser_common(self, parser): parser.add_argument('network', metavar="<network>", help=_("Network to display (name or ID)")) return parser
def get_parser(self, prog_name): parser = super(SetNetwork, self).get_parser(prog_name) parser.add_argument('network', metavar="<network>", help=_("Network to modify (name or ID)")) parser.add_argument('--name', metavar='<name>', help=_("Set network name")) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument('--enable', action='store_true', default=None, help=_("Enable network")) admin_group.add_argument('--disable', action='store_true', help=_("Disable network")) share_group = parser.add_mutually_exclusive_group() share_group.add_argument('--share', action='store_true', default=None, help=_("Share the network between projects")) share_group.add_argument( '--no-share', action='store_true', help=_("Do not share the network between projects")) parser.add_argument('--description', metavar="<description", help=_("Set network description")) port_security_group = parser.add_mutually_exclusive_group() port_security_group.add_argument( '--enable-port-security', action='store_true', help=_("Enable port security by default for ports created on " "this network")) port_security_group.add_argument( '--disable-port-security', action='store_true', help=_("Disable port security by default for ports created on " "this network")) external_router_grp = parser.add_mutually_exclusive_group() external_router_grp.add_argument( '--external', action='store_true', help=_("Set this network as an external network " "(external-net extension required)")) external_router_grp.add_argument( '--internal', action='store_true', help=_("Set this network as an internal network")) default_router_grp = parser.add_mutually_exclusive_group() default_router_grp.add_argument( '--default', action='store_true', help=_("Set the network as the default external network")) default_router_grp.add_argument( '--no-default', action='store_true', help=_("Do not use the network as the default external network")) qos_group = parser.add_mutually_exclusive_group() qos_group.add_argument( '--qos-policy', metavar='<qos-policy>', help=_("QoS policy to attach to this network (name or ID)")) qos_group.add_argument( '--no-qos-policy', action='store_true', help=_("Remove the QoS policy attached to this network")) _add_additional_network_options(parser) return parser
class SetNetwork(command.Command): _description = _("Set network properties") def get_parser(self, prog_name): parser = super(SetNetwork, self).get_parser(prog_name) parser.add_argument('network', metavar="<network>", help=_("Network to modify (name or ID)")) parser.add_argument('--name', metavar='<name>', help=_("Set network name")) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument('--enable', action='store_true', default=None, help=_("Enable network")) admin_group.add_argument('--disable', action='store_true', help=_("Disable network")) share_group = parser.add_mutually_exclusive_group() share_group.add_argument('--share', action='store_true', default=None, help=_("Share the network between projects")) share_group.add_argument( '--no-share', action='store_true', help=_("Do not share the network between projects")) parser.add_argument('--description', metavar="<description", help=_("Set network description")) port_security_group = parser.add_mutually_exclusive_group() port_security_group.add_argument( '--enable-port-security', action='store_true', help=_("Enable port security by default for ports created on " "this network")) port_security_group.add_argument( '--disable-port-security', action='store_true', help=_("Disable port security by default for ports created on " "this network")) external_router_grp = parser.add_mutually_exclusive_group() external_router_grp.add_argument( '--external', action='store_true', help=_("Set this network as an external network " "(external-net extension required)")) external_router_grp.add_argument( '--internal', action='store_true', help=_("Set this network as an internal network")) default_router_grp = parser.add_mutually_exclusive_group() default_router_grp.add_argument( '--default', action='store_true', help=_("Set the network as the default external network")) default_router_grp.add_argument( '--no-default', action='store_true', help=_("Do not use the network as the default external network")) qos_group = parser.add_mutually_exclusive_group() qos_group.add_argument( '--qos-policy', metavar='<qos-policy>', help=_("QoS policy to attach to this network (name or ID)")) qos_group.add_argument( '--no-qos-policy', action='store_true', help=_("Remove the QoS policy attached to this network")) _add_additional_network_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_network(parsed_args.network, ignore_missing=False) attrs = _get_attrs_network(self.app.client_manager, parsed_args) client.update_network(obj, **attrs)
def update_parser_network(self, parser): router_ext_group = parser.add_mutually_exclusive_group() router_ext_group.add_argument('--external', action='store_true', help=_("List external networks")) router_ext_group.add_argument('--internal', action='store_true', help=_("List internal networks")) parser.add_argument('--long', action='store_true', help=_("List additional fields in output")) parser.add_argument('--name', metavar='<name>', help=_("List networks according to their name")) admin_state_group = parser.add_mutually_exclusive_group() admin_state_group.add_argument('--enable', action='store_true', help=_("List enabled networks")) admin_state_group.add_argument('--disable', action='store_true', help=_("List disabled networks")) parser.add_argument( '--project', metavar='<project>', help=_("List networks according to their project (name or ID)")) identity_common.add_project_domain_option_to_parser(parser) shared_group = parser.add_mutually_exclusive_group() shared_group.add_argument( '--share', action='store_true', help=_("List networks shared between projects")) shared_group.add_argument( '--no-share', action='store_true', help=_("List networks not shared between projects")) parser.add_argument('--status', metavar='<status>', choices=['ACTIVE', 'BUILD', 'DOWN', 'ERROR'], help=_("List networks according to their status " "('ACTIVE', 'BUILD', 'DOWN', 'ERROR')")) parser.add_argument( '--provider-network-type', metavar='<provider-network-type>', choices=['flat', 'geneve', 'gre', 'local', 'vlan', 'vxlan'], help=_("List networks according to their physical mechanisms. " "The supported options are: flat, geneve, gre, local, " "vlan, vxlan.")) parser.add_argument( '--provider-physical-network', metavar='<provider-physical-network>', dest='physical_network', help=_("List networks according to name of the physical network")) parser.add_argument( '--provider-segment', metavar='<provider-segment>', dest='segmentation_id', help=_("List networks according to VLAN ID for VLAN networks " "or Tunnel ID for GENEVE/GRE/VXLAN networks")) parser.add_argument('--agent', metavar='<agent-id>', dest='agent_id', help=_('List networks hosted by agent (ID only)')) return parser
class ListNetwork(common.NetworkAndComputeLister): _description = _("List networks") def update_parser_network(self, parser): router_ext_group = parser.add_mutually_exclusive_group() router_ext_group.add_argument('--external', action='store_true', help=_("List external networks")) router_ext_group.add_argument('--internal', action='store_true', help=_("List internal networks")) parser.add_argument('--long', action='store_true', help=_("List additional fields in output")) parser.add_argument('--name', metavar='<name>', help=_("List networks according to their name")) admin_state_group = parser.add_mutually_exclusive_group() admin_state_group.add_argument('--enable', action='store_true', help=_("List enabled networks")) admin_state_group.add_argument('--disable', action='store_true', help=_("List disabled networks")) parser.add_argument( '--project', metavar='<project>', help=_("List networks according to their project (name or ID)")) identity_common.add_project_domain_option_to_parser(parser) shared_group = parser.add_mutually_exclusive_group() shared_group.add_argument( '--share', action='store_true', help=_("List networks shared between projects")) shared_group.add_argument( '--no-share', action='store_true', help=_("List networks not shared between projects")) parser.add_argument('--status', metavar='<status>', choices=['ACTIVE', 'BUILD', 'DOWN', 'ERROR'], help=_("List networks according to their status " "('ACTIVE', 'BUILD', 'DOWN', 'ERROR')")) parser.add_argument( '--provider-network-type', metavar='<provider-network-type>', choices=['flat', 'geneve', 'gre', 'local', 'vlan', 'vxlan'], help=_("List networks according to their physical mechanisms. " "The supported options are: flat, geneve, gre, local, " "vlan, vxlan.")) parser.add_argument( '--provider-physical-network', metavar='<provider-physical-network>', dest='physical_network', help=_("List networks according to name of the physical network")) parser.add_argument( '--provider-segment', metavar='<provider-segment>', dest='segmentation_id', help=_("List networks according to VLAN ID for VLAN networks " "or Tunnel ID for GENEVE/GRE/VXLAN networks")) parser.add_argument('--agent', metavar='<agent-id>', dest='agent_id', help=_('List networks hosted by agent (ID only)')) return parser def take_action_network(self, client, parsed_args): identity_client = self.app.client_manager.identity if parsed_args.long: columns = ( 'id', 'name', 'status', 'project_id', 'is_admin_state_up', 'is_shared', 'subnet_ids', 'provider_network_type', 'is_router_external', 'availability_zones', ) column_headers = ( 'ID', 'Name', 'Status', 'Project', 'State', 'Shared', 'Subnets', 'Network Type', 'Router Type', 'Availability Zones', ) elif parsed_args.agent_id: columns = ('id', 'name', 'subnet_ids') column_headers = ( 'ID', 'Name', 'Subnets', ) client = self.app.client_manager.network dhcp_agent = client.get_agent(parsed_args.agent_id) data = client.dhcp_agent_hosting_networks(dhcp_agent) return (column_headers, (utils.get_item_properties( s, columns, formatters=_formatters, ) for s in data)) else: columns = ('id', 'name', 'subnet_ids') column_headers = ( 'ID', 'Name', 'Subnets', ) args = {} if parsed_args.external: args['router:external'] = True args['is_router_external'] = True elif parsed_args.internal: args['router:external'] = False args['is_router_external'] = False if parsed_args.name is not None: args['name'] = parsed_args.name if parsed_args.enable: args['admin_state_up'] = True args['is_admin_state_up'] = True elif parsed_args.disable: args['admin_state_up'] = False args['is_admin_state_up'] = False if parsed_args.project: project = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ) args['tenant_id'] = project.id args['project_id'] = project.id if parsed_args.share: args['shared'] = True args['is_shared'] = True elif parsed_args.no_share: args['shared'] = False args['is_shared'] = False if parsed_args.status: args['status'] = parsed_args.status if parsed_args.provider_network_type: args['provider:network_type'] = parsed_args.provider_network_type args['provider_network_type'] = parsed_args.provider_network_type if parsed_args.physical_network: args['provider:physical_network'] = parsed_args.physical_network args['provider_physical_network'] = parsed_args.physical_network if parsed_args.segmentation_id: args['provider:segmentation_id'] = parsed_args.segmentation_id args['provider_segmentation_id'] = parsed_args.segmentation_id data = client.networks(**args) return (column_headers, (utils.get_item_properties( s, columns, formatters=_formatters, ) for s in data)) def take_action_compute(self, client, parsed_args): columns = ( 'id', 'label', 'cidr', ) column_headers = ( 'ID', 'Name', 'Subnet', ) data = client.api.network_list() return (column_headers, (utils.get_dict_properties( s, columns, formatters=_formatters, ) for s in data))
def get_parser(self, prog_name): parser = super(ShowNetworkAgent, self).get_parser(prog_name) parser.add_argument('network_agent', metavar="<network-agent>", help=(_("Network agent to display (ID only)"))) return parser
def get_parser(self, prog_name): parser = super(ShowMeterRule, self).get_parser(prog_name) parser.add_argument('meter_rule_id', metavar='<meter-rule-id>', help=_('Meter rule (ID only)')) return parser
class CreateNetwork(common.NetworkAndComputeShowOne): _description = _("Create new network") def update_parser_common(self, parser): parser.add_argument('name', metavar='<name>', help=_("New network name")) share_group = parser.add_mutually_exclusive_group() share_group.add_argument('--share', action='store_true', default=None, help=_("Share the network between projects")) share_group.add_argument( '--no-share', action='store_true', help=_("Do not share the network between projects")) return parser def update_parser_network(self, parser): admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument('--enable', action='store_true', default=True, help=_("Enable network (default)")) admin_group.add_argument('--disable', action='store_true', help=_("Disable network")) parser.add_argument('--project', metavar='<project>', help=_("Owner's project (name or ID)")) parser.add_argument('--description', metavar='<description>', help=_("Set network description")) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--availability-zone-hint', action='append', dest='availability_zone_hints', metavar='<availability-zone>', help=_("Availability Zone in which to create this network " "(Network Availability Zone extension required, " "repeat option to set multiple availability zones)")) port_security_group = parser.add_mutually_exclusive_group() port_security_group.add_argument( '--enable-port-security', action='store_true', help=_("Enable port security by default for ports created on " "this network (default)")) port_security_group.add_argument( '--disable-port-security', action='store_true', help=_("Disable port security by default for ports created on " "this network")) external_router_grp = parser.add_mutually_exclusive_group() external_router_grp.add_argument( '--external', action='store_true', help=_("Set this network as an external network " "(external-net extension required)")) external_router_grp.add_argument( '--internal', action='store_true', help=_("Set this network as an internal network (default)")) default_router_grp = parser.add_mutually_exclusive_group() default_router_grp.add_argument( '--default', action='store_true', help=_("Specify if this network should be used as " "the default external network")) default_router_grp.add_argument( '--no-default', action='store_true', help=_("Do not use the network as the default external network " "(default)")) parser.add_argument( '--qos-policy', metavar='<qos-policy>', help=_("QoS policy to attach to this network (name or ID)")) _add_additional_network_options(parser) return parser def update_parser_compute(self, parser): parser.add_argument( '--subnet', metavar='<subnet>', required=True, help=_("IPv4 subnet for fixed IPs (in CIDR notation)")) return parser def take_action_network(self, client, parsed_args): attrs = _get_attrs_network(self.app.client_manager, parsed_args) obj = client.create_network(**attrs) display_columns, columns = _get_columns_network(obj) data = utils.get_item_properties(obj, columns, formatters=_formatters) return (display_columns, data) def take_action_compute(self, client, parsed_args): attrs = _get_attrs_compute(self.app.client_manager, parsed_args) obj = client.api.network_create(**attrs) display_columns, columns = _get_columns_compute(obj) data = utils.get_dict_properties(obj, columns) return (display_columns, data)
class ListContainer(command.Lister): _description = _("List containers") def get_parser(self, prog_name): parser = super(ListContainer, self).get_parser(prog_name) parser.add_argument( "--prefix", metavar="<prefix>", help=_("Filter list using <prefix>"), ) parser.add_argument( "--marker", metavar="<marker>", help=_("Anchor for paging"), ) parser.add_argument( "--end-marker", metavar="<end-marker>", help=_("End anchor for paging"), ) parser.add_argument( "--limit", metavar="<num-containers>", type=int, help=_("Limit the number of containers returned"), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( '--all', action='store_true', default=False, help=_('List all containers (default is 10000)'), ) return parser def take_action(self, parsed_args): if parsed_args.long: columns = ('Name', 'Bytes', 'Count') else: columns = ('Name', ) kwargs = {} if parsed_args.prefix: kwargs['prefix'] = parsed_args.prefix if parsed_args.marker: kwargs['marker'] = parsed_args.marker if parsed_args.end_marker: kwargs['end_marker'] = parsed_args.end_marker if parsed_args.limit: kwargs['limit'] = parsed_args.limit if parsed_args.all: kwargs['full_listing'] = True data = self.app.client_manager.object_store.container_list(**kwargs) return (columns, (utils.get_dict_properties( s, columns, formatters={}, ) for s in data))
class ListNetworkAgent(command.Lister): _description = _("List network agents") def get_parser(self, prog_name): parser = super(ListNetworkAgent, self).get_parser(prog_name) parser.add_argument( '--agent-type', metavar='<agent-type>', choices=[ "bgp", "dhcp", "open-vswitch", "linux-bridge", "ofa", "l3", "loadbalancer", "metering", "metadata", "macvtap", "nic" ], help=_("List only agents with the specified agent type. " "The supported agent types are: bgp, dhcp, open-vswitch, " "linux-bridge, ofa, l3, loadbalancer, metering, " "metadata, macvtap, nic.")) parser.add_argument( '--host', metavar='<host>', help=_("List only agents running on the specified host")) agent_type_group = parser.add_mutually_exclusive_group() agent_type_group.add_argument( '--network', metavar='<network>', help=_('List agents hosting a network (name or ID)')) agent_type_group.add_argument( '--router', metavar='<router>', help=_('List agents hosting this router (name or ID)')) parser.add_argument('--long', action='store_true', default=False, help=_("List additional fields in output")) return parser def take_action(self, parsed_args): client = self.app.client_manager.network columns = ('id', 'agent_type', 'host', 'availability_zone', 'is_alive', 'is_admin_state_up', 'binary') column_headers = ('ID', 'Agent Type', 'Host', 'Availability Zone', 'Alive', 'State', 'Binary') key_value = { 'bgp': 'BGP dynamic routing agent', 'dhcp': 'DHCP agent', 'open-vswitch': 'Open vSwitch agent', 'linux-bridge': 'Linux bridge agent', 'ofa': 'OFA driver agent', 'l3': 'L3 agent', 'loadbalancer': 'Loadbalancer agent', 'metering': 'Metering agent', 'metadata': 'Metadata agent', 'macvtap': 'Macvtap agent', 'nic': 'NIC Switch agent' } filters = {} if parsed_args.network is not None: network = client.find_network(parsed_args.network, ignore_missing=False) data = client.network_hosting_dhcp_agents(network) elif parsed_args.router is not None: if parsed_args.long: columns += ('ha_state', ) column_headers += ('HA State', ) router = client.find_router(parsed_args.router, ignore_missing=False) data = client.routers_hosting_l3_agents(router) else: if parsed_args.agent_type is not None: filters['agent_type'] = key_value[parsed_args.agent_type] if parsed_args.host is not None: filters['host'] = parsed_args.host data = client.agents(**filters) return (column_headers, (utils.get_item_properties( s, columns, formatters=_formatters, ) for s in data))
def take_action(self, parsed_args): compute_client = self.app.client_manager.sdk_connection.compute identity_client = self.app.client_manager.identity kwargs = {'name': parsed_args.name} public_key = parsed_args.public_key if public_key: try: with io.open(os.path.expanduser(parsed_args.public_key)) as p: public_key = p.read() except IOError as e: msg = _("Key file %(public_key)s not found: %(exception)s") raise exceptions.CommandError(msg % { "public_key": parsed_args.public_key, "exception": e }) kwargs['public_key'] = public_key if parsed_args.type: if not sdk_utils.supports_microversion(compute_client, '2.2'): msg = _( '--os-compute-api-version 2.2 or greater is required to ' 'support the --type option') raise exceptions.CommandError(msg) kwargs['key_type'] = parsed_args.type if parsed_args.user: if not sdk_utils.supports_microversion(compute_client, '2.10'): msg = _( '--os-compute-api-version 2.10 or greater is required to ' 'support the --user option') raise exceptions.CommandError(msg) kwargs['user_id'] = identity_common.find_user( identity_client, parsed_args.user, parsed_args.user_domain, ).id keypair = compute_client.create_keypair(**kwargs) private_key = parsed_args.private_key # Save private key into specified file if private_key: try: with io.open(os.path.expanduser(parsed_args.private_key), 'w+') as p: p.write(keypair.private_key) except IOError as e: msg = _("Key file %(private_key)s can not be saved: " "%(exception)s") raise exceptions.CommandError(msg % { "private_key": parsed_args.private_key, "exception": e }) # NOTE(dtroyer): how do we want to handle the display of the private # key when it needs to be communicated back to the user # For now, duplicate nova keypair-add command output if public_key or private_key: display_columns, columns = _get_keypair_columns(keypair, hide_pub_key=True, hide_priv_key=True) data = utils.get_item_properties(keypair, columns) return (display_columns, data) else: sys.stdout.write(keypair.private_key) return ({}, {})
class ListExtension(command.Lister): _description = _("List API extensions") def get_parser(self, prog_name): parser = super(ListExtension, self).get_parser(prog_name) parser.add_argument( '--compute', action='store_true', default=False, help=_('List extensions for the Compute API'), ) parser.add_argument( '--identity', action='store_true', default=False, help=_('List extensions for the Identity API'), ) parser.add_argument( '--network', action='store_true', default=False, help=_('List extensions for the Network API'), ) parser.add_argument( '--volume', action='store_true', default=False, help=_('List extensions for the Block Storage API'), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) return parser def take_action(self, parsed_args): if parsed_args.long: columns = ('Name', 'Alias', 'Description', 'Namespace', 'Updated', 'Links') else: columns = ('Name', 'Alias', 'Description') data = [] # by default we want to show everything, unless the # user specifies one or more of the APIs to show # for now, only identity and compute are supported. show_all = (not parsed_args.identity and not parsed_args.compute and not parsed_args.volume and not parsed_args.network) if parsed_args.identity or show_all: identity_client = self.app.client_manager.identity try: data += identity_client.extensions.list() except Exception: message = _("Extensions list not supported by Identity API") LOG.warning(message) if parsed_args.compute or show_all: compute_client = self.app.client_manager.compute try: data += compute_client.list_extensions.show_all() except Exception: message = _("Extensions list not supported by Compute API") LOG.warning(message) if parsed_args.volume or show_all: volume_client = self.app.client_manager.volume try: data += volume_client.list_extensions.show_all() except Exception: message = _("Extensions list not supported by " "Block Storage API") LOG.warning(message) if parsed_args.network or show_all: network_client = self.app.client_manager.network try: data += network_client.extensions() except Exception: message = _("Failed to retrieve extensions list " "from Network API") LOG.warning(message) extension_tuples = (utils.get_item_properties( s, columns, ) for s in data) return (columns, extension_tuples)
def take_action(self, parsed_args): compute_client = self.app.client_manager.sdk_connection.compute identity_client = self.app.client_manager.identity kwargs = {} if parsed_args.marker: if not sdk_utils.supports_microversion(compute_client, '2.35'): msg = _('--os-compute-api-version 2.35 or greater is required ' 'to support the --marker option') raise exceptions.CommandError(msg) kwargs['marker'] = parsed_args.marker if parsed_args.limit: if not sdk_utils.supports_microversion(compute_client, '2.35'): msg = _('--os-compute-api-version 2.35 or greater is required ' 'to support the --limit option') raise exceptions.CommandError(msg) kwargs['limit'] = parsed_args.limit if parsed_args.project: if not sdk_utils.supports_microversion(compute_client, '2.10'): msg = _( '--os-compute-api-version 2.10 or greater is required to ' 'support the --project option') raise exceptions.CommandError(msg) if parsed_args.marker: # NOTE(stephenfin): Because we're doing this client-side, we # can't really rely on the marker, because we don't know what # user the marker is associated with msg = _('--project is not compatible with --marker') # NOTE(stephenfin): This is done client side because nova doesn't # currently support doing so server-side. If this is slow, we can # think about spinning up a threadpool or similar. project = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id users = identity_client.users.list(tenant_id=project) data = [] for user in users: kwargs['user_id'] = user.id data.extend(compute_client.keypairs(**kwargs)) elif parsed_args.user: if not sdk_utils.supports_microversion(compute_client, '2.10'): msg = _( '--os-compute-api-version 2.10 or greater is required to ' 'support the --user option') raise exceptions.CommandError(msg) user = identity_common.find_user( identity_client, parsed_args.user, parsed_args.user_domain, ) kwargs['user_id'] = user.id data = compute_client.keypairs(**kwargs) else: data = compute_client.keypairs(**kwargs) columns = ("Name", "Fingerprint") if sdk_utils.supports_microversion(compute_client, '2.2'): columns += ("Type", ) return ( columns, (utils.get_item_properties(s, columns) for s in data), )
def get_parser(self, prog_name): parser = super(ShowPort, self).get_parser(prog_name) parser.add_argument('port', metavar="<port>", help=_("Port to display (name or ID)")) return parser
class CreateApplicationCredential(command.ShowOne): _description = _("Create new application credential") def get_parser(self, prog_name): parser = super(CreateApplicationCredential, self).get_parser(prog_name) parser.add_argument( 'name', metavar='<name>', help=_('Name of the application credential'), ) parser.add_argument( '--secret', metavar='<secret>', help=_('Secret to use for authentication (if not provided, one' ' will be generated)'), ) parser.add_argument( '--role', metavar='<role>', action='append', default=[], help=_('Roles to authorize (name or ID) (repeat option to set' ' multiple values)'), ) parser.add_argument( '--expiration', metavar='<expiration>', help=_('Sets an expiration date for the application credential,' ' format of YYYY-mm-ddTHH:MM:SS (if not provided, the' ' application credential will not expire)'), ) parser.add_argument( '--description', metavar='<description>', help=_('Application credential description'), ) parser.add_argument( '--unrestricted', action="store_true", help=_('Enable application credential to create and delete other' ' application credentials and trusts (this is potentially' ' dangerous behavior and is disabled by default)'), ) parser.add_argument( '--restricted', action="store_true", help=_('Prohibit application credential from creating and deleting' ' other application credentials and trusts (this is the' ' default behavior)'), ) parser.add_argument( '--access-rules', metavar='<access-rules>', help=_('Either a string or file path containing a JSON-formatted ' 'list of access rules, each containing a request method, ' 'path, and service, for example ' '\'[{"method": "GET", ' '"path": "/v2.1/servers", ' '"service": "compute"}]\''), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity role_ids = [] for role in parsed_args.role: # A user can only create an application credential for themself, # not for another user even as an admin, and only on the project to # which they are currently scoped with a subset of the role # assignments they have on that project. Don't bother trying to # look up roles via keystone, just introspect the token. role_id = common._get_token_resource(identity_client, "roles", role) role_ids.append(role_id) expires_at = None if parsed_args.expiration: expires_at = datetime.datetime.strptime(parsed_args.expiration, '%Y-%m-%dT%H:%M:%S') if parsed_args.restricted: unrestricted = False else: unrestricted = parsed_args.unrestricted if parsed_args.access_rules: try: access_rules = json.loads(parsed_args.access_rules) except ValueError: try: with open(parsed_args.access_rules) as f: access_rules = json.load(f) except IOError: raise exceptions.CommandError( _("Access rules is not valid JSON string or file does" " not exist.")) else: access_rules = None app_cred_manager = identity_client.application_credentials application_credential = app_cred_manager.create( parsed_args.name, roles=role_ids, expires_at=expires_at, description=parsed_args.description, secret=parsed_args.secret, unrestricted=unrestricted, access_rules=access_rules, ) application_credential._info.pop('links', None) # Format roles into something sensible roles = application_credential._info.pop('roles') msg = ' '.join(r['name'] for r in roles) application_credential._info['roles'] = msg return zip(*sorted(application_credential._info.items()))
class CreateKeypair(command.ShowOne): _description = _("Create new public or private key for server ssh access") def get_parser(self, prog_name): parser = super(CreateKeypair, self).get_parser(prog_name) parser.add_argument('name', metavar='<name>', help=_("New public or private key name")) key_group = parser.add_mutually_exclusive_group() key_group.add_argument( '--public-key', metavar='<file>', help=_("Filename for public key to add. If not used, " "creates a private key.")) key_group.add_argument( '--private-key', metavar='<file>', help=_("Filename for private key to save. If not used, " "print private key in console.")) parser.add_argument( '--type', metavar='<type>', choices=['ssh', 'x509'], help=_("Keypair type. Can be ssh or x509. " "(Supported by API versions '2.2' - '2.latest')"), ) parser.add_argument( '--user', metavar='<user>', help=_('The owner of the keypair. (admin only) (name or ID). ' 'Requires ``--os-compute-api-version`` 2.10 or greater.'), ) identity_common.add_user_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.sdk_connection.compute identity_client = self.app.client_manager.identity kwargs = {'name': parsed_args.name} public_key = parsed_args.public_key if public_key: try: with io.open(os.path.expanduser(parsed_args.public_key)) as p: public_key = p.read() except IOError as e: msg = _("Key file %(public_key)s not found: %(exception)s") raise exceptions.CommandError(msg % { "public_key": parsed_args.public_key, "exception": e }) kwargs['public_key'] = public_key if parsed_args.type: if not sdk_utils.supports_microversion(compute_client, '2.2'): msg = _( '--os-compute-api-version 2.2 or greater is required to ' 'support the --type option') raise exceptions.CommandError(msg) kwargs['key_type'] = parsed_args.type if parsed_args.user: if not sdk_utils.supports_microversion(compute_client, '2.10'): msg = _( '--os-compute-api-version 2.10 or greater is required to ' 'support the --user option') raise exceptions.CommandError(msg) kwargs['user_id'] = identity_common.find_user( identity_client, parsed_args.user, parsed_args.user_domain, ).id keypair = compute_client.create_keypair(**kwargs) private_key = parsed_args.private_key # Save private key into specified file if private_key: try: with io.open(os.path.expanduser(parsed_args.private_key), 'w+') as p: p.write(keypair.private_key) except IOError as e: msg = _("Key file %(private_key)s can not be saved: " "%(exception)s") raise exceptions.CommandError(msg % { "private_key": parsed_args.private_key, "exception": e }) # NOTE(dtroyer): how do we want to handle the display of the private # key when it needs to be communicated back to the user # For now, duplicate nova keypair-add command output if public_key or private_key: display_columns, columns = _get_keypair_columns(keypair, hide_pub_key=True, hide_priv_key=True) data = utils.get_item_properties(keypair, columns) return (display_columns, data) else: sys.stdout.write(keypair.private_key) return ({}, {})
class ListSubnetPool(command.Lister): _description = _("List subnet pools") def get_parser(self, prog_name): parser = super(ListSubnetPool, self).get_parser(prog_name) parser.add_argument('--long', action='store_true', default=False, help=_("List additional fields in output")) shared_group = parser.add_mutually_exclusive_group() shared_group.add_argument( '--share', action='store_true', help=_("List subnet pools shared between projects"), ) shared_group.add_argument( '--no-share', action='store_true', help=_("List subnet pools not shared between projects"), ) default_group = parser.add_mutually_exclusive_group() default_group.add_argument( '--default', action='store_true', help=_("List subnet pools used as the default external " "subnet pool"), ) default_group.add_argument( '--no-default', action='store_true', help=_("List subnet pools not used as the default external " "subnet pool")) parser.add_argument( '--project', metavar='<project>', help=_( "List subnet pools according to their project (name or ID)")) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--name', metavar='<name>', help=_("List only subnet pools of given name in output")) parser.add_argument( '--address-scope', metavar='<address-scope>', help=_("List only subnet pools of given address scope " "in output (name or ID)")) _tag.add_tag_filtering_option_to_parser(parser, _('subnet pools')) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity network_client = self.app.client_manager.network filters = {} if parsed_args.share: filters['shared'] = True filters['is_shared'] = True elif parsed_args.no_share: filters['shared'] = False filters['is_shared'] = False if parsed_args.default: filters['is_default'] = True elif parsed_args.no_default: filters['is_default'] = False if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id filters['tenant_id'] = project_id filters['project_id'] = project_id if parsed_args.name is not None: filters['name'] = parsed_args.name if parsed_args.address_scope: address_scope = network_client.find_address_scope( parsed_args.address_scope, ignore_missing=False) filters['address_scope_id'] = address_scope.id _tag.get_tag_filtering_args(parsed_args, filters) data = network_client.subnet_pools(**filters) headers = ('ID', 'Name', 'Prefixes') columns = ('id', 'name', 'prefixes') if parsed_args.long: headers += ('Default Prefix Length', 'Address Scope', 'Default Subnet Pool', 'Shared', 'Tags') columns += ('default_prefix_length', 'address_scope_id', 'is_default', 'is_shared', 'tags') return (headers, (utils.get_item_properties( s, columns, formatters=_formatters, ) for s in data))
class ListKeypair(command.Lister): _description = _("List key fingerprints") def get_parser(self, prog_name): parser = super().get_parser(prog_name) user_group = parser.add_mutually_exclusive_group() user_group.add_argument( '--user', metavar='<user>', help=_('Show keypairs for another user (admin only) (name or ID). ' 'Requires ``--os-compute-api-version`` 2.10 or greater.'), ) identity_common.add_user_domain_option_to_parser(parser) user_group.add_argument( '--project', metavar='<project>', help=_('Show keypairs for all users associated with project ' '(admin only) (name or ID). ' 'Requires ``--os-compute-api-version`` 2.10 or greater.'), ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--marker', help=_('The last keypair ID of the previous page'), ) parser.add_argument( '--limit', type=int, help=_('Maximum number of keypairs to display'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.sdk_connection.compute identity_client = self.app.client_manager.identity kwargs = {} if parsed_args.marker: if not sdk_utils.supports_microversion(compute_client, '2.35'): msg = _('--os-compute-api-version 2.35 or greater is required ' 'to support the --marker option') raise exceptions.CommandError(msg) kwargs['marker'] = parsed_args.marker if parsed_args.limit: if not sdk_utils.supports_microversion(compute_client, '2.35'): msg = _('--os-compute-api-version 2.35 or greater is required ' 'to support the --limit option') raise exceptions.CommandError(msg) kwargs['limit'] = parsed_args.limit if parsed_args.project: if not sdk_utils.supports_microversion(compute_client, '2.10'): msg = _( '--os-compute-api-version 2.10 or greater is required to ' 'support the --project option') raise exceptions.CommandError(msg) if parsed_args.marker: # NOTE(stephenfin): Because we're doing this client-side, we # can't really rely on the marker, because we don't know what # user the marker is associated with msg = _('--project is not compatible with --marker') # NOTE(stephenfin): This is done client side because nova doesn't # currently support doing so server-side. If this is slow, we can # think about spinning up a threadpool or similar. project = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id users = identity_client.users.list(tenant_id=project) data = [] for user in users: kwargs['user_id'] = user.id data.extend(compute_client.keypairs(**kwargs)) elif parsed_args.user: if not sdk_utils.supports_microversion(compute_client, '2.10'): msg = _( '--os-compute-api-version 2.10 or greater is required to ' 'support the --user option') raise exceptions.CommandError(msg) user = identity_common.find_user( identity_client, parsed_args.user, parsed_args.user_domain, ) kwargs['user_id'] = user.id data = compute_client.keypairs(**kwargs) else: data = compute_client.keypairs(**kwargs) columns = ("Name", "Fingerprint") if sdk_utils.supports_microversion(compute_client, '2.2'): columns += ("Type", ) return ( columns, (utils.get_item_properties(s, columns) for s in data), )
def take_action_network(self, client, parsed_args): # Get the security group ID to hold the rule. security_group_id = client.find_security_group( parsed_args.group, ignore_missing=False ).id # Build the create attributes. attrs = {} attrs['protocol'] = self._get_protocol(parsed_args) if parsed_args.description is not None: attrs['description'] = parsed_args.description # NOTE(rtheis): A direction must be specified and ingress # is the default. if parsed_args.ingress or not parsed_args.egress: attrs['direction'] = 'ingress' if parsed_args.egress: attrs['direction'] = 'egress' # NOTE(rtheis): Use ethertype specified else default based # on IP protocol. attrs['ethertype'] = self._get_ethertype(parsed_args, attrs['protocol']) # NOTE(rtheis): Validate the port range and ICMP type and code. # It would be ideal if argparse could do this. if parsed_args.dst_port and (parsed_args.icmp_type or parsed_args.icmp_code): msg = _('Argument --dst-port not allowed with arguments ' '--icmp-type and --icmp-code') raise exceptions.CommandError(msg) if parsed_args.icmp_type is None and parsed_args.icmp_code is not None: msg = _('Argument --icmp-type required with argument --icmp-code') raise exceptions.CommandError(msg) is_icmp_protocol = _is_icmp_protocol(attrs['protocol']) if not is_icmp_protocol and (parsed_args.icmp_type or parsed_args.icmp_code): msg = _('ICMP IP protocol required with arguments ' '--icmp-type and --icmp-code') raise exceptions.CommandError(msg) # NOTE(rtheis): For backwards compatibility, continue ignoring # the destination port range when an ICMP IP protocol is specified. if parsed_args.dst_port and not is_icmp_protocol: attrs['port_range_min'] = parsed_args.dst_port[0] attrs['port_range_max'] = parsed_args.dst_port[1] if parsed_args.icmp_type is not None and parsed_args.icmp_type >= 0: attrs['port_range_min'] = parsed_args.icmp_type if parsed_args.icmp_code is not None and parsed_args.icmp_code >= 0: attrs['port_range_max'] = parsed_args.icmp_code if parsed_args.remote_group is not None: attrs['remote_group_id'] = client.find_security_group( parsed_args.remote_group, ignore_missing=False ).id elif parsed_args.remote_ip is not None: attrs['remote_ip_prefix'] = parsed_args.remote_ip elif attrs['ethertype'] == 'IPv4': attrs['remote_ip_prefix'] = '0.0.0.0/0' elif attrs['ethertype'] == 'IPv6': attrs['remote_ip_prefix'] = '::/0' attrs['security_group_id'] = security_group_id if parsed_args.project is not None: identity_client = self.app.client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id # Create and show the security group rule. obj = client.create_security_group_rule(**attrs) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return (display_columns, data)
def get_parser(self, prog_name): parser = super(ShowSubnetPool, self).get_parser(prog_name) parser.add_argument('subnet_pool', metavar='<subnet-pool>', help=_("Subnet pool to display (name or ID)")) return parser
class CreateSecurityGroupRule(common.NetworkAndComputeShowOne): _description = _("Create a new security group rule") def update_parser_common(self, parser): parser.add_argument( 'group', metavar='<group>', help=_("Create rule in this security group (name or ID)") ) remote_group = parser.add_mutually_exclusive_group() remote_group.add_argument( "--remote-ip", metavar="<ip-address>", help=_("Remote IP address block (may use CIDR notation; " "default for IPv4 rule: 0.0.0.0/0, " "default for IPv6 rule: ::/0)"), ) remote_group.add_argument( "--remote-group", metavar="<group>", help=_("Remote security group (name or ID)"), ) return parser def update_parser_network(self, parser): parser.add_argument( '--description', metavar='<description>', help=_("Set security group rule description") ) parser.add_argument( '--dst-port', metavar='<port-range>', action=parseractions.RangeAction, help=_("Destination port, may be a single port or a starting and " "ending port range: 137:139. Required for IP protocols TCP " "and UDP. Ignored for ICMP IP protocols.") ) parser.add_argument( '--icmp-type', metavar='<icmp-type>', type=int, help=_("ICMP type for ICMP IP protocols") ) parser.add_argument( '--icmp-code', metavar='<icmp-code>', type=int, help=_("ICMP code for ICMP IP protocols") ) # NOTE(rtheis): Support either protocol option name for now. # However, consider deprecating and then removing --proto in # a future release. protocol_group = parser.add_mutually_exclusive_group() protocol_group.add_argument( '--protocol', metavar='<protocol>', type=_convert_to_lowercase, help=_("IP protocol (ah, dccp, egp, esp, gre, icmp, igmp, " "ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, " "ipv6-opts, ipv6-route, ospf, pgm, rsvp, sctp, tcp, " "udp, udplite, vrrp and integer representations [0-255] " "or any; default: any (all protocols))") ) protocol_group.add_argument( '--proto', metavar='<proto>', type=_convert_to_lowercase, help=argparse.SUPPRESS ) direction_group = parser.add_mutually_exclusive_group() direction_group.add_argument( '--ingress', action='store_true', help=_("Rule applies to incoming network traffic (default)") ) direction_group.add_argument( '--egress', action='store_true', help=_("Rule applies to outgoing network traffic") ) parser.add_argument( '--ethertype', metavar='<ethertype>', choices=['IPv4', 'IPv6'], type=_convert_ipvx_case, help=_("Ethertype of network traffic " "(IPv4, IPv6; default: based on IP protocol)") ) parser.add_argument( '--project', metavar='<project>', help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) return parser def update_parser_compute(self, parser): parser.add_argument( '--dst-port', metavar='<port-range>', default=(0, 0), action=parseractions.RangeAction, help=_("Destination port, may be a single port or a starting and " "ending port range: 137:139. Required for IP protocols TCP " "and UDP. Ignored for ICMP IP protocols.") ) # NOTE(rtheis): Support either protocol option name for now. # However, consider deprecating and then removing --proto in # a future release. protocol_group = parser.add_mutually_exclusive_group() protocol_group.add_argument( '--protocol', metavar='<protocol>', choices=['icmp', 'tcp', 'udp'], type=_convert_to_lowercase, help=_("IP protocol (icmp, tcp, udp; default: tcp)") ) protocol_group.add_argument( '--proto', metavar='<proto>', choices=['icmp', 'tcp', 'udp'], type=_convert_to_lowercase, help=argparse.SUPPRESS ) return parser def _get_protocol(self, parsed_args, default_protocol='any'): protocol = default_protocol if parsed_args.protocol is not None: protocol = parsed_args.protocol if parsed_args.proto is not None: protocol = parsed_args.proto if protocol == 'any': protocol = None return protocol def _get_ethertype(self, parsed_args, protocol): ethertype = 'IPv4' if parsed_args.ethertype is not None: ethertype = parsed_args.ethertype elif self._is_ipv6_protocol(protocol): ethertype = 'IPv6' return ethertype def _is_ipv6_protocol(self, protocol): # NOTE(rtheis): Neutron has deprecated protocol icmpv6. # However, while the OSC CLI doesn't document the protocol, # the code must still handle it. In addition, handle both # protocol names and numbers. if (protocol is not None and protocol.startswith('ipv6-') or protocol in ['icmpv6', '41', '43', '44', '58', '59', '60']): return True else: return False def take_action_network(self, client, parsed_args): # Get the security group ID to hold the rule. security_group_id = client.find_security_group( parsed_args.group, ignore_missing=False ).id # Build the create attributes. attrs = {} attrs['protocol'] = self._get_protocol(parsed_args) if parsed_args.description is not None: attrs['description'] = parsed_args.description # NOTE(rtheis): A direction must be specified and ingress # is the default. if parsed_args.ingress or not parsed_args.egress: attrs['direction'] = 'ingress' if parsed_args.egress: attrs['direction'] = 'egress' # NOTE(rtheis): Use ethertype specified else default based # on IP protocol. attrs['ethertype'] = self._get_ethertype(parsed_args, attrs['protocol']) # NOTE(rtheis): Validate the port range and ICMP type and code. # It would be ideal if argparse could do this. if parsed_args.dst_port and (parsed_args.icmp_type or parsed_args.icmp_code): msg = _('Argument --dst-port not allowed with arguments ' '--icmp-type and --icmp-code') raise exceptions.CommandError(msg) if parsed_args.icmp_type is None and parsed_args.icmp_code is not None: msg = _('Argument --icmp-type required with argument --icmp-code') raise exceptions.CommandError(msg) is_icmp_protocol = _is_icmp_protocol(attrs['protocol']) if not is_icmp_protocol and (parsed_args.icmp_type or parsed_args.icmp_code): msg = _('ICMP IP protocol required with arguments ' '--icmp-type and --icmp-code') raise exceptions.CommandError(msg) # NOTE(rtheis): For backwards compatibility, continue ignoring # the destination port range when an ICMP IP protocol is specified. if parsed_args.dst_port and not is_icmp_protocol: attrs['port_range_min'] = parsed_args.dst_port[0] attrs['port_range_max'] = parsed_args.dst_port[1] if parsed_args.icmp_type is not None and parsed_args.icmp_type >= 0: attrs['port_range_min'] = parsed_args.icmp_type if parsed_args.icmp_code is not None and parsed_args.icmp_code >= 0: attrs['port_range_max'] = parsed_args.icmp_code if parsed_args.remote_group is not None: attrs['remote_group_id'] = client.find_security_group( parsed_args.remote_group, ignore_missing=False ).id elif parsed_args.remote_ip is not None: attrs['remote_ip_prefix'] = parsed_args.remote_ip elif attrs['ethertype'] == 'IPv4': attrs['remote_ip_prefix'] = '0.0.0.0/0' elif attrs['ethertype'] == 'IPv6': attrs['remote_ip_prefix'] = '::/0' attrs['security_group_id'] = security_group_id if parsed_args.project is not None: identity_client = self.app.client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id # Create and show the security group rule. obj = client.create_security_group_rule(**attrs) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return (display_columns, data) def take_action_compute(self, client, parsed_args): group = client.api.security_group_find(parsed_args.group) protocol = self._get_protocol(parsed_args, default_protocol='tcp') if protocol == 'icmp': from_port, to_port = -1, -1 else: from_port, to_port = parsed_args.dst_port remote_ip = None if parsed_args.remote_group is not None: parsed_args.remote_group = client.api.security_group_find( parsed_args.remote_group, )['id'] if parsed_args.remote_ip is not None: remote_ip = parsed_args.remote_ip else: remote_ip = '0.0.0.0/0' obj = client.api.security_group_rule_create( security_group_id=group['id'], ip_protocol=protocol, from_port=from_port, to_port=to_port, remote_ip=remote_ip, remote_group=parsed_args.remote_group, ) return _format_security_group_rule_show(obj)
class ListSecurityGroupRule(common.NetworkAndComputeLister): _description = _("List security group rules") def _format_network_security_group_rule(self, rule): """Transform the SDK SecurityGroupRule object to a dict The SDK object gets in the way of reformatting columns... Create port_range column from port_range_min and port_range_max """ rule = rule.to_dict() rule['port_range'] = _format_network_port_range(rule) rule['remote_ip_prefix'] = _format_remote_ip_prefix(rule) return rule def update_parser_common(self, parser): parser.add_argument( 'group', metavar='<group>', nargs='?', help=_("List all rules in this security group (name or ID)") ) return parser def update_parser_network(self, parser): # Accept but hide the argument for consistency with compute. # Network will always return all projects for an admin. parser.add_argument( '--all-projects', action='store_true', default=False, help=argparse.SUPPRESS ) parser.add_argument( '--protocol', metavar='<protocol>', type=_convert_to_lowercase, help=_("List rules by the IP protocol (" "ah, dhcp, egp, esp, gre, icmp, igmp, " "ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, " "ipv6-opts, ipv6-route, ospf, pgm, rsvp, sctp, tcp, " "udp, udplite, vrrp and integer representations [0-255] " "or any; default: any (all protocols))") ) parser.add_argument( '--ethertype', metavar='<ethertype>', type=_convert_to_lowercase, help=_("List rules by the Ethertype (IPv4 or IPv6)") ) direction_group = parser.add_mutually_exclusive_group() direction_group.add_argument( '--ingress', action='store_true', help=_("List rules applied to incoming network traffic") ) direction_group.add_argument( '--egress', action='store_true', help=_("List rules applied to outgoing network traffic") ) parser.add_argument( '--long', action='store_true', default=False, help=_("List additional fields in output") ) return parser def update_parser_compute(self, parser): parser.add_argument( '--all-projects', action='store_true', default=False, help=_("Display information from all projects (admin only)") ) # Accept but hide the argument for consistency with network. # There are no additional fields to display at this time. parser.add_argument( '--long', action='store_false', default=False, help=argparse.SUPPRESS ) return parser def _get_column_headers(self, parsed_args): column_headers = ( 'ID', 'IP Protocol', 'Ethertype', 'IP Range', 'Port Range', ) if parsed_args.long: column_headers = column_headers + ('Direction',) column_headers = column_headers + ('Remote Security Group',) if parsed_args.group is None: column_headers = column_headers + ('Security Group',) return column_headers def take_action_network(self, client, parsed_args): column_headers = self._get_column_headers(parsed_args) columns = ( 'id', 'protocol', 'ether_type', 'remote_ip_prefix', 'port_range', ) if parsed_args.long: columns = columns + ('direction',) columns = columns + ('remote_group_id',) # Get the security group rules using the requested query. query = {} if parsed_args.group is not None: # NOTE(rtheis): Unfortunately, the security group resource # does not contain security group rules resources. So use # the security group ID in a query to get the resources. security_group_id = client.find_security_group( parsed_args.group, ignore_missing=False ).id query = {'security_group_id': security_group_id} else: columns = columns + ('security_group_id',) if parsed_args.ingress: query['direction'] = 'ingress' if parsed_args.egress: query['direction'] = 'egress' if parsed_args.protocol is not None: query['protocol'] = parsed_args.protocol rules = [ self._format_network_security_group_rule(r) for r in client.security_group_rules(**query) ] return (column_headers, (utils.get_dict_properties( s, columns, ) for s in rules)) def take_action_compute(self, client, parsed_args): column_headers = self._get_column_headers(parsed_args) columns = ( "ID", "IP Protocol", "Ethertype", "IP Range", "Port Range", "Remote Security Group", ) rules_to_list = [] if parsed_args.group is not None: group = client.api.security_group_find( parsed_args.group, ) rules_to_list = group['rules'] else: columns = columns + ('parent_group_id',) search = {'all_tenants': parsed_args.all_projects} for group in client.api.security_group_list(search_opts=search): rules_to_list.extend(group['rules']) # NOTE(rtheis): Turn the raw rules into resources. rules = [] for rule in rules_to_list: rules.append( network_utils.transform_compute_security_group_rule(rule), ) # rules.append(compute_secgroup_rules.SecurityGroupRule( # client.security_group_rules, # network_utils.transform_compute_security_group_rule(rule), # )) return (column_headers, (utils.get_dict_properties( s, columns, ) for s in rules))
class SetVolumeSnapshot(command.Command): _description = _("Set volume snapshot properties") def get_parser(self, prog_name): parser = super(SetVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshot', metavar='<snapshot>', help=_('Snapshot to modify (name or ID)') ) parser.add_argument( '--name', metavar='<name>', help=_('New snapshot name') ) parser.add_argument( '--description', metavar='<description>', help=_('New snapshot description') ) parser.add_argument( "--no-property", dest="no_property", action="store_true", help=_("Remove all properties from <snapshot> " "(specify both --no-property and --property to " "remove the current properties before setting " "new properties.)"), ) parser.add_argument( '--property', metavar='<key=value>', action=parseractions.KeyValueAction, help=_('Property to add/change for this snapshot ' '(repeat option to set multiple properties)'), ) parser.add_argument( '--state', metavar='<state>', choices=['available', 'error', 'creating', 'deleting', 'error-deleting'], help=_('New snapshot state. ("available", "error", "creating", ' '"deleting", or "error_deleting") (admin only) ' '(This option simply changes the state of the snapshot ' 'in the database with no regard to actual status, ' 'exercise caution when using)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume snapshot = utils.find_resource(volume_client.volume_snapshots, parsed_args.snapshot) result = 0 if parsed_args.no_property: try: key_list = snapshot.metadata.keys() volume_client.volume_snapshots.delete_metadata( snapshot.id, list(key_list), ) except Exception as e: LOG.error(_("Failed to clean snapshot properties: %s"), e) result += 1 if parsed_args.property: try: volume_client.volume_snapshots.set_metadata( snapshot.id, parsed_args.property) except Exception as e: LOG.error(_("Failed to set snapshot property: %s"), e) result += 1 if parsed_args.state: try: volume_client.volume_snapshots.reset_state( snapshot.id, parsed_args.state) except Exception as e: LOG.error(_("Failed to set snapshot state: %s"), e) result += 1 kwargs = {} if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.description: kwargs['description'] = parsed_args.description if kwargs: try: volume_client.volume_snapshots.update( snapshot.id, **kwargs) except Exception as e: LOG.error(_("Failed to update snapshot name " "or description: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("One or more of the " "set operations failed"))
def update_parser_network(self, parser): parser.add_argument( '--description', metavar='<description>', help=_("Set security group rule description") ) parser.add_argument( '--dst-port', metavar='<port-range>', action=parseractions.RangeAction, help=_("Destination port, may be a single port or a starting and " "ending port range: 137:139. Required for IP protocols TCP " "and UDP. Ignored for ICMP IP protocols.") ) parser.add_argument( '--icmp-type', metavar='<icmp-type>', type=int, help=_("ICMP type for ICMP IP protocols") ) parser.add_argument( '--icmp-code', metavar='<icmp-code>', type=int, help=_("ICMP code for ICMP IP protocols") ) # NOTE(rtheis): Support either protocol option name for now. # However, consider deprecating and then removing --proto in # a future release. protocol_group = parser.add_mutually_exclusive_group() protocol_group.add_argument( '--protocol', metavar='<protocol>', type=_convert_to_lowercase, help=_("IP protocol (ah, dccp, egp, esp, gre, icmp, igmp, " "ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, " "ipv6-opts, ipv6-route, ospf, pgm, rsvp, sctp, tcp, " "udp, udplite, vrrp and integer representations [0-255] " "or any; default: any (all protocols))") ) protocol_group.add_argument( '--proto', metavar='<proto>', type=_convert_to_lowercase, help=argparse.SUPPRESS ) direction_group = parser.add_mutually_exclusive_group() direction_group.add_argument( '--ingress', action='store_true', help=_("Rule applies to incoming network traffic (default)") ) direction_group.add_argument( '--egress', action='store_true', help=_("Rule applies to outgoing network traffic") ) parser.add_argument( '--ethertype', metavar='<ethertype>', choices=['IPv4', 'IPv6'], type=_convert_ipvx_case, help=_("Ethertype of network traffic " "(IPv4, IPv6; default: based on IP protocol)") ) parser.add_argument( '--project', metavar='<project>', help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) return parser
def get_parser(self, prog_name): parser = super(ShowProject, self).get_parser(prog_name) parser.add_argument('project', metavar='<project>', help=_('Project to display (name or ID)')) return parser
class CreateVolumeSnapshot(command.ShowOne): _description = _("Create new volume snapshot") def get_parser(self, prog_name): parser = super(CreateVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( "snapshot_name", metavar="<snapshot-name>", help=_("Name of the new snapshot"), ) parser.add_argument( "--volume", metavar="<volume>", help=_("Volume to snapshot (name or ID) " "(default is <snapshot-name>)") ) parser.add_argument( "--description", metavar="<description>", help=_("Description of the snapshot") ) parser.add_argument( "--force", action="store_true", default=False, help=_("Create a snapshot attached to an instance. " "Default is False") ) parser.add_argument( "--property", metavar="<key=value>", action=parseractions.KeyValueAction, help=_("Set a property to this snapshot " "(repeat option to set multiple properties)"), ) parser.add_argument( "--remote-source", metavar="<key=value>", action=parseractions.KeyValueAction, help=_("The attribute(s) of the exsiting remote volume snapshot " "(admin required) (repeat option to specify multiple " "attributes) e.g.: '--remote-source source-name=test_name " "--remote-source source-id=test_id'"), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume = parsed_args.volume if not parsed_args.volume: volume = parsed_args.snapshot_name volume_id = utils.find_resource( volume_client.volumes, volume).id if parsed_args.remote_source: # Create a new snapshot from an existing remote snapshot source if parsed_args.force: msg = (_("'--force' option will not work when you create " "new volume snapshot from an existing remote " "volume snapshot")) LOG.warning(msg) snapshot = volume_client.volume_snapshots.manage( volume_id=volume_id, ref=parsed_args.remote_source, name=parsed_args.snapshot_name, description=parsed_args.description, metadata=parsed_args.property, ) else: # create a new snapshot from scratch snapshot = volume_client.volume_snapshots.create( volume_id, force=parsed_args.force, name=parsed_args.snapshot_name, description=parsed_args.description, metadata=parsed_args.property, ) snapshot._info.update( {'properties': format_columns.DictColumn(snapshot._info.pop('metadata'))} ) return zip(*sorted(six.iteritems(snapshot._info)))
def get_parser(self, prog_name): parser = super(DeleteRole, self).get_parser(prog_name) parser.add_argument('role', metavar='<role>', help=_('Name or ID of role to delete')) return parser
class ListVolumeSnapshot(command.Lister): _description = _("List volume snapshots") def get_parser(self, prog_name): parser = super(ListVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( '--all-projects', action='store_true', default=False, help=_('Include all projects (admin only)'), ) parser.add_argument( '--project', metavar='<project>', help=_('Filter results by project (name or ID) (admin only)') ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( '--marker', metavar='<volume-snapshot>', help=_('The last snapshot ID of the previous page'), ) parser.add_argument( '--limit', type=int, action=parseractions.NonNegativeAction, metavar='<num-snapshots>', help=_('Maximum number of snapshots to display'), ) parser.add_argument( '--name', metavar='<name>', default=None, help=_('Filters results by a name.') ) parser.add_argument( '--status', metavar='<status>', choices=['available', 'error', 'creating', 'deleting', 'error-deleting'], help=_("Filters results by a status. " "('available', 'error', 'creating', 'deleting'" " or 'error-deleting')") ) parser.add_argument( '--volume', metavar='<volume>', default=None, help=_('Filters results by a volume (name or ID).') ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume identity_client = self.app.client_manager.identity if parsed_args.long: columns = ['ID', 'Name', 'Description', 'Status', 'Size', 'Created At', 'Volume ID', 'Metadata'] column_headers = copy.deepcopy(columns) column_headers[6] = 'Volume' column_headers[7] = 'Properties' else: columns = ['ID', 'Name', 'Description', 'Status', 'Size'] column_headers = copy.deepcopy(columns) # Cache the volume list volume_cache = {} try: for s in volume_client.volumes.list(): volume_cache[s.id] = s except Exception: # Just forget it if there's any trouble pass _VolumeIdColumn = functools.partial(VolumeIdColumn, volume_cache=volume_cache) volume_id = None if parsed_args.volume: volume_id = utils.find_resource( volume_client.volumes, parsed_args.volume).id project_id = None if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain).id # set value of 'all_tenants' when using project option all_projects = True if parsed_args.project else \ parsed_args.all_projects search_opts = { 'all_tenants': all_projects, 'project_id': project_id, 'name': parsed_args.name, 'status': parsed_args.status, 'volume_id': volume_id, } data = volume_client.volume_snapshots.list( search_opts=search_opts, marker=parsed_args.marker, limit=parsed_args.limit, ) return (column_headers, (utils.get_item_properties( s, columns, formatters={'Metadata': format_columns.DictColumn, 'Volume ID': _VolumeIdColumn}, ) for s in data))