diff options
Diffstat (limited to 'openstackclient/network')
| -rw-r--r-- | openstackclient/network/v2/floating_ip.py | 4 | ||||
| -rw-r--r-- | openstackclient/network/v2/network.py | 1 | ||||
| -rw-r--r-- | openstackclient/network/v2/network_qos_policy.py | 231 | ||||
| -rw-r--r-- | openstackclient/network/v2/port.py | 84 | ||||
| -rw-r--r-- | openstackclient/network/v2/router.py | 54 | ||||
| -rw-r--r-- | openstackclient/network/v2/subnet.py | 2 | ||||
| -rw-r--r-- | openstackclient/network/v2/subnet_pool.py | 18 |
7 files changed, 376 insertions, 18 deletions
diff --git a/openstackclient/network/v2/floating_ip.py b/openstackclient/network/v2/floating_ip.py index bb75540c..e8057628 100644 --- a/openstackclient/network/v2/floating_ip.py +++ b/openstackclient/network/v2/floating_ip.py @@ -203,12 +203,16 @@ class ListFloatingIP(common.NetworkAndComputeLister): 'floating_ip_address', 'fixed_ip_address', 'port_id', + 'floating_network_id', + 'project_id', ) headers = ( 'ID', 'Floating IP Address', 'Fixed IP Address', 'Port', + 'Floating Network', + 'Project', ) query = {} diff --git a/openstackclient/network/v2/network.py b/openstackclient/network/v2/network.py index dbf1b601..40183b73 100644 --- a/openstackclient/network/v2/network.py +++ b/openstackclient/network/v2/network.py @@ -42,6 +42,7 @@ def _get_columns(item): columns = list(item.keys()) if 'tenant_id' in columns: columns.remove('tenant_id') + if 'project_id' not in columns: columns.append('project_id') return tuple(sorted(columns)) diff --git a/openstackclient/network/v2/network_qos_policy.py b/openstackclient/network/v2/network_qos_policy.py new file mode 100644 index 00000000..a8fcfc59 --- /dev/null +++ b/openstackclient/network/v2/network_qos_policy.py @@ -0,0 +1,231 @@ +# Copyright (c) 2016, Intel Corporation. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import logging + +from osc_lib.command import command +from osc_lib import exceptions +from osc_lib import utils + +from openstackclient.i18n import _ +from openstackclient.identity import common as identity_common + + +LOG = logging.getLogger(__name__) + + +def _get_columns(item): + columns = list(item.keys()) + if 'tenant_id' in columns: + columns.remove('tenant_id') + columns.append('project_id') + return tuple(sorted(columns)) + + +def _get_attrs(client_manager, parsed_args): + attrs = {} + if parsed_args.name is not None: + attrs['name'] = str(parsed_args.name) + if parsed_args.description is not None: + attrs['description'] = parsed_args.description + if parsed_args.share: + attrs['shared'] = True + if parsed_args.no_share: + attrs['shared'] = False + if parsed_args.project is not None: + identity_client = client_manager.identity + project_id = identity_common.find_project( + identity_client, + parsed_args.project, + parsed_args.project_domain, + ).id + attrs['tenant_id'] = project_id + + return attrs + + +class CreateNetworkQosPolicy(command.ShowOne): + """Create a QoS policy""" + + 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 take_action(self, parsed_args): + client = self.app.client_manager.network + attrs = _get_attrs(self.app.client_manager, parsed_args) + obj = client.create_qos_policy(**attrs) + columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns, formatters={}) + return columns, data + + +class DeleteNetworkQosPolicy(command.Command): + """Delete Qos Policy(s)""" + + def get_parser(self, prog_name): + parser = super(DeleteNetworkQosPolicy, self).get_parser(prog_name) + parser.add_argument( + 'policy', + metavar="<qos-policy>", + nargs="+", + help=_("QoS policy(s) to delete (name or ID)") + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + result = 0 + + for policy in parsed_args.policy: + try: + obj = client.find_qos_policy(policy, ignore_missing=False) + client.delete_qos_policy(obj) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete QoS policy " + "name or ID '%(qos_policy)s': %(e)s"), + {'qos_policy': policy, 'e': e}) + + if result > 0: + total = len(parsed_args.policy) + msg = (_("%(result)s of %(total)s QoS policies failed " + "to delete.") % {'result': result, 'total': total}) + raise exceptions.CommandError(msg) + + +class ListNetworkQosPolicy(command.Lister): + """List QoS policies""" + + def take_action(self, parsed_args): + client = self.app.client_manager.network + columns = ( + 'id', + 'name', + 'shared', + 'tenant_id', + ) + column_headers = ( + 'ID', + 'Name', + 'Shared', + 'Project', + ) + data = client.qos_policies() + + return (column_headers, + (utils.get_item_properties( + s, columns, formatters={}, + ) for s in data)) + + +class SetNetworkQosPolicy(command.Command): + """Set QoS policy properties""" + + 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 take_action(self, parsed_args): + client = self.app.client_manager.network + obj = client.find_qos_policy( + parsed_args.policy, + ignore_missing=False) + attrs = {} + if parsed_args.name is not None: + attrs['name'] = parsed_args.name + if parsed_args.share: + attrs['shared'] = True + if parsed_args.no_share: + attrs['shared'] = False + if parsed_args.description is not None: + attrs['description'] = parsed_args.description + client.update_qos_policy(obj, **attrs) + + +class ShowNetworkQosPolicy(command.ShowOne): + """Display QoS policy details""" + + def get_parser(self, prog_name): + parser = super(ShowNetworkQosPolicy, self).get_parser(prog_name) + parser.add_argument( + 'policy', + metavar="<qos-policy>", + help=_("QoS policy to display (name or ID)") + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + obj = client.find_qos_policy(parsed_args.policy, + ignore_missing=False) + columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns) + return columns, data diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py index 92b286a9..86174d53 100644 --- a/openstackclient/network/v2/port.py +++ b/openstackclient/network/v2/port.py @@ -281,7 +281,23 @@ class CreatePort(command.ShowOne): help=_("Name of this port") ) # TODO(singhj): Add support for extended options: - # qos,security groups,dhcp, address pairs + # qos,dhcp, address pairs + secgroups = parser.add_mutually_exclusive_group() + secgroups.add_argument( + '--security-group', + metavar='<security-group>', + action='append', + dest='security_groups', + help=_("Security group to associate with this port (name or ID) " + "(repeat option to set multiple security groups)") + ) + secgroups.add_argument( + '--no-security-group', + dest='no_security_group', + action='store_true', + help=_("Associate no security groups with this port") + ) + return parser def take_action(self, parsed_args): @@ -291,6 +307,14 @@ class CreatePort(command.ShowOne): parsed_args.network = _network.id _prepare_fixed_ips(self.app.client_manager, parsed_args) attrs = _get_attrs(self.app.client_manager, parsed_args) + + if parsed_args.security_groups: + attrs['security_groups'] = [client.find_security_group( + sg, ignore_missing=False).id + for sg in parsed_args.security_groups] + if parsed_args.no_security_group: + attrs['security_groups'] = [] + obj = client.create_port(**attrs) columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters=_formatters) @@ -360,6 +384,12 @@ class ListPort(command.Lister): 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 take_action(self, parsed_args): @@ -371,15 +401,20 @@ class ListPort(command.Lister): 'name', 'mac_address', 'fixed_ips', + 'status', ) column_headers = ( 'ID', 'Name', 'MAC Address', 'Fixed IP Addresses', + 'Status', ) filters = {} + if parsed_args.long: + columns += ('security_groups', 'device_owner',) + column_headers += ('Security Groups', 'Device Owner',) if parsed_args.device_owner is not None: filters['device_owner'] = parsed_args.device_owner if parsed_args.router: @@ -463,6 +498,21 @@ class SetPort(command.Command): metavar="<port>", help=_("Port to modify (name or ID)") ) + parser.add_argument( + '--security-group', + metavar='<security-group>', + action='append', + dest='security_groups', + help=_("Security group to associate with this port (name or ID) " + "(repeat option to set multiple security groups)") + ) + parser.add_argument( + '--no-security-group', + dest='no_security_group', + action='store_true', + help=_("Clear existing security groups associated with this port") + ) + return parser def take_action(self, parsed_args): @@ -490,6 +540,17 @@ class SetPort(command.Command): attrs['fixed_ips'] += [ip for ip in obj.fixed_ips if ip] elif parsed_args.no_fixed_ip: attrs['fixed_ips'] = [] + if parsed_args.security_groups and parsed_args.no_security_group: + attrs['security_groups'] = [client.find_security_group(sg, + ignore_missing=False).id + for sg in parsed_args.security_groups] + elif parsed_args.security_groups: + attrs['security_groups'] = obj.security_groups + for sg in parsed_args.security_groups: + sg_id = client.find_security_group(sg, ignore_missing=False).id + attrs['security_groups'].append(sg_id) + elif parsed_args.no_security_group: + attrs['security_groups'] = [] client.update_port(obj, **attrs) @@ -536,6 +597,15 @@ class UnsetPort(command.Command): 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)") @@ -550,6 +620,7 @@ class UnsetPort(command.Command): # Unset* classes tmp_fixed_ips = copy.deepcopy(obj.fixed_ips) tmp_binding_profile = copy.deepcopy(obj.binding_profile) + tmp_secgroups = copy.deepcopy(obj.security_groups) _prepare_fixed_ips(self.app.client_manager, parsed_args) attrs = {} if parsed_args.fixed_ip: @@ -568,5 +639,16 @@ class UnsetPort(command.Command): msg = _("Port does not contain binding-profile %s") % key raise exceptions.CommandError(msg) attrs['binding:profile'] = tmp_binding_profile + if parsed_args.security_groups: + try: + for sg in parsed_args.security_groups: + sg_id = client.find_security_group( + sg, ignore_missing=False).id + tmp_secgroups.remove(sg_id) + except ValueError: + msg = _("Port does not contain security group %s") % sg + raise exceptions.CommandError(msg) + attrs['security_groups'] = tmp_secgroups + if attrs: client.update_port(obj, **attrs) diff --git a/openstackclient/network/v2/router.py b/openstackclient/network/v2/router.py index 48a3a92c..d96c314a 100644 --- a/openstackclient/network/v2/router.py +++ b/openstackclient/network/v2/router.py @@ -261,6 +261,22 @@ class ListRouter(command.Lister): def get_parser(self, prog_name): parser = super(ListRouter, self).get_parser(prog_name) parser.add_argument( + '--name', + metavar='<name>', + help=_("List routers according to their name") + ) + admin_state_group = parser.add_mutually_exclusive_group() + admin_state_group.add_argument( + '--enable', + action='store_true', + help=_("List enabled routers") + ) + admin_state_group.add_argument( + '--disable', + action='store_true', + help=_("List disabled routers") + ) + parser.add_argument( '--long', action='store_true', default=False, @@ -289,6 +305,17 @@ class ListRouter(command.Lister): 'HA', 'Project', ) + + args = {} + + if parsed_args.name is not None: + args['name'] = parsed_args.name + + if parsed_args.enable: + args['admin_state_up'] = True + elif parsed_args.disable: + args['admin_state_up'] = False + if parsed_args.long: columns = columns + ( 'routes', @@ -308,7 +335,7 @@ class ListRouter(command.Lister): 'Availability zones', ) - data = client.routers() + data = client.routers(**args) return (column_headers, (utils.get_item_properties( s, columns, @@ -433,11 +460,19 @@ class SetRouter(command.Command): action='store_true', help=argparse.SUPPRESS, ) - - # TODO(tangchen): Support setting 'ha' property in 'router set' - # command. It appears that changing the ha state is supported by - # neutron under certain conditions. - + routes_ha = parser.add_mutually_exclusive_group() + routes_ha.add_argument( + '--ha', + action='store_true', + help=_("Set the router as highly available " + "(disabled router only)") + ) + routes_ha.add_argument( + '--no-ha', + action='store_true', + help=_("Clear high availablability attribute of the router " + "(disabled router only)") + ) # TODO(tangchen): Support setting 'external_gateway_info' property in # 'router set' command. @@ -451,6 +486,10 @@ class SetRouter(command.Command): attrs = _get_attrs(self.app.client_manager, parsed_args) # Get the route attributes. + if parsed_args.ha: + attrs['ha'] = True + elif parsed_args.no_ha: + attrs['ha'] = False if parsed_args.no_route: attrs['routes'] = [] elif parsed_args.clear_routes: @@ -520,12 +559,11 @@ class UnsetRouter(command.Command): if parsed_args.routes: try: for route in parsed_args.routes: + route['nexthop'] = route.pop('gateway') tmp_routes.remove(route) except ValueError: msg = (_("Router does not contain route %s") % route) raise exceptions.CommandError(msg) - for route in tmp_routes: - route['nexthop'] = route.pop('gateway') attrs['routes'] = tmp_routes if attrs: client.update_router(obj, **attrs) diff --git a/openstackclient/network/v2/subnet.py b/openstackclient/network/v2/subnet.py index 1b778c91..f1ecb5a7 100644 --- a/openstackclient/network/v2/subnet.py +++ b/openstackclient/network/v2/subnet.py @@ -542,7 +542,7 @@ class SetSubnet(command.Command): if not parsed_args.no_allocation_pool: attrs['allocation_pools'] += obj.allocation_pools elif parsed_args.no_allocation_pool: - attrs['allocation_pools'] = '' + attrs['allocation_pools'] = [] if 'service_types' in attrs: attrs['service_types'] += obj.service_types client.update_subnet(obj, **attrs) diff --git a/openstackclient/network/v2/subnet_pool.py b/openstackclient/network/v2/subnet_pool.py index a01d2f7b..a29c4518 100644 --- a/openstackclient/network/v2/subnet_pool.py +++ b/openstackclient/network/v2/subnet_pool.py @@ -238,40 +238,42 @@ class ListSubnetPool(command.Lister): shared_group.add_argument( '--share', action='store_true', - help=_("List subnets shared between projects"), + help=_("List subnet pools shared between projects"), ) shared_group.add_argument( '--no-share', action='store_true', - help=_("List subnets not shared between projects"), + 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 subnets used as the default external subnet pool"), + help=_("List subnet pools used as the default external " + "subnet pool"), ) default_group.add_argument( '--no-default', action='store_true', - help=_("List subnets not used as the default external subnet pool") + help=_("List subnet pools not used as the default external " + "subnet pool") ) parser.add_argument( '--project', metavar='<project>', - help=_("List subnets according to their project (name or ID)") + 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 subnets of given name in output") + help=_("List only subnet pools of given name in output") ) parser.add_argument( '--address-scope', metavar='<address-scope>', - help=_("List only subnets of given address scope (name or ID) " - "in output") + help=_("List only subnet pools of given address scope " + "(name or ID) in output") ) return parser |
