summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSalvatore Orlando <sorlando@nicira.com>2012-11-29 06:51:25 -0800
committerSalvatore Orlando <salv.orlando@gmail.com>2013-02-20 13:40:30 +0100
commitd77f86218e4c0c2f5371accce64605e7cfff41c5 (patch)
tree212edbe8f98459f2f30ad1bac3c6184301484535
parentee4cb431859046c7be93e09168961d2af3328ef7 (diff)
downloadpython-neutronclient-d77f86218e4c0c2f5371accce64605e7cfff41c5.tar.gz
CLI support for network gateway feature2.2.0a1
Blueprint nvp-nwgw-extension-client Adds commands for gateway management, and for connecting networks to gateways. These commands use the nicira-specific extension 'nvp-network-gateway' Change-Id: Iefcba201bc9fd8dce35762514af0f56b29430ccd
-rw-r--r--quantumclient/quantum/v2_0/nvpnetworkgateway.py160
-rw-r--r--quantumclient/shell.py15
-rw-r--r--quantumclient/tests/unit/test_cli20.py6
-rw-r--r--quantumclient/tests/unit/test_cli20_nvpnetworkgateway.py108
-rw-r--r--quantumclient/v2_0/client.py53
5 files changed, 340 insertions, 2 deletions
diff --git a/quantumclient/quantum/v2_0/nvpnetworkgateway.py b/quantumclient/quantum/v2_0/nvpnetworkgateway.py
new file mode 100644
index 0000000..3957304
--- /dev/null
+++ b/quantumclient/quantum/v2_0/nvpnetworkgateway.py
@@ -0,0 +1,160 @@
+# Copyright 2013 OpenStack LLC.
+# 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.
+#
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+import argparse
+import logging
+
+from quantumclient.common import utils
+from quantumclient.quantum import v2_0 as quantumv20
+
+RESOURCE = 'network_gateway'
+
+
+class ListNetworkGateway(quantumv20.ListCommand):
+ """List network gateways for a given tenant."""
+
+ resource = RESOURCE
+ _formatters = {}
+ log = logging.getLogger(__name__ + '.ListNetworkGateway')
+ list_columns = ['id', 'name']
+
+
+class ShowNetworkGateway(quantumv20.ShowCommand):
+ """Show information of a given network gateway."""
+
+ resource = RESOURCE
+ log = logging.getLogger(__name__ + '.ShowNetworkGateway')
+
+
+class CreateNetworkGateway(quantumv20.CreateCommand):
+ """Create a network gateway."""
+
+ resource = RESOURCE
+ log = logging.getLogger(__name__ + '.CreateNetworkGateway')
+
+ def add_known_arguments(self, parser):
+ parser.add_argument(
+ 'name', metavar='NAME',
+ help='Name of network gateway to create')
+ parser.add_argument(
+ '--device',
+ action='append',
+ help='device info for this gateway '
+ 'device_id=<device identifier>,'
+ 'interface_name=<name_or_identifier> '
+ 'It can be repeated for multiple devices for HA gateways')
+
+ def args2body(self, parsed_args):
+ body = {self.resource: {
+ 'name': parsed_args.name}}
+ devices = []
+ if parsed_args.device:
+ for device in parsed_args.device:
+ devices.append(utils.str2dict(device))
+ if devices:
+ body[self.resource].update({'devices': devices})
+ if parsed_args.tenant_id:
+ body[self.resource].update({'tenant_id': parsed_args.tenant_id})
+ return body
+
+
+class DeleteNetworkGateway(quantumv20.DeleteCommand):
+ """Delete a given network gateway."""
+
+ resource = RESOURCE
+ log = logging.getLogger(__name__ + '.DeleteNetworkGateway')
+
+
+class UpdateNetworkGateway(quantumv20.UpdateCommand):
+ """Update the name for a network gateway."""
+
+ resource = RESOURCE
+ log = logging.getLogger(__name__ + '.UpdateNetworkGateway')
+
+
+class NetworkGatewayInterfaceCommand(quantumv20.QuantumCommand):
+ """Base class for connecting/disconnecting networks to/from a gateway."""
+
+ resource = RESOURCE
+
+ def get_parser(self, prog_name):
+ parser = super(NetworkGatewayInterfaceCommand,
+ self).get_parser(prog_name)
+ parser.add_argument(
+ 'net_gateway_id', metavar='NET-GATEWAY-ID',
+ help='ID of the network gateway')
+ parser.add_argument(
+ 'network_id', metavar='NETWORK-ID',
+ help='ID of the internal network to connect on the gateway')
+ parser.add_argument(
+ '--segmentation-type',
+ help=('L2 segmentation strategy on the external side of '
+ 'the gateway (e.g.: VLAN, FLAT)'))
+ parser.add_argument(
+ '--segmentation-id',
+ help=('Identifier for the L2 segment on the external side '
+ 'of the gateway'))
+ return parser
+
+ def retrieve_ids(self, client, args):
+ gateway_id = quantumv20.find_resourceid_by_name_or_id(
+ client, self.resource, args.net_gateway_id)
+ network_id = quantumv20.find_resourceid_by_name_or_id(
+ client, 'network', args.network_id)
+ return (gateway_id, network_id)
+
+
+class ConnectNetworkGateway(NetworkGatewayInterfaceCommand):
+ """Add an internal network interface to a router."""
+
+ log = logging.getLogger(__name__ + '.ConnectNetworkGateway')
+
+ def run(self, parsed_args):
+ self.log.debug('run(%s)' % parsed_args)
+ quantum_client = self.get_client()
+ quantum_client.format = parsed_args.request_format
+ (gateway_id, network_id) = self.retrieve_ids(quantum_client,
+ parsed_args)
+ quantum_client.connect_network_gateway(
+ gateway_id, {'network_id': network_id,
+ 'segmentation_type': parsed_args.segmentation_type,
+ 'segmentation_id': parsed_args.segmentation_id})
+ # TODO(Salvatore-Orlando): Do output formatting as
+ # any other command
+ print >>self.app.stdout, (
+ _('Connected network to gateway %s') % gateway_id)
+
+
+class DisconnectNetworkGateway(NetworkGatewayInterfaceCommand):
+ """Remove a network from a network gateway."""
+
+ log = logging.getLogger(__name__ + '.DisconnectNetworkGateway')
+
+ def run(self, parsed_args):
+ self.log.debug('run(%s)' % parsed_args)
+ quantum_client = self.get_client()
+ quantum_client.format = parsed_args.request_format
+ (gateway_id, network_id) = self.retrieve_ids(quantum_client,
+ parsed_args)
+ quantum_client.disconnect_network_gateway(
+ gateway_id, {'network_id': network_id,
+ 'segmentation_type': parsed_args.segmentation_type,
+ 'segmentation_id': parsed_args.segmentation_id})
+ # TODO(Salvatore-Orlando): Do output formatting as
+ # any other command
+ print >>self.app.stdout, (
+ _('Disconnected network from gateway %s') % gateway_id)
diff --git a/quantumclient/shell.py b/quantumclient/shell.py
index 4b22e98..feb6941 100644
--- a/quantumclient/shell.py
+++ b/quantumclient/shell.py
@@ -220,6 +220,21 @@ COMMAND_V2 = {
'quantumclient.quantum.v2_0.agent.DeleteAgent'),
'agent-update': utils.import_class(
'quantumclient.quantum.v2_0.agent.UpdateAgent'),
+ 'net-gateway-create': utils.import_class(
+ 'quantumclient.quantum.v2_0.nvpnetworkgateway.CreateNetworkGateway'),
+ 'net-gateway-update': utils.import_class(
+ 'quantumclient.quantum.v2_0.nvpnetworkgateway.UpdateNetworkGateway'),
+ 'net-gateway-delete': utils.import_class(
+ 'quantumclient.quantum.v2_0.nvpnetworkgateway.DeleteNetworkGateway'),
+ 'net-gateway-show': utils.import_class(
+ 'quantumclient.quantum.v2_0.nvpnetworkgateway.ShowNetworkGateway'),
+ 'net-gateway-list': utils.import_class(
+ 'quantumclient.quantum.v2_0.nvpnetworkgateway.ListNetworkGateway'),
+ 'net-gateway-connect': utils.import_class(
+ 'quantumclient.quantum.v2_0.nvpnetworkgateway.ConnectNetworkGateway'),
+ 'net-gateway-disconnect': utils.import_class(
+ 'quantumclient.quantum.v2_0.nvpnetworkgateway.'
+ 'DisconnectNetworkGateway')
}
COMMANDS = {'2.0': COMMAND_V2}
diff --git a/quantumclient/tests/unit/test_cli20.py b/quantumclient/tests/unit/test_cli20.py
index d2abaf9..4e62eda 100644
--- a/quantumclient/tests/unit/test_cli20.py
+++ b/quantumclient/tests/unit/test_cli20.py
@@ -159,12 +159,13 @@ class CLITestV20Base(testtools.TestCase):
name, myid, args,
position_names, position_values, tenant_id=None,
tags=None, admin_state_up=True, shared=False,
- extra_body=None):
+ extra_body=None, **kwargs):
self.mox.StubOutWithMock(cmd, "get_client")
self.mox.StubOutWithMock(self.client.httpclient, "request")
cmd.get_client().MultipleTimes().AndReturn(self.client)
non_admin_status_resources = ['subnet', 'floatingip', 'security_group',
- 'security_group_rule', 'qos_queue']
+ 'security_group_rule', 'qos_queue',
+ 'network_gateway']
if (resource in non_admin_status_resources):
body = {resource: {}, }
else:
@@ -177,6 +178,7 @@ class CLITestV20Base(testtools.TestCase):
body[resource].update({'shared': shared})
if extra_body:
body[resource].update(extra_body)
+ body[resource].update(kwargs)
for i in xrange(len(position_names)):
body[resource].update({position_names[i]: position_values[i]})
diff --git a/quantumclient/tests/unit/test_cli20_nvpnetworkgateway.py b/quantumclient/tests/unit/test_cli20_nvpnetworkgateway.py
new file mode 100644
index 0000000..7f17571
--- /dev/null
+++ b/quantumclient/tests/unit/test_cli20_nvpnetworkgateway.py
@@ -0,0 +1,108 @@
+# Copyright 2012 Nicira, Inc
+# 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.
+#
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+import sys
+
+from quantumclient.common import exceptions
+from quantumclient.quantum.v2_0 import nvpnetworkgateway
+from quantumclient.tests.unit.test_cli20 import CLITestV20Base
+from quantumclient.tests.unit.test_cli20 import MyApp
+
+
+class CLITestV20NetworkGateway(CLITestV20Base):
+
+ resource = "network_gateway"
+
+ def test_create_gateway(self):
+ cmd = nvpnetworkgateway.CreateNetworkGateway(MyApp(sys.stdout), None)
+ name = 'gw-test'
+ myid = 'myid'
+ args = [name, ]
+ position_names = ['name', ]
+ position_values = [name, ]
+ _str = self._test_create_resource(self.resource, cmd, name, myid, args,
+ position_names, position_values)
+
+ def test_create_gateway_with_tenant(self):
+ cmd = nvpnetworkgateway.CreateNetworkGateway(MyApp(sys.stdout), None)
+ name = 'gw-test'
+ myid = 'myid'
+ args = ['--tenant_id', 'tenantid', name]
+ position_names = ['name', ]
+ position_values = [name, ]
+ _str = self._test_create_resource(self.resource, cmd, name, myid, args,
+ position_names, position_values,
+ tenant_id='tenantid')
+
+ def test_create_gateway_with_device(self):
+ cmd = nvpnetworkgateway.CreateNetworkGateway(MyApp(sys.stdout), None)
+ name = 'gw-test'
+ myid = 'myid'
+ args = ['--device', 'device_id=test', name, ]
+ position_names = ['name', ]
+ position_values = [name, ]
+ _str = self._test_create_resource(self.resource, cmd, name, myid, args,
+ position_names, position_values,
+ devices=[{'device_id': 'test'}])
+
+ def test_list_gateways(self):
+ resources = '%ss' % self.resource
+ cmd = nvpnetworkgateway.ListNetworkGateway(MyApp(sys.stdout), None)
+ self._test_list_resources(resources, cmd, True)
+
+ def test_update_gateway(self):
+ cmd = nvpnetworkgateway.UpdateNetworkGateway(MyApp(sys.stdout), None)
+ self._test_update_resource(self.resource, cmd, 'myid',
+ ['myid', '--name', 'cavani'],
+ {'name': 'cavani'})
+
+ def test_delete_gateway(self):
+ cmd = nvpnetworkgateway.DeleteNetworkGateway(MyApp(sys.stdout), None)
+ myid = 'myid'
+ args = [myid]
+ self._test_delete_resource(self.resource, cmd, myid, args)
+
+ def test_show_gateway(self):
+ cmd = nvpnetworkgateway.ShowNetworkGateway(MyApp(sys.stdout), None)
+ args = ['--fields', 'id', '--fields', 'name', self.test_id]
+ self._test_show_resource(self.resource, cmd, self.test_id, args,
+ ['id', 'name'])
+
+ def test_connect_network_to_gateway(self):
+ cmd = nvpnetworkgateway.ConnectNetworkGateway(MyApp(sys.stdout), None)
+ args = ['gw_id', 'net_id',
+ '--segmentation-type', 'edi',
+ '--segmentation-id', '7']
+ self._test_update_resource_action(self.resource, cmd, 'gw_id',
+ 'connect_network',
+ args,
+ {'network_id': 'net_id',
+ 'segmentation_type': 'edi',
+ 'segmentation_id': '7'})
+
+ def test_disconnect_network_from_gateway(self):
+ cmd = nvpnetworkgateway.DisconnectNetworkGateway(MyApp(sys.stdout),
+ None)
+ args = ['gw_id', 'net_id',
+ '--segmentation-type', 'edi',
+ '--segmentation-id', '7']
+ self._test_update_resource_action(self.resource, cmd, 'gw_id',
+ 'disconnect_network',
+ args,
+ {'network_id': 'net_id',
+ 'segmentation_type': 'edi',
+ 'segmentation_id': '7'})
diff --git a/quantumclient/v2_0/client.py b/quantumclient/v2_0/client.py
index 883b208..3ee26e9 100644
--- a/quantumclient/v2_0/client.py
+++ b/quantumclient/v2_0/client.py
@@ -174,6 +174,8 @@ class Client(object):
qos_queue_path = "/qos-queues/%s"
agents_path = "/agents"
agent_path = "/agents/%s"
+ network_gateways_path = "/network-gateways"
+ network_gateway_path = "/network-gateways/%s"
# API has no way to report plurals, so we have to hard code them
EXTED_PLURALS = {'routers': 'router',
@@ -735,6 +737,57 @@ class Client(object):
"""
return self.delete(self.agent_path % (agent))
+ @APIParamsCall
+ def list_network_gateways(self, **_params):
+ """
+ Retrieve network gateways
+ """
+ return self.get(self.network_gateways_path, params=_params)
+
+ @APIParamsCall
+ def show_network_gateway(self, gateway_id, **_params):
+ """
+ Fetch a network gateway
+ """
+ return self.get(self.network_gateway_path % gateway_id, params=_params)
+
+ @APIParamsCall
+ def create_network_gateway(self, body=None):
+ """
+ Create a new network gateway
+ """
+ return self.post(self.network_gateways_path, body=body)
+
+ @APIParamsCall
+ def update_network_gateway(self, gateway_id, body=None):
+ """
+ Update a network gateway
+ """
+ return self.put(self.network_gateway_path % gateway_id, body=body)
+
+ @APIParamsCall
+ def delete_network_gateway(self, gateway_id):
+ """
+ Delete the specified network gateway
+ """
+ return self.delete(self.network_gateway_path % gateway_id)
+
+ @APIParamsCall
+ def connect_network_gateway(self, gateway_id, body=None):
+ """
+ Connect a network gateway to the specified network
+ """
+ base_uri = self.network_gateway_path % gateway_id
+ return self.put("%s/connect_network" % base_uri, body=body)
+
+ @APIParamsCall
+ def disconnect_network_gateway(self, gateway_id, body=None):
+ """
+ Disconnect a network from the specified gateway
+ """
+ base_uri = self.network_gateway_path % gateway_id
+ return self.put("%s/disconnect_network" % base_uri, body=body)
+
def __init__(self, **kwargs):
""" Initialize a new client for the Quantum v2.0 API. """
super(Client, self).__init__()