summaryrefslogtreecommitdiff
path: root/openstackclient/network
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient/network')
-rw-r--r--openstackclient/network/v2/floating_ip.py4
-rw-r--r--openstackclient/network/v2/network.py1
-rw-r--r--openstackclient/network/v2/network_qos_policy.py231
-rw-r--r--openstackclient/network/v2/port.py84
-rw-r--r--openstackclient/network/v2/router.py54
-rw-r--r--openstackclient/network/v2/subnet.py2
-rw-r--r--openstackclient/network/v2/subnet_pool.py18
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