commit bf6c3b52f676888203082e25e404ed5e9503648e Author: rpm-build Date: Mon Feb 12 12:11:43 2018 -0500 neutron extensions diff --git a/openstackclient/network/v2/host.py b/openstackclient/network/v2/host.py new file mode 100644 index 0000000..f9dab8b --- /dev/null +++ b/openstackclient/network/v2/host.py @@ -0,0 +1,191 @@ +# 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. +# +# Copyright (c) 2016 Wind River Systems, Inc. +# +# +# +# +# + +"""Host action implementations""" + +from osc_lib.command import command +from osc_lib import exceptions +from osc_lib import utils +from openstackclient.network import common +from openstackclient.network import sdk_utils + +_showhost_formatters = { + 'agents': utils.format_list_of_dicts +} + +_listhost_formatters = { + 'agents': len +} + + +def _get_columns(item): + column_map = {} + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) + + +def _get_attrs(client_manager, parsed_args): + attrs = {key: parsed_args[key] for key in ['availability', 'id', 'name'] + if key in parsed_args and parsed_args[key] is not None} + return attrs + + +class ListHost(common.NetworkAndComputeLister): + """List host""" + + def update_parser_common(self, parser): + return parser + + def take_action_network(self, client, parsed_args): + columns = ( + 'id', + 'name', + 'availability', + 'agents', + 'subnets', + 'routers', + 'ports' + ) + column_headers = ( + 'Id', + 'Name', + 'Availability', + 'Agents', + 'Subnets', + 'Routers', + 'Ports' + ) + + args = {} + + data = client.hosts(**args) + + return (column_headers, + (utils.get_item_properties( + s, columns, + formatters=_listhost_formatters, + ) for s in data)) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class ShowHost(common.NetworkAndComputeShowOne): + """Show host details""" + + def update_parser_common(self, parser): + parser.add_argument( + 'host', + metavar="", + help=("ID or name of host to look up") + ) + return parser + + def take_action_network(self, client, parsed_args): + obj = client.find_host(parsed_args.host, ignore_missing=False) + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns, + formatters=_showhost_formatters) + return (display_columns, data) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class CreateHost(common.NetworkAndComputeShowOne): + """Create a host record""" + + def update_parser_common(self, parser): + parser.add_argument('--availability', metavar="availability", + help='Set host availability status to up or down', + required=False) + parser.add_argument('--id', metavar="id", + help='Create a new host record', + required=False) + parser.add_argument('name', metavar='NAME', + help='System hostname of given host') + return parser + + def take_action_network(self, client, parsed_args): + attrs = _get_attrs(self.app.client_manager, vars(parsed_args)) + + # the neutron equivalent command defaults to availability=down + # when not specified + if "availability" not in attrs: + attrs['availability'] = "down" + + obj = client.create_host(**attrs) + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns, + formatters=_listhost_formatters) + return (display_columns, data) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class DeleteHost(common.NetworkAndComputeDelete): + """Delete host""" + + # Used by base class to find resources in parsed_args. + resource = 'name' + r = None + + def update_parser_common(self, parser): + parser.add_argument('name', metavar='NAME', nargs="+", + help='System hostname of given host') + return parser + + def take_action_network(self, client, parsed_args): + obj = client.find_host(self.r) + client.delete_host(obj) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class UpdateHost(command.Command): + """Set host properties""" + + def get_parser(self, prog_name): + parser = super(UpdateHost, self).get_parser(prog_name) + parser.add_argument('--availability', metavar="availability", + help='Set host availability status to up or down', + required=False) + parser.add_argument('host', metavar='HOST', + help='System hostname of given host') + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + obj = client.find_host(parsed_args.host, ignore_missing=False) + attrs = _get_attrs(self.app.client_manager, vars(parsed_args)) + + if attrs == {}: + msg = "Nothing specified to be set" + raise exceptions.CommandError(msg) + client.update_host(obj, **attrs) + return diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py index 9536fe8..4a29daf 100644 --- a/openstackclient/network/v2/port.py +++ b/openstackclient/network/v2/port.py @@ -62,6 +62,9 @@ def _get_columns(item): 'is_admin_state_up': 'admin_state_up', 'is_port_security_enabled': 'port_security_enabled', 'tenant_id': 'project_id', + 'mtu': 'wrs-binding:mtu', + 'vif_model': 'wrs-binding:vif_model', + 'mac_filtering': 'wrs-binding:mac_filtering', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) diff --git a/openstackclient/network/v2/portforwarding.py b/openstackclient/network/v2/portforwarding.py new file mode 100644 index 0000000..0f70e84 --- /dev/null +++ b/openstackclient/network/v2/portforwarding.py @@ -0,0 +1,259 @@ +# 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. +# +# Copyright (c) 2016 Wind River Systems, Inc. +# +# +# +# +# + +"""Port forwarding action implementations""" + +import argparse +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 +from openstackclient.network import common +from openstackclient.network import sdk_utils + +_formatters = {} + + +def _get_columns(item): + column_map = {} + invisible_columns = ["name"] + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map, + invisible_columns) + + +def _get_attrs(client_manager, parsed_args): + attr_names = ['inside_addr', 'inside_port', 'outside_port', + 'protocol', 'description', 'router_id'] + attrs = {key: parsed_args[key] for key in attr_names + if key in parsed_args and parsed_args[key] is not None} + + if 'project' in parsed_args and parsed_args["project"] is not None: + identity_client = client_manager.identity + project_id = identity_common.find_project( + identity_client, + parsed_args["project"] + ).id + # TODO(dtroyer): Remove tenant_id when we clean up the SDK refactor + attrs['tenant_id'] = project_id + attrs['project_id'] = project_id + + return attrs + + +class ListPortforwarding(common.NetworkAndComputeLister): + """List portforwarding""" + + def update_parser_common(self, parser): + parser.add_argument( + '--project', + metavar='', + help=_("Owner's project (name or ID)") + ) + parser.add_argument( + '--router-id', + metavar='', + help=_("Router's ID") + ) + return parser + + def take_action_network(self, client, parsed_args): + columns = ( + 'id', + 'router_id', + 'inside_addr', + 'inside_port', + 'outside_port', + 'protocol', + ) + column_headers = ( + 'ID', + 'Router ID', + 'Inside Address', + 'Inside Port', + 'Outside Port', + 'Protocol' + ) + + args = _get_attrs(self.app.client_manager, vars(parsed_args)) + + data = client.portforwardings(**args) + + return (column_headers, + (utils.get_item_properties( + s, columns, + formatters=_formatters, + ) for s in data)) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class ShowPortforwarding(common.NetworkAndComputeShowOne): + """Show portforwarding details""" + + def update_parser_common(self, parser): + parser.add_argument( + 'portforwarding', + metavar="", + help=("Portforwarding to display (ID)") + ) + return parser + + def take_action_network(self, client, parsed_args): + obj = client.find_portforwarding(parsed_args.portforwarding, + ignore_missing=False) + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns, formatters=_formatters) + return (display_columns, data) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class CreatePortforwarding(common.NetworkAndComputeShowOne): + """Create new portforwarding""" + + def update_parser_common(self, parser): + parser.add_argument( + '--inside-addr', + help='Private IP address.') + parser.add_argument( + '--inside_addr', + help=argparse.SUPPRESS) + parser.add_argument( + '--inside-port', + help='Private layer4 protocol port.') + parser.add_argument( + '--inside_port', + help=argparse.SUPPRESS) + parser.add_argument( + '--outside-port', + help='Public layer4 protocol port.') + parser.add_argument( + '--outside_port', + help=argparse.SUPPRESS) + parser.add_argument( + '--protocol', + help='Layer4 protocol port number.') + parser.add_argument( + '--project', + metavar='', + help=_("Owner's project (name or ID)") + ) + identity_common.add_project_domain_option_to_parser(parser) + parser.add_argument( + '--description', + help='User specified text description') + parser.add_argument( + 'router_id', metavar='ROUTERID', + help='Router instance identifier.') + + return parser + + def take_action_network(self, client, parsed_args): + attrs = _get_attrs(self.app.client_manager, vars(parsed_args)) + router = client.find_router(attrs['router_id'], ignore_missing=False) + attrs['router_id'] = router.id + obj = client.create_portforwarding(**attrs) + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns, formatters=_formatters) + return (display_columns, data) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class DeletePortforwarding(common.NetworkAndComputeDelete): + """Delete portforwarding""" + + # Used by base class to find resources in parsed_args. + resource = 'portforwarding' + r = None + + def update_parser_common(self, parser): + parser.add_argument( + 'portforwarding', + metavar="", + nargs="+", + help=("Portforwarding to delete (ID)") + ) + return parser + + def take_action_network(self, client, parsed_args): + obj = client.find_portforwarding(self.r) + client.delete_portforwarding(obj) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class UpdatePortforwarding(command.Command): + """Set portforwarding properties""" + + def get_parser(self, prog_name): + parser = super(UpdatePortforwarding, self).get_parser(prog_name) + parser.add_argument( + '--inside-addr', + help='Private IP address.') + parser.add_argument( + '--inside_addr', + help=argparse.SUPPRESS) + parser.add_argument( + '--inside-port', + help='Private layer4 protocol port.') + parser.add_argument( + '--inside_port', + help=argparse.SUPPRESS) + parser.add_argument( + '--outside-port', + help='Public layer4 protocol port.') + parser.add_argument( + '--outside_port', + help=argparse.SUPPRESS) + parser.add_argument( + '--protocol', + help='Layer4 protocol port number.') + parser.add_argument( + '--description', + help='User specified text description') + parser.add_argument( + 'portforwarding', metavar='PORTFORWARDING', + help='Portforwarding to delete (ID)') + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + obj = client.find_portforwarding(parsed_args.portforwarding, + ignore_missing=False) + attrs = _get_attrs(self.app.client_manager, vars(parsed_args)) + + if attrs == {}: + msg = "Nothing specified to be set" + raise exceptions.CommandError(msg) + client.update_portforwarding(obj, **attrs) + return diff --git a/openstackclient/network/v2/providernet.py b/openstackclient/network/v2/providernet.py new file mode 100644 index 0000000..635eb64 --- /dev/null +++ b/openstackclient/network/v2/providernet.py @@ -0,0 +1,302 @@ +# 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. +# +# Copyright (c) 2016 Wind River Systems, Inc. +# +# +# +# +# + +"""Providernet action implementations""" + +import argparse + +from osc_lib.command import command +from osc_lib import exceptions +from osc_lib import utils +from openstackclient.network import common +from openstackclient.network import sdk_utils + + +def add_boolean_argument(parser, name, **kwargs): + for keyword in ('metavar', 'choices'): + kwargs.pop(keyword, None) + default = kwargs.pop('default', argparse.SUPPRESS) + parser.add_argument( + name, + metavar='{True,False}', + choices=['True', 'true', 'False', 'false'], + default=default, + **kwargs) + + +def _format_ranges(item): + item = utils.format_list_of_dicts(item) + # we want to remove some fields + # to match the output to neutron providernet-list + separator = ', ' + item = item.split(separator) + item = [s for s in item if "name" in s or "maximum" in s or "minimum" in s] + + return separator.join(item) + +# the providernet list command does not display some values in the ranges field +_filtered_ranges_formatters = { + 'ranges': _format_ranges +} + +_formatters = { + 'ranges': utils.format_list_of_dicts +} + +_net_list_on_providernet_formatters = { + 'vxlan': utils.format_dict +} + + +def _get_columns(item): + column_map = {} + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) + + +def _get_attrs(client_manager, parsed_args): + attrs = {key: parsed_args[key] for key in + ["name", "type", "vlan_transparent", "description", "mtu"] + if key in parsed_args} + if "mtu" in attrs and attrs["mtu"] is None: + del attrs["mtu"] + + return attrs + + +class ListProvidernet(common.NetworkAndComputeLister): + """List providernets""" + + def update_parser_common(self, parser): + parser.add_argument( + '--type', + dest='type', + help='List all providernets of type') + return parser + + def take_action_network(self, client, parsed_args): + columns = ( + 'id', + 'name', + 'type', + 'mtu', + 'ranges' + ) + column_headers = ( + 'ID', + 'Name', + 'Type', + 'MTU', + 'Ranges' + ) + + args = _get_attrs(self.app.client_manager, vars(parsed_args)) + + data = client.providernets(**args) + + return (column_headers, + (utils.get_item_properties( + s, columns, + formatters=_filtered_ranges_formatters, + ) for s in data)) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class ShowProvidernet(common.NetworkAndComputeShowOne): + """Show providernet details""" + + def update_parser_common(self, parser): + parser.add_argument( + 'providernet', + metavar="", + help=("Providernet to display (name or ID)") + ) + return parser + + def take_action_network(self, client, parsed_args): + obj = client.find_providernet(parsed_args.providernet, + ignore_missing=False) + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns, formatters=_formatters) + return (display_columns, data) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class CreateProvidernet(common.NetworkAndComputeShowOne): + """Create new providernet""" + + def update_parser_common(self, parser): + parser.add_argument( + '--description', + dest='description', + help='Set user-defined description field for a provider network') + parser.add_argument( + '--type', required=True, + dest='type', default='flat', + choices=['flat', 'vlan', 'vxlan'], + help='Set network type for a provider network') + parser.add_argument( + '--mtu', dest='mtu', type=int, + help='Maximum transmit unit on provider network') + add_boolean_argument( + parser, + '--vlan-transparent', + default='False', + help='Allow VLAN tagged packets on tenant networks') + parser.add_argument( + 'name', metavar='NAME', + help='Set user-defined name for a provider network') + + return parser + + def take_action_network(self, client, parsed_args): + attrs = _get_attrs(self.app.client_manager, vars(parsed_args)) + obj = client.create_providernet(**attrs) + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns, formatters=_formatters) + return (display_columns, data) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class DeleteProvidernet(common.NetworkAndComputeDelete): + """Delete providernet""" + + # Used by base class to find resources in parsed_args. + resource = 'providernet' + r = None + + def update_parser_common(self, parser): + parser.add_argument( + 'providernet', + metavar="", + nargs="+", + help=("Providernet to delete (name or ID)") + ) + return parser + + def take_action_network(self, client, parsed_args): + obj = client.find_providernet(self.r) + client.delete_providernet(obj) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class UpdateProvidernet(command.Command): + """Set providernet properties""" + + def get_parser(self, prog_name): + parser = super(UpdateProvidernet, self).get_parser(prog_name) + parser.add_argument( + '--description', + dest='description', + help='Set user-defined description field for a provider network') + parser.add_argument( + '--mtu', dest='mtu', type=int, + help='Maximum transmit unit on provider network') + add_boolean_argument( + parser, + '--vlan-transparent', + help='Allow VLAN tagged packets on tenant networks') + parser.add_argument( + 'providernet', metavar='PROVIDERNET', + help='Set user-defined name for a provider network') + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + + obj = client.find_providernet(parsed_args.providernet, + ignore_missing=False) + attrs = _get_attrs(self.app.client_manager, vars(parsed_args)) + if attrs == {}: + msg = "Nothing specified to be set" + raise exceptions.CommandError(msg) + + client.update_providernet(obj, **attrs) + return + + +class NetListOnProvidernet(common.NetworkAndComputeLister): + """List the networks on a provider network.""" + + def update_parser_common(self, parser): + parser.add_argument( + 'providernet', + metavar="", + help=("Providernet to display (name or ID)") + ) + return parser + + def take_action_network(self, client, parsed_args): + obj = client.find_providernet(parsed_args.providernet, + ignore_missing=False) + providernet_id = obj.id + + columns = ( + 'id', + 'name', + 'vlan_id', + 'providernet_type', + 'segmentation_id', + 'vxlan', + ) + column_headers = ( + 'ID', + 'Name', + 'VLAN ID', + 'Providernet Type', + 'Segmentation ID', + 'Providernet Attributes' + ) + + args = {} + + # cheated a bit here, doing the same request as a providernet list, + # except using providernet_id/providernet-bindings + # as the base path. Openstack client framwork does not support what + # we need in terms of editing the address at the + # time of implementing this + data = client.net_list_on_providernet(providernet_id + + "/providernet-bindings", **args) + + return (column_headers, + (utils.get_item_properties( + s, columns, + formatters=_net_list_on_providernet_formatters, + ) for s in data)) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return diff --git a/openstackclient/network/v2/providernet_connectivity_test.py b/openstackclient/network/v2/providernet_connectivity_test.py new file mode 100644 index 0000000..e879ec2 --- /dev/null +++ b/openstackclient/network/v2/providernet_connectivity_test.py @@ -0,0 +1,220 @@ +# 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. +# +# Copyright (c) 2016 Wind River Systems, Inc. +# +# +# +# +# + +"""Providernet connectivity test action implementations""" + +import itertools +from osc_lib import exceptions +from osc_lib import utils +from openstackclient.network import common +from openstackclient.network import sdk_utils + +_formatters = { +} + + +def _get_columns(item): + column_map = {} + invisible_columns = ["host_id", "host_name", "id", "message", "name", + "providernet_id", "providernet_name", + "segmentation_id", "status", "type", "updated_at"] + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map, + invisible_columns) + + +def _get_attrs(client_manager, parsed_args, client): + attrs = {key: parsed_args[key] for key in + ["providernet", "host", "segmentation_id", "audit_uuid"] + if key in parsed_args and parsed_args[key] is not None} + if "providernet" in attrs: + providernet = client.find_providernet(attrs.pop("providernet"), + ignore_missing=False) + attrs["providernet_id"] = providernet.id + if "host" in attrs: + host = client.find_host(attrs.pop("host"), ignore_missing=False) + attrs["host_id"] = host.id + return attrs + + +# copied from neutron client and modified to fit data formats here +def _list_segments(segments): + """Takes a list of segments, and outputs them as a string""" + msg = ", ".join([str(x or "*") for x in sorted(segments)]) + return msg + + +# copied from neutron client and modified to fit data formats here +def _group_segmentation_id_list(segmentation_ids): + """Takes a list of integers and groups them into ranges""" + if len(segmentation_ids) < 1: + return "" + try: + sorted_segmentation_ids = sorted( + [int(segmentation_id) for segmentation_id in segmentation_ids] + ) + except Exception: + return _list_segments(segmentation_ids) + grouped_ids = [tuple(g[1]) for g in itertools.groupby( + enumerate(sorted_segmentation_ids), lambda (i, n): i - n + )] + msg = ", ".join( + [(("%s-%s" % (g[0][1], g[-1][1])) if g[0][1] != g[-1][1] + else ("%s" % g[0][1])) for g in grouped_ids] + ) + return msg + + +# copied from neutron client and modified to fit data formats here +def _format_connectivity_results(data): + """Takes a list of results, and formats them for reporting + + order assumed: providernet_id, providernet_name, type, host_name, + segmentation_id, status, message + """ + + parsed_results = {} + has_message = False + for result in data: + providernet_id = result.providernet_id + providernet_name = result.providernet_name + providernet_type = result.type + hostname = result.host_name + if hasattr(result, "segmentation_id"): + segmentation_id = result.segmentation_id + else: + segmentation_id = None + status = result.status + message = result.message + if message: + has_message = True + test = (providernet_id, providernet_name, providernet_type, + hostname, status, message) + if test not in parsed_results: + parsed_results[test] = [] + parsed_results[test].append(segmentation_id) + + formatted_results = [] + for test, results in parsed_results.iteritems(): + (providernet_id, providernet_name, providernet_type, + hostname, status, message) = test + formatted_segmentation_ids = \ + _group_segmentation_id_list(results) + + if has_message: + formatted_result = (providernet_id, + providernet_name, + providernet_type, + hostname, + formatted_segmentation_ids, + status, + message + ) + else: + formatted_result = (providernet_id, + providernet_name, + providernet_type, + hostname, + formatted_segmentation_ids, + status + ) + formatted_results.append(formatted_result) + + return tuple(formatted_results), has_message + + +class ListProvidernetConnectivityTest(common.NetworkAndComputeLister): + """List providernet connectivity tests""" + + def update_parser_common(self, parser): + parser.add_argument( + '--audit-uuid', + dest='audit_uuid', default=None, + help='List only for this audit-uuid') + parser.add_argument( + '--providernet', + dest='providernet', default=None, + help='List only for this providernet') + parser.add_argument( + '--host', + dest='host', default=None, + help='List only for this host') + parser.add_argument( + '--segmentation-id', + dest='segmentation_id', default=None, + help='List only for this segmentation-id') + return parser + + def take_action_network(self, client, parsed_args): + column_headers = ( + 'Providernet ID', + 'Providernet Name', + 'Type', + 'Host Name', + 'Segmentation IDs', + 'Status' + ) + args = _get_attrs(self.app.client_manager, vars(parsed_args), client) + + data = client.providernet_connectivity_tests(**args) + formatted_data, has_message = _format_connectivity_results(data) + + # replicate behavior from neutron command: + # dont show message column if it does not exist + if has_message: + column_headers = column_headers + ('Message',) + + return (column_headers, + formatted_data) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class CreateProvidernetConnectivityTest(common.NetworkAndComputeShowOne): + """Create new providernet connectivity test""" + + def update_parser_common(self, parser): + parser.add_argument( + '--providernet', + dest='providernet', default=None, + help=('Schedule audit for given providernet')) + parser.add_argument( + '--host', + dest='host', default=None, + help='Schedule audits for all providernets on host') + parser.add_argument( + '--segmentation-id', + dest='segmentation_id', default=None, + help='Schedule for this segmentation ID') + + return parser + + def take_action_network(self, client, parsed_args): + attrs = _get_attrs(self.app.client_manager, vars(parsed_args), client) + obj = client.create_providernet_connectivity_test(**attrs) + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns, formatters=_formatters) + return (display_columns, data) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return diff --git a/openstackclient/network/v2/providernet_range.py b/openstackclient/network/v2/providernet_range.py new file mode 100644 index 0000000..8748c4c --- /dev/null +++ b/openstackclient/network/v2/providernet_range.py @@ -0,0 +1,272 @@ +# 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. +# +# Copyright (c) 2016 Wind River Systems, Inc. +# +# +# +# +# + +"""Providernet range action implementations""" + +import argparse +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 +from openstackclient.network import common +from openstackclient.network import sdk_utils + +_formatters = { + 'vxlan': utils.format_dict +} + + +def _get_columns(item): + column_map = {} + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) + + +def _get_attrs(client_manager, parsed_args): + attrs = {key: parsed_args[key] for key in + ["shared", "description", "name", "group", "ttl", "port", "mode", + "providernet_id", "providernet_range_id"] + if key in parsed_args} + if "range" in parsed_args and parsed_args["range"] is not None: + attrs["maximum"] = parsed_args["range"]["maximum"] + attrs["minimum"] = parsed_args["range"]["minimum"] + if "port" in attrs and attrs["port"] is None: + del attrs["port"] + if "ttl" in attrs and attrs["ttl"] is None: + del attrs["ttl"] + if "group" in attrs and attrs["group"] is None: + del attrs["group"] + if "mode" in attrs and attrs["mode"] is None: + del attrs["mode"] + if 'project' in parsed_args and parsed_args["project"] is not None: + identity_client = client_manager.identity + project_id = identity_common.find_project( + identity_client, + parsed_args["project"] + ).id + # TODO(dtroyer): Remove tenant_id when we clean up the SDK refactor + attrs['tenant_id'] = project_id + attrs['project_id'] = project_id + + return attrs + + +def _id_range_value(value): + range_list = value.split('-') + if (len(range_list) != 2): + raise argparse.ArgumentTypeError( + 'Expecting MIN_VALUE-MAX_VALUE in range list') + return {'minimum': range_list[0], + 'maximum': range_list[1]} + + +class ListProvidernetRange(common.NetworkAndComputeLister): + """List providernet ranges""" + + def update_parser_common(self, parser): + parser.add_argument( + '--project', + metavar='', + help=_("Owner's project (name or ID)") + ) + return parser + + def take_action_network(self, client, parsed_args): + columns = ( + 'id', + 'name', + 'providernet_name', + 'providernet_type', + 'minimum', + 'maximum', + 'vxlan' + ) + column_headers = ( + 'ID', + 'Name', + 'Providernet', + 'Type', + 'Minimum', + 'Maximum', + 'Attributes' + ) + + args = _get_attrs(self.app.client_manager, vars(parsed_args)) + + data = client.providernet_ranges(**args) + + return (column_headers, + (utils.get_item_properties( + s, columns, + formatters=_formatters, + ) for s in data)) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class ShowProvidernetRange(common.NetworkAndComputeShowOne): + """Show providernet range details""" + + def update_parser_common(self, parser): + parser.add_argument( + 'providernet_range', + metavar="", + help=("Providernet range to display (name or ID)") + ) + return parser + + def take_action_network(self, client, parsed_args): + obj = client.find_providernet_range(parsed_args.providernet_range, + ignore_missing=False) + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns, formatters=_formatters) + return (display_columns, data) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class CreateProvidernetRange(common.NetworkAndComputeShowOne): + """Create new providernet range""" + + def update_parser_common(self, parser): + parser.add_argument( + '--shared', + dest='shared', action='store_true', default=False, + help=('Set whether a provider network segmentation id range ' + 'may be shared between tenants')) + parser.add_argument( + '--project', + metavar='', + help=_("Owner's project (name or ID)") + ) + identity_common.add_project_domain_option_to_parser(parser) + parser.add_argument( + '--description', + dest='description', + help='Set user-defined description field for a provider network') + parser.add_argument( + '--range', metavar='MIN_VALUE-MAX_VALUE', required=True, + dest='range', type=_id_range_value, + help='Segmentation id value range') + parser.add_argument( + '--name', required=True, + dest='name', + help=('Set user-defined name for a provider network ' + 'segmentation id range')) + parser.add_argument( + '--group', + dest='group', + help='Multicast IP addresses for VXLAN endpoints') + parser.add_argument( + '--ttl', dest='ttl', type=int, + help='Time-to-live value for VXLAN provider networks') + parser.add_argument( + '--port', dest='port', type=int, + help=('Destination UDP port value to use for ' + 'VXLAN provider networks')) + parser.add_argument( + '--mode', + dest='mode', default='dynamic', + choices=['dynamic', 'static', 'evpn'], + help='Set vxlan learning mode') + parser.add_argument( + 'providernet_id', metavar='PROVIDERNET', + help='Provider network this segmentation id range belongs to') + + return parser + + def take_action_network(self, client, parsed_args): + attrs = _get_attrs(self.app.client_manager, vars(parsed_args)) + obj = client.find_providernet(parsed_args.providernet_id, + ignore_missing=False) + attrs["providernet_id"] = obj.id + obj = client.create_providernet_range(**attrs) + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns, formatters=_formatters) + return (display_columns, data) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class DeleteProvidernetRange(common.NetworkAndComputeDelete): + """Delete providernet range""" + + # Used by base class to find resources in parsed_args. + resource = 'providernet_range' + r = None + + def update_parser_common(self, parser): + parser.add_argument( + 'providernet_range', + metavar="", + nargs="+", + help=("Providernet to Delete (name or ID)") + ) + return parser + + def take_action_network(self, client, parsed_args): + obj = client.find_providernet_range(self.r) + client.delete_providernet_range(obj) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class UpdateProvidernetRange(command.Command): + """Set providernet range properties""" + + def get_parser(self, prog_name): + parser = super(UpdateProvidernetRange, self).get_parser(prog_name) + parser.add_argument( + '--description', + dest='description', + help='Set user-defined description field for a provider network') + parser.add_argument( + '--range', metavar='MIN_VALUE-MAX_VALUE', + dest='range', type=_id_range_value, + help='Segmentation id value range') + parser.add_argument( + 'providernet_range_id', metavar='PROVIDERNET_RANGE', + help='Name or ID of this providernet range') + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + obj = client.find_providernet_range(parsed_args.providernet_range_id, + ignore_missing=False) + + attrs = _get_attrs(self.app.client_manager, vars(parsed_args)) + del attrs['providernet_range_id'] + + if attrs == {}: + msg = "Nothing specified to be set" + raise exceptions.CommandError(msg) + client.update_providernet_range(obj, **attrs) + return diff --git a/openstackclient/network/v2/providernet_type.py b/openstackclient/network/v2/providernet_type.py new file mode 100644 index 0000000..2abd8c4 --- /dev/null +++ b/openstackclient/network/v2/providernet_type.py @@ -0,0 +1,60 @@ +# 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. +# +# Copyright (c) 2016 Wind River Systems, Inc. +# +# +# +# +# + +"""Providernet type action implementations""" + +from osc_lib import exceptions +from osc_lib import utils +from openstackclient.network import common +from openstackclient.network import sdk_utils + +_formatters = { +} + + +class ListProvidernetType(common.NetworkAndComputeLister): + """List providernet types""" + + def update_parser_common(self, parser): + return parser + + def take_action_network(self, client, parsed_args): + columns = ( + 'type', + 'description' + ) + column_headers = ( + 'Type', + 'Description' + ) + + args = {} + + data = client.providernet_types(**args) + + return (column_headers, + (utils.get_item_properties( + s, columns, + formatters=_formatters, + ) for s in data)) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return diff --git a/openstackclient/network/v2/router.py b/openstackclient/network/v2/router.py index 4f90853..4eb5908 100644 --- a/openstackclient/network/v2/router.py +++ b/openstackclient/network/v2/router.py @@ -68,6 +68,7 @@ def _get_columns(item): 'is_ha': 'ha', 'is_distributed': 'distributed', 'is_admin_state_up': 'admin_state_up', + 'host': 'wrs-net:host', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) diff --git a/openstackclient/network/v2/setting.py b/openstackclient/network/v2/setting.py new file mode 100644 index 0000000..d404325 --- /dev/null +++ b/openstackclient/network/v2/setting.py @@ -0,0 +1,183 @@ +# 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. +# +# Copyright (c) 2016 Wind River Systems, Inc. +# +# +# +# +# + +"""Settings action implementations""" + +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 +from openstackclient.network import common +from openstackclient.network import sdk_utils + +_formatters = {} + + +def _get_columns(item): + column_map = {"id": "project_id"} + invisible_columns = ["name"] + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map, + invisible_columns) + + +def _get_attrs(client_manager, parsed_args): + attrs = {key: parsed_args[key] for key in ["mac_filtering"] + if key in parsed_args} + + if 'project' in parsed_args and parsed_args["project"] is not None: + identity_client = client_manager.identity + project_id = identity_common.find_project( + identity_client, + parsed_args["project"] + ).id + attrs['project_id'] = project_id + + return attrs + + +class ListSetting(common.NetworkAndComputeLister): + """List settings of all projects who have non-default setting values""" + + def update_parser_common(self, parser): + return parser + + def take_action_network(self, client, parsed_args): + columns = ( + 'mac_filtering', + 'project_id' + ) + column_headers = ( + 'Mac Filtering', + 'Project ID' + ) + + args = {} + + data = client.settings(**args) + + return (column_headers, + (utils.get_item_properties( + s, columns, + formatters=_formatters, + ) for s in data)) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +class ShowSetting(common.NetworkAndComputeShowOne): + """Show settings of a given project""" + + def update_parser_common(self, parser): + parser.add_argument( + '--project', + metavar='', + help=_("Owner's project (name or ID)"), + required=False + ) + return parser + + def take_action_network(self, client, parsed_args): + client = self.app.client_manager.network + # if no project id is specified, operate on current project + args = _get_attrs(self.app.client_manager, vars(parsed_args)) + if not "project_id" in args: + args["project_id"] = client.find_tenant().project_id + project_id = args["project_id"] + + obj = client.find_setting(project_id, ignore_missing=False) + + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns, formatters=_formatters) + return (display_columns, data) + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs access to" + " a network endpoint.") + return + + +# this one uses NetworkAndComputeCommand because settings can be deleted +# without a project id +class DeleteSetting(common.NetworkAndComputeCommand): + """Delete setting""" + + def update_parser_common(self, parser): + parser.add_argument( + '--project', + metavar='', + help=_("Owner's project (name or ID)"), + required=False + ) + return parser + + def take_action_network(self, client, parsed_args): + client = self.app.client_manager.network + # if no project id is specified, operate on current project + args = _get_attrs(self.app.client_manager, vars(parsed_args)) + if not "project_id" in args: + args["project_id"] = client.find_tenant().project_id + project_id = args["project_id"] + + client.delete_setting(project_id) + return + + def take_action_compute(self, client, parsed_args): + raise exceptions.CommandError("This command needs " + "access to a network endpoint.") + return + + +class UpdateSetting(command.Command): + """Set setting properties""" + + def get_parser(self, prog_name): + parser = super(UpdateSetting, self).get_parser(prog_name) + parser.add_argument( + '--project', + metavar='', + help=_("Owner's project (name or ID)"), + required=False + ) + parser.add_argument('--mac-filtering', metavar='mac_filtering', + help="Enable/Disable source MAC filtering" + " on all ports", + required=True) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + # if no project id is specified, operate on current project + args = _get_attrs(self.app.client_manager, vars(parsed_args)) + if not "project_id" in args: + args["project_id"] = client.find_tenant().project_id + project_id = args["project_id"] + del args['project_id'] + + client.find_setting(project_id, ignore_missing=False) + + if args == {}: + msg = "Nothing specified to be set" + raise exceptions.CommandError(msg) + + client.update_setting(project_id, **args) + return diff --git a/openstackclient/network/v2/subnet.py b/openstackclient/network/v2/subnet.py index b96dff7..864c832 100644 --- a/openstackclient/network/v2/subnet.py +++ b/openstackclient/network/v2/subnet.py @@ -13,7 +13,9 @@ """Subnet action implementations""" +import argparse import copy +import functools import logging from osc_lib.cli import parseractions @@ -27,6 +29,10 @@ from openstackclient.network import sdk_utils from openstackclient.network.v2 import _tag +MIN_VLAN_TAG = 1 +MAX_VLAN_TAG = 4094 + + LOG = logging.getLogger(__name__) @@ -233,9 +239,36 @@ def _get_attrs(client_manager, parsed_args, is_create=True): attrs['service_types'] = parsed_args.service_types if parsed_args.description is not None: attrs['description'] = parsed_args.description + + # wrs extensions + if ('vlan_id' in parsed_args and + parsed_args.vlan_id is not None): + attrs['wrs-net:vlan_id'] = parsed_args.vlan_id + if ('network_type' in parsed_args and + parsed_args.network_type is not None): + attrs['wrs-provider:network_type'] = parsed_args.network_type + if ('physical_network' in parsed_args and + parsed_args.physical_network is not None): + attrs['wrs-provider:vlan_id'] = parsed_args.physical_network + if ('segmentation_id' in parsed_args and + parsed_args.segmentation_id is not None): + attrs['wrs-provider:segmentation_id'] = parsed_args.segmentation_id + if ('unmanaged' in parsed_args and + parsed_args.unmanaged is not False): + attrs['wrs-net:managed'] = False + return attrs +def _check_vlan_id(value): + vlan_id = int(value) + if vlan_id < MIN_VLAN_TAG or vlan_id > MAX_VLAN_TAG: + raise argparse.ArgumentTypeError( + "VLAN ID must be between {} and {}".format( + MIN_VLAN_TAG, MAX_VLAN_TAG)) + return vlan_id + + # TODO(abhiraut): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateSubnet(command.ShowOne): @@ -337,6 +370,27 @@ class CreateSubnet(command.ShowOne): metavar='', help=_("Set subnet description") ) + parser.add_argument( + '--wrs-net:vlan_id', + dest='vlan_id', + type=_check_vlan_id, + help='VLAN ID of the subnet') + parser.add_argument( + '--wrs-provider:network_type', + dest='network_type', + help='Provider network type (admin only)') + parser.add_argument( + '--wrs-provider:physical_network', + dest='physical_network', + help='Provider network name (admin only)') + parser.add_argument( + '--wrs-provider:segmentation_id', + dest='segmentation_id', + help='Provider network segmentation id (admin only)') + parser.add_argument( + '--unmanaged', + action='store_true', + help='Disable IP allocation on this subnet') _get_common_parse_arguments(parser) _tag.add_tag_option_to_parser_for_create(parser, _('subnet')) return parser @@ -497,14 +551,16 @@ class ListSubnet(command.Lister): _tag.get_tag_filtering_args(parsed_args, filters) data = network_client.subnets(**filters) - headers = ('ID', 'Name', 'Network', 'Subnet') - columns = ('id', 'name', 'network_id', 'cidr') + headers = ('ID', 'Name', 'Network', 'Subnet', 'Allocation Pools', + 'WRS-Net:VLAN ID') + columns = ('id', 'name', 'network_id', 'cidr', 'allocation_pools', + 'wrs-net:vlan_id') if parsed_args.long: headers += ('Project', 'DHCP', 'Name Servers', - 'Allocation Pools', 'Host Routes', 'IP Version', + 'Host Routes', 'IP Version', 'Gateway', 'Service Types', 'Tags') columns += ('project_id', 'is_dhcp_enabled', 'dns_nameservers', - 'allocation_pools', 'host_routes', 'ip_version', + 'host_routes', 'ip_version', 'gateway_ip', 'service_types', 'tags') return (headers, diff --git a/openstackclient/tests/unit/network/v2/fakes.py b/openstackclient/tests/unit/network/v2/fakes.py index eadab58..0d53fc5 100644 --- a/openstackclient/tests/unit/network/v2/fakes.py +++ b/openstackclient/tests/unit/network/v2/fakes.py @@ -1244,7 +1244,8 @@ class FakeSecurityGroupRule(object): @staticmethod def get_security_group_rules(security_group_rules=None, count=2): - """Get an iterable Mock object with a list of faked security group rules. + """Get an iterable Mock object with a list of faked security group + rules. If security group rules list is provided, then initialize the Mock object with the list. Otherwise create one. @@ -1298,6 +1299,7 @@ class FakeSubnet(object): 'subnetpool_id': None, 'description': 'subnet-description-' + uuid.uuid4().hex, 'tags': [], + 'wrs-net:vlan_id': '1', } # Overwrite default attributes. diff --git a/openstackclient/tests/unit/network/v2/test_subnet.py b/openstackclient/tests/unit/network/v2/test_subnet.py index c96d680..a4c8914 100644 --- a/openstackclient/tests/unit/network/v2/test_subnet.py +++ b/openstackclient/tests/unit/network/v2/test_subnet.py @@ -126,6 +126,7 @@ class TestCreateSubnet(TestSubnet): 'service_types', 'subnetpool_id', 'tags', + 'wrs-net:vlan_id', ) data = ( @@ -147,6 +148,7 @@ class TestCreateSubnet(TestSubnet): utils.format_list(_subnet.service_types), _subnet.subnetpool_id, utils.format_list(_subnet.tags), + getattr(_subnet, 'wrs-net:vlan_id', ''), ) data_subnet_pool = ( @@ -168,6 +170,7 @@ class TestCreateSubnet(TestSubnet): utils.format_list(_subnet_from_pool.service_types), _subnet_from_pool.subnetpool_id, utils.format_list(_subnet.tags), + getattr(_subnet_from_pool, 'wrs-net:vlan_id', ''), ) data_ipv6 = ( @@ -189,6 +192,7 @@ class TestCreateSubnet(TestSubnet): utils.format_list(_subnet_ipv6.service_types), _subnet_ipv6.subnetpool_id, utils.format_list(_subnet.tags), + getattr(_subnet_ipv6, 'wrs-net:vlan_id', ''), ) def setUp(self): @@ -589,12 +593,13 @@ class TestListSubnet(TestSubnet): 'Name', 'Network', 'Subnet', + 'Allocation Pools', + 'WRS-Net:VLAN ID', ) columns_long = columns + ( 'Project', 'DHCP', 'Name Servers', - 'Allocation Pools', 'Host Routes', 'IP Version', 'Gateway', @@ -609,6 +614,8 @@ class TestListSubnet(TestSubnet): subnet.name, subnet.network_id, subnet.cidr, + subnet_v2._format_allocation_pools(subnet.allocation_pools), + getattr(subnet, 'wrs-net:vlan_id', ''), )) data_long = [] @@ -618,10 +625,11 @@ class TestListSubnet(TestSubnet): subnet.name, subnet.network_id, subnet.cidr, + subnet_v2._format_allocation_pools(subnet.allocation_pools), + getattr(subnet, 'wrs-net:vlan_id', ''), subnet.tenant_id, subnet.enable_dhcp, utils.format_list(subnet.dns_nameservers), - subnet_v2._format_allocation_pools(subnet.allocation_pools), utils.format_list(subnet.host_routes), subnet.ip_version, subnet.gateway_ip, @@ -1093,6 +1101,7 @@ class TestShowSubnet(TestSubnet): 'service_types', 'subnetpool_id', 'tags', + 'wrs-net:vlan_id', ) data = ( @@ -1114,6 +1123,7 @@ class TestShowSubnet(TestSubnet): utils.format_list(_subnet.service_types), _subnet.subnetpool_id, utils.format_list(_subnet.tags), + getattr(_subnet, 'wrs-net:vlan_id', ''), ) def setUp(self): diff --git a/setup.cfg b/setup.cfg index 0afa479..1bff735 100644 --- a/setup.cfg +++ b/setup.cfg @@ -398,6 +398,34 @@ openstack.network.v2 = subnet_pool_set = openstackclient.network.v2.subnet_pool:SetSubnetPool subnet_pool_show = openstackclient.network.v2.subnet_pool:ShowSubnetPool subnet_pool_unset = openstackclient.network.v2.subnet_pool:UnsetSubnetPool + providernet_list = openstackclient.network.v2.providernet:ListProvidernet + providernet_show = openstackclient.network.v2.providernet:ShowProvidernet + providernet_create = openstackclient.network.v2.providernet:CreateProvidernet + providernet_update = openstackclient.network.v2.providernet:UpdateProvidernet + providernet_delete = openstackclient.network.v2.providernet:DeleteProvidernet + providernet_range_list = openstackclient.network.v2.providernet_range:ListProvidernetRange + providernet_range_show = openstackclient.network.v2.providernet_range:ShowProvidernetRange + providernet_range_create = openstackclient.network.v2.providernet_range:CreateProvidernetRange + providernet_range_update = openstackclient.network.v2.providernet_range:UpdateProvidernetRange + providernet_range_delete = openstackclient.network.v2.providernet_range:DeleteProvidernetRange + portforwarding_list = openstackclient.network.v2.portforwarding:ListPortforwarding + portforwarding_show = openstackclient.network.v2.portforwarding:ShowPortforwarding + portforwarding_create = openstackclient.network.v2.portforwarding:CreatePortforwarding + portforwarding_update = openstackclient.network.v2.portforwarding:UpdatePortforwarding + portforwarding_delete = openstackclient.network.v2.portforwarding:DeletePortforwarding + setting_list = openstackclient.network.v2.setting:ListSetting + setting_show = openstackclient.network.v2.setting:ShowSetting + setting_update = openstackclient.network.v2.setting:UpdateSetting + setting_delete = openstackclient.network.v2.setting:DeleteSetting + net_host_list = openstackclient.network.v2.host:ListHost + net_host_show = openstackclient.network.v2.host:ShowHost + net_host_create = openstackclient.network.v2.host:CreateHost + net_host_update = openstackclient.network.v2.host:UpdateHost + net_host_delete = openstackclient.network.v2.host:DeleteHost + providernet_type_list = openstackclient.network.v2.providernet_type:ListProvidernetType + providernet_connectivity_test_list = openstackclient.network.v2.providernet_connectivity_test:ListProvidernetConnectivityTest + providernet_connectivity_test_schedule = openstackclient.network.v2.providernet_connectivity_test:CreateProvidernetConnectivityTest + net_list_on_providernet = openstackclient.network.v2.providernet:NetListOnProvidernet openstack.object_store.v1 = object_store_account_set = openstackclient.object.v1.account:SetAccount object_store_account_show = openstackclient.object.v1.account:ShowAccount