diff options
| author | Na <nazhu@cn.ibm.com> | 2016-07-12 02:50:06 -0500 |
|---|---|---|
| committer | Akihiro Motoki <amotoki@gmail.com> | 2017-10-26 14:10:42 +0900 |
| commit | 33947da4b93c41248cb6c46c1f6e0a7bdcaaf9e9 (patch) | |
| tree | 8ba1ed9a256abf657c214084975b7acb7c5fecff /neutronclient/osc | |
| parent | 0907ccc4df68c71f1af71976819bff741829e434 (diff) | |
| download | python-neutronclient-33947da4b93c41248cb6c46c1f6e0a7bdcaaf9e9.tar.gz | |
Dynamic routing CLIs OSC transition
Neutron is transitioning its CLI to OSC, should update dynamic routing
CLIs to align with OSC plugin.
Change-Id: Ic1a633ca103d9e97e28ddf23e0f528e0261ce497
Co-Authored-By: Ryan Tidwell <ryan@6tidwells.com>
Co-Authored-By: Roey Chen <roeyc@vmware.com>
Partially-Implements: blueprint bgp-spinout
Partial-Bug: #1560003
Diffstat (limited to 'neutronclient/osc')
| -rw-r--r-- | neutronclient/osc/v2/dynamic_routing/bgp_dragent.py | 99 | ||||
| -rw-r--r-- | neutronclient/osc/v2/dynamic_routing/bgp_peer.py | 188 | ||||
| -rw-r--r-- | neutronclient/osc/v2/dynamic_routing/bgp_speaker.py | 320 | ||||
| -rw-r--r-- | neutronclient/osc/v2/dynamic_routing/constants.py | 18 |
4 files changed, 625 insertions, 0 deletions
diff --git a/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py b/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py new file mode 100644 index 0000000..f7f1e83 --- /dev/null +++ b/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py @@ -0,0 +1,99 @@ +# 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. +# + +from osc_lib.command import command +from osc_lib import utils + +from neutronclient._i18n import _ +from neutronclient.osc.v2.dynamic_routing import constants + + +def _format_alive_state(item): + return ':-)' if item else 'XXX' + + +_formatters = { + 'alive': _format_alive_state +} + + +def add_common_args(parser): + parser.add_argument('dragent_id', + metavar='<agent-id>', + help=_("ID of the dynamic routing agent")) + parser.add_argument('bgp_speaker', + metavar='<bgp-speaker>', + help=_("ID or name of the BGP speaker")) + + +class AddBgpSpeakerToDRAgent(command.Command): + """Add a BGP speaker to a dynamic routing agent""" + + def get_parser(self, prog_name): + parser = super(AddBgpSpeakerToDRAgent, self).get_parser(prog_name) + add_common_args(parser) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + speaker_id = client.find_resource(constants.BGP_SPEAKER, + parsed_args.bgp_speaker)['id'] + client.add_bgp_speaker_to_dragent( + parsed_args.dragent_id, {'bgp_speaker_id': speaker_id}) + + +class RemoveBgpSpeakerFromDRAgent(command.Command): + """Removes a BGP speaker from a dynamic routing agent""" + + def get_parser(self, prog_name): + parser = super(RemoveBgpSpeakerFromDRAgent, self).get_parser( + prog_name) + add_common_args(parser) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + speaker_id = client.find_resource(constants.BGP_SPEAKER, + parsed_args.bgp_speaker)['id'] + client.remove_bgp_speaker_from_dragent(parsed_args.dragent_id, + speaker_id) + + +class ListDRAgentsHostingBgpSpeaker(command.Lister): + """List dynamic routing agents hosting a BGP speaker""" + + resource = 'agent' + list_columns = ['id', 'host', 'admin_state_up', 'alive'] + unknown_parts_flag = False + + def get_parser(self, prog_name): + parser = super(ListDRAgentsHostingBgpSpeaker, + self).get_parser(prog_name) + parser.add_argument('bgp_speaker', + metavar='<bgp-speaker>', + help=_("ID or name of the BGP speaker")) + return parser + + def take_action(self, parsed_args): + search_opts = {} + client = self.app.client_manager.neutronclient + speaker_id = client.find_resource(constants.BGP_SPEAKER, + parsed_args.bgp_speaker)['id'] + search_opts['bgp_speaker'] = speaker_id + data = client.list_dragents_hosting_bgp_speaker(**search_opts) + headers = ('ID', 'Host', 'State', 'Alive') + columns = ('id', 'host', 'admin_state_up', 'alive') + return (headers, + (utils.get_dict_properties( + s, columns, formatters=_formatters, + ) for s in data['agents'])) diff --git a/neutronclient/osc/v2/dynamic_routing/bgp_peer.py b/neutronclient/osc/v2/dynamic_routing/bgp_peer.py new file mode 100644 index 0000000..c245ce2 --- /dev/null +++ b/neutronclient/osc/v2/dynamic_routing/bgp_peer.py @@ -0,0 +1,188 @@ +# 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. +# + +from osc_lib.command import command +from osc_lib import utils + +from neutronclient._i18n import _ +from neutronclient.common import exceptions +from neutronclient.common import utils as nc_utils +from neutronclient.osc import utils as nc_osc_utils +from neutronclient.osc.v2.dynamic_routing import constants + + +def _get_attrs(client_manager, parsed_args): + attrs = {} + + # Validate password + if 'auth_type' in parsed_args: + if parsed_args.auth_type != 'none': + if 'password' not in parsed_args or parsed_args.password is None: + raise exceptions.CommandError(_('Must provide password if ' + 'auth-type is specified.')) + if ( + parsed_args.auth_type == 'none' and + parsed_args.password is not None + ): + raise exceptions.CommandError(_('Must provide auth-type if ' + 'password is specified.')) + attrs['auth_type'] = parsed_args.auth_type + + if parsed_args.name is not None: + attrs['name'] = parsed_args.name + if 'remote_as' in parsed_args: + attrs['remote_as'] = parsed_args.remote_as + if 'peer_ip' in parsed_args: + attrs['peer_ip'] = parsed_args.peer_ip + if 'password' in parsed_args: + attrs['password'] = parsed_args.password + + if 'project' in parsed_args and parsed_args.project is not None: + identity_client = client_manager.identity + project_id = nc_osc_utils.find_project( + identity_client, + parsed_args.project, + parsed_args.project_domain, + ).id + attrs['tenant_id'] = project_id + return attrs + + +class CreateBgpPeer(command.ShowOne): + _description = _("Create a BGP peer") + + def get_parser(self, prog_name): + parser = super(CreateBgpPeer, self).get_parser(prog_name) + parser.add_argument( + 'name', + metavar='<name>', + help=_("Name of the BGP peer to create")) + parser.add_argument( + '--peer-ip', + metavar='<peer-ip-address>', + required=True, + help=_("Peer IP address")) + parser.add_argument( + '--remote-as', + required=True, + metavar='<peer-remote-as>', + help=_("Peer AS number. (Integer in [%(min_val)s, %(max_val)s] " + "is allowed)") % {'min_val': constants.MIN_AS_NUM, + 'max_val': constants.MAX_AS_NUM}) + parser.add_argument( + '--auth-type', + metavar='<peer-auth-type>', + choices=['none', 'md5'], + type=nc_utils.convert_to_lowercase, + default='none', + help=_("Authentication algorithm. Supported algorithms: " + "none (default), md5")) + parser.add_argument( + '--password', + metavar='<auth-password>', + help=_("Authentication password")) + nc_osc_utils.add_project_owner_option_to_parser(parser) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + attrs = _get_attrs(self.app.client_manager, parsed_args) + body = {constants.BGP_PEER: attrs} + obj = client.create_bgp_peer(body)[constants.BGP_PEER] + columns, display_columns = nc_osc_utils.get_columns(obj) + data = utils.get_dict_properties(obj, columns) + return display_columns, data + + +class DeleteBgpPeer(command.Command): + _description = _("Delete a BGP peer") + + def get_parser(self, prog_name): + parser = super(DeleteBgpPeer, self).get_parser(prog_name) + parser.add_argument( + 'bgp_peer', + metavar="<bgp-peer>", + help=_("BGP peer to delete (name or ID)") + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + id = client.find_resource(constants.BGP_PEER, + parsed_args.bgp_peer)['id'] + client.delete_bgp_peer(id) + + +class ListBgpPeer(command.Lister): + _description = _("List BGP peers") + + def take_action(self, parsed_args): + data = self.app.client_manager.neutronclient.list_bgp_peers() + headers = ('ID', 'Name', 'Peer IP', 'Remote AS') + columns = ('id', 'name', 'peer_ip', 'remote_as') + return (headers, + (utils.get_dict_properties( + s, columns, + ) for s in data[constants.BGP_PEERS])) + + +class SetBgpPeer(command.Command): + _description = _("Update a BGP peer") + resource = constants.BGP_PEER + + def get_parser(self, prog_name): + parser = super(SetBgpPeer, self).get_parser(prog_name) + parser.add_argument( + '--name', + help=_("Updated name of the BGP peer")) + parser.add_argument( + '--password', + metavar='<auth-password>', + help=_("Updated authentication password")) + parser.add_argument( + 'bgp_peer', + metavar="<bgp-peer>", + help=_("BGP peer to update (name or ID)") + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + id = client.find_resource(constants.BGP_PEER, + parsed_args.bgp_peer)['id'] + attrs = _get_attrs(self.app.client_manager, parsed_args) + body = {} + body[constants.BGP_PEER] = attrs + client.update_bgp_peer(id, body) + + +class ShowBgpPeer(command.ShowOne): + _description = _("Show information for a BGP peer") + + def get_parser(self, prog_name): + parser = super(ShowBgpPeer, self).get_parser(prog_name) + parser.add_argument( + 'bgp_peer', + metavar="<bgp-peer>", + help=_("BGP peer to display (name or ID)") + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + id = client.find_resource(constants.BGP_PEER, + parsed_args.bgp_peer)['id'] + obj = client.show_bgp_peer(id)[constants.BGP_PEER] + columns, display_columns = nc_osc_utils.get_columns(obj) + data = utils.get_dict_properties(obj, columns) + return display_columns, data diff --git a/neutronclient/osc/v2/dynamic_routing/bgp_speaker.py b/neutronclient/osc/v2/dynamic_routing/bgp_speaker.py new file mode 100644 index 0000000..bfe202f --- /dev/null +++ b/neutronclient/osc/v2/dynamic_routing/bgp_speaker.py @@ -0,0 +1,320 @@ +# 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. +# + +from osc_lib.command import command +from osc_lib import utils + +from neutronclient._i18n import _ +from neutronclient.osc import utils as nc_osc_utils +from neutronclient.osc.v2.dynamic_routing import constants + + +def _get_attrs(client_manager, parsed_args): + attrs = {} + if parsed_args.name is not None: + attrs['name'] = str(parsed_args.name) + if 'local_as' in parsed_args: + attrs['local_as'] = parsed_args.local_as + if 'ip_version' in parsed_args: + attrs['ip_version'] = parsed_args.ip_version + if parsed_args.advertise_tenant_networks: + attrs['advertise_tenant_networks'] = True + if parsed_args.no_advertise_tenant_networks: + attrs['advertise_tenant_networks'] = False + if parsed_args.advertise_floating_ip_host_routes: + attrs['advertise_floating_ip_host_routes'] = True + if parsed_args.no_advertise_floating_ip_host_routes: + attrs['advertise_floating_ip_host_routes'] = False + + if 'project' in parsed_args and parsed_args.project is not None: + identity_client = client_manager.identity + project_id = nc_osc_utils.find_project( + identity_client, + parsed_args.project, + parsed_args.project_domain, + ).id + attrs['tenant_id'] = project_id + return attrs + + +def add_common_arguments(parser): + parser.add_argument( + '--advertise-floating-ip-host-routes', + action='store_true', + help=_("Enable the advertisement of floating IP host routes " + "by the BGP speaker. (default)")) + parser.add_argument( + '--no-advertise-floating-ip-host-routes', + action='store_true', + help=_("Disable the advertisement of floating IP host routes " + "by the BGP speaker.")) + parser.add_argument( + '--advertise-tenant-networks', + action='store_true', + help=_("Enable the advertisement of tenant network routes " + "by the BGP speaker. (default)")) + parser.add_argument( + '--no-advertise-tenant-networks', + action='store_true', + help=_("Disable the advertisement of tenant network routes " + "by the BGP speaker.")) + + +class AddNetworkToSpeaker(command.Command): + _description = _("Add a network to a BGP speaker") + + def get_parser(self, prog_name): + parser = super(AddNetworkToSpeaker, self).get_parser(prog_name) + parser.add_argument( + 'bgp_speaker', + metavar='<bgp-speaker>', + help=_("BGP speaker (name or ID)")) + parser.add_argument( + 'network', + metavar='<network>', + help=_("Network to add (name or ID)")) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + speaker_id = client.find_resource(constants.BGP_SPEAKER, + parsed_args.bgp_speaker)['id'] + net_id = client.find_resource('network', + parsed_args.network)['id'] + client.add_network_to_bgp_speaker(speaker_id, {'network_id': net_id}) + + +class AddPeerToSpeaker(command.Command): + _description = _("Add a peer to a BGP speaker") + + def get_parser(self, prog_name): + parser = super(AddPeerToSpeaker, self).get_parser(prog_name) + parser.add_argument( + 'bgp_speaker', + metavar='<bgp-speaker>', + help=_("BGP speaker (name or ID)")) + parser.add_argument( + 'bgp_peer', + metavar='<bgp-peer>', + help=_("BGP Peer to add (name or ID)")) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + speaker_id = client.find_resource(constants.BGP_SPEAKER, + parsed_args.bgp_speaker)['id'] + peer_id = client.find_resource(constants.BGP_PEER, + parsed_args.bgp_peer)['id'] + client.add_peer_to_bgp_speaker(speaker_id, {'bgp_peer_id': peer_id}) + + +class CreateBgpSpeaker(command.ShowOne): + _description = _("Create a BGP speaker") + + def get_parser(self, prog_name): + parser = super(CreateBgpSpeaker, self).get_parser(prog_name) + parser.add_argument( + 'name', + metavar='<name>', + help=_("Name of the BGP speaker to create")) + parser.add_argument( + '--local-as', + metavar='<local-as>', + required=True, + help=_("Local AS number. (Integer in [%(min_val)s, %(max_val)s] " + "is allowed.)") % {'min_val': constants.MIN_AS_NUM, + 'max_val': constants.MAX_AS_NUM}) + parser.add_argument( + '--ip-version', + type=int, choices=[4, 6], + default=4, + help=_("IP version for the BGP speaker (default is 4)")) + add_common_arguments(parser) + nc_osc_utils.add_project_owner_option_to_parser(parser) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + attrs = _get_attrs(self.app.client_manager, parsed_args) + body = {} + body[constants.BGP_SPEAKER] = attrs + obj = client.create_bgp_speaker(body)[constants.BGP_SPEAKER] + columns, display_columns = nc_osc_utils.get_columns(obj) + data = utils.get_dict_properties(obj, columns) + return display_columns, data + + +class DeleteBgpSpeaker(command.Command): + _description = _("Delete a BGP speaker") + + def get_parser(self, prog_name): + parser = super(DeleteBgpSpeaker, self).get_parser(prog_name) + parser.add_argument( + 'bgp_speaker', + metavar="<bgp-speaker>", + help=_("BGP speaker to delete (name or ID)") + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + id = client.find_resource(constants.BGP_SPEAKER, + parsed_args.bgp_speaker)['id'] + client.delete_bgp_speaker(id) + + +class ListBgpSpeaker(command.Lister): + _description = _("List BGP speakers") + + def get_parser(self, prog_name): + parser = super(ListBgpSpeaker, self).get_parser(prog_name) + parser.add_argument( + '--agent', + metavar='<agent-id>', + help=_("List BGP speakers hosted by an agent (ID only)")) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + if parsed_args.agent is not None: + data = client.list_bgp_speaker_on_dragent(parsed_args.agent_id) + else: + data = client.list_bgp_speakers() + + headers = ('ID', 'Name', 'Local AS', 'IP Version') + columns = ('id', 'name', 'local_as', 'ip_version') + return (headers, (utils.get_dict_properties(s, columns) + for s in data[constants.BGP_SPEAKERS])) + + +class ListRoutesAdvertisedBySpeaker(command.Lister): + _description = _("List routes advertised") + + def get_parser(self, prog_name): + parser = super(ListRoutesAdvertisedBySpeaker, + self).get_parser(prog_name) + parser.add_argument( + 'bgp_speaker', + metavar='<bgp-speaker>', + help=_("BGP speaker (name or ID)")) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + speaker_id = client.find_resource(constants.BGP_SPEAKER, + parsed_args.bgp_speaker)['id'] + data = client.list_route_advertised_from_bgp_speaker(speaker_id) + headers = ('ID', 'Destination', 'Nexthop') + columns = ('id', 'destination', 'next_hop') + return (headers, (utils.get_dict_properties(s, columns) + for s in data['advertised_routes'])) + + +class RemoveNetworkFromSpeaker(command.Command): + _description = _("Remove a network from a BGP speaker") + + def get_parser(self, prog_name): + parser = super(RemoveNetworkFromSpeaker, self).get_parser(prog_name) + parser.add_argument( + 'bgp_speaker', + metavar='<bgp-speaker>', + help=_("BGP speaker (name or ID)")) + parser.add_argument( + 'network', + metavar='<network>', + help=_("Network to remove (name or ID)")) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + speaker_id = client.find_resource(constants.BGP_SPEAKER, + parsed_args.bgp_speaker)['id'] + net_id = client.find_resource('network', + parsed_args.network)['id'] + client.remove_network_from_bgp_speaker(speaker_id, + {'network_id': net_id}) + + +class RemovePeerFromSpeaker(command.Command): + _description = _("Remove a peer from a BGP speaker") + + def get_parser(self, prog_name): + parser = super(RemovePeerFromSpeaker, self).get_parser(prog_name) + parser.add_argument( + 'bgp_speaker', + metavar='<bgp-speaker>', + help=_("BGP speaker (name or ID)")) + parser.add_argument( + 'bgp_peer', + metavar='<bgp-peer>', + help=_("BGP Peer to remove (name or ID)")) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + speaker_id = client.find_resource(constants.BGP_SPEAKER, + parsed_args.bgp_speaker)['id'] + peer_id = client.find_resource(constants.BGP_PEER, + parsed_args.bgp_peer)['id'] + client.remove_peer_from_bgp_speaker(speaker_id, + {'bgp_peer_id': peer_id}) + + +class SetBgpSpeaker(command.Command): + _description = _("Set BGP speaker properties") + + resource = constants.BGP_SPEAKER + + def get_parser(self, prog_name): + parser = super(SetBgpSpeaker, self).get_parser(prog_name) + parser.add_argument( + 'bgp_speaker', + metavar="<bgp-speaker>", + help=_("BGP speaker to update (name or ID)") + ) + parser.add_argument( + '--name', + help=_("Name of the BGP speaker to update")) + add_common_arguments(parser) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + id = client.find_resource(constants.BGP_SPEAKER, + parsed_args.bgp_speaker)['id'] + attrs = _get_attrs(self.app.client_manager, parsed_args) + body = {} + body[constants.BGP_SPEAKER] = attrs + client.update_bgp_speaker(id, body) + + +class ShowBgpSpeaker(command.ShowOne): + _description = _("Show a BGP speaker") + + def get_parser(self, prog_name): + parser = super(ShowBgpSpeaker, self).get_parser(prog_name) + parser.add_argument( + 'bgp_speaker', + metavar="<bgp-speaker>", + help=_("BGP speaker to display (name or ID)") + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + id = client.find_resource(constants.BGP_SPEAKER, + parsed_args.bgp_speaker)['id'] + obj = client.show_bgp_speaker(id)[constants.BGP_SPEAKER] + columns, display_columns = nc_osc_utils.get_columns(obj) + data = utils.get_dict_properties(obj, columns) + return display_columns, data diff --git a/neutronclient/osc/v2/dynamic_routing/constants.py b/neutronclient/osc/v2/dynamic_routing/constants.py new file mode 100644 index 0000000..0dd16b1 --- /dev/null +++ b/neutronclient/osc/v2/dynamic_routing/constants.py @@ -0,0 +1,18 @@ +# 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. + +BGP_SPEAKERS = 'bgp_speakers' +BGP_SPEAKER = 'bgp_speaker' +BGP_PEERS = 'bgp_peers' +BGP_PEER = 'bgp_peer' +MIN_AS_NUM = 1 +MAX_AS_NUM = 65535 |
