From c7e632d3f9e86a3eb42617d8e5ddc4349c6b2240 Mon Sep 17 00:00:00 2001 From: Somik Behera Date: Sun, 15 May 2011 13:31:23 -0700 Subject: [PATCH] 1) Created a DummDataPlugin in SamplePlugin module. - DummyDataPlugin is a sligh improvment over QuantumEchoPlugin in that the plugin returns hard-coded data structures. 2) Created a CLI that enabled quantum plugin writers to test their plug-in implementation. - Currently I am using DummyDataPlugin to test and run the CLI but if anybody has another better Quantum plug-in, please modify manager.py to use your plug-in and drive the plug-in using the CLI. - Running the CLI against wider variety of plug-ins will help the CLI evolve and improve. Please free to send patches. 3) TODO: list - Finalize the plug-in data model - Finalize the exception and make the plug-in throw exceptions - Write unit tests for plug-in qualification and CLI testing. --- quantum/cli.py | 98 +++++++++++++++++++++++ quantum/manager.py | 6 +- quantum/plugins/SamplePlugin.py | 133 +++++++++++++++++++++++++++++++- quantum/quantumCLI.py | 33 -------- quantum/quantum_plugin_base.py | 4 +- 5 files changed, 235 insertions(+), 39 deletions(-) create mode 100644 quantum/cli.py delete mode 100644 quantum/quantumCLI.py diff --git a/quantum/cli.py b/quantum/cli.py new file mode 100644 index 00000000000..0614f95f291 --- /dev/null +++ b/quantum/cli.py @@ -0,0 +1,98 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011, Nicira Networks, Inc. +# +# 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. +# @author: Somik Behera, Nicira Networks, Inc. + +import sys + +from manager import QuantumManager + + +def usage(): + print "\nUsage:" + print "list_nets " + print "create_net " + print "delete_net " + print "detail_net " + print "rename_net " + print "list_ports " + print "create_port " + print "delete_port " + print "detail_port " + print "plug_iface " + print "unplug_iface " + print "detail_iface " + print "list_iface \n" + +if len(sys.argv) < 2 or len(sys.argv) > 6: + usage() + exit(1) + +quantum = QuantumManager() +manager = quantum.get_manager() + +if sys.argv[1] == "list_nets" and len(sys.argv) == 3: + network_on_tenant = manager.get_all_networks(sys.argv[2]) + print "Virtual Networks on Tenant:%s\n" % sys.argv[2] + for k, v in network_on_tenant.iteritems(): + print"\tNetwork ID:%s \n\tNetwork Name:%s \n" % (k, v) +elif sys.argv[1] == "create_net" and len(sys.argv) == 4: + new_net_id = manager.create_network(sys.argv[2], sys.argv[3]) + print "Created a new Virtual Network with ID:%s\n" % new_net_id +elif sys.argv[1] == "delete_net" and len(sys.argv) == 4: + manager.delete_network(sys.argv[2], sys.argv[3]) + print "Deleted Virtual Network with ID:%s" % sys.argv[3] +elif sys.argv[1] == "detail_net" and len(sys.argv) == 4: + vif_list = manager.get_network_details(sys.argv[2], sys.argv[3]) + print "Remote Interfaces on Virtual Network:%s\n" % sys.argv[3] + for iface in vif_list: + print "\tRemote interface :%s" % iface +elif sys.argv[1] == "rename_net" and len(sys.argv) == 5: + manager.rename_network(sys.argv[2], sys.argv[3], sys.argv[4]) + print "Renamed Virtual Network with ID:%s" % sys.argv[3] +elif sys.argv[1] == "list_ports" and len(sys.argv) == 4: + ports = manager.get_all_ports(sys.argv[2], sys.argv[3]) + print " Virtual Ports on Virtual Network:%s\n" % sys.argv[3] + for port in ports: + print "\tVirtual Port:%s" % port +elif sys.argv[1] == "create_port" and len(sys.argv) == 4: + new_port = manager.create_port(sys.argv[2], sys.argv[3]) + print "Created Virtual Port:%s on Virtual Network:%s" % (new_port, sys.argv[3]) +elif sys.argv[1] == "delete_port" and len(sys.argv) == 5: + manager.delete_port(sys.argv[2], sys.argv[3], sys.argv[4]) + print "Deleted Virtual Port:%s on Virtual Network:%s" % (sys.argv[3], sys.argv[4]) +elif sys.argv[1] == "detail_port" and len(sys.argv) == 5: + port_detail = manager.get_port_details(sys.argv[2], sys.argv[3], sys.argv[4]) + print "Virtual Port:%s on Virtual Network:%s contains remote interface:%s" % (sys.argv[3], sys.argv[4], port_detail) +elif sys.argv[1] == "plug_iface" and len(sys.argv) == 6: + manager.plug_interface(sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5]) + print "Plugged remote interface:%s into Virtual Network:%s" % (sys.argv[5], sys.argv[3]) +elif sys.argv[1] == "unplug_iface" and len(sys.argv) == 5: + manager.unplug_interface(sys.argv[2], sys.argv[3], sys.argv[4]) + print "UnPlugged remote interface from Virtual Port:%s Virtual Network:%s" % (sys.argv[4], sys.argv[3]) +elif sys.argv[1] == "detail_iface" and len(sys.argv) == 5: + remote_iface = manager.get_interface_details(sys.argv[2], sys.argv[3], sys.argv[4]) + print "Remote interface on Virtual Port:%s Virtual Network:%s is %s" % (sys.argv[4], sys.argv[3], remote_iface) +elif sys.argv[1] == "list_iface" and len(sys.argv) == 4: + iface_list = manager.get_all_attached_interfaces(sys.argv[2], sys.argv[3]) + print "Remote Interfaces on Virtual Network:%s\n" % sys.argv[3] + for iface in iface_list: + print "\tRemote interface :%s" % iface +elif sys.argv[1] == "all" and len(sys.argv) == 2: + print "Not Implemented" +else: + print "invalid arguments: %s" % str(sys.argv) + usage() + diff --git a/quantum/manager.py b/quantum/manager.py index a8a6da6ed9d..cdf75052797 100644 --- a/quantum/manager.py +++ b/quantum/manager.py @@ -37,12 +37,12 @@ class QuantumManager(object): # configuration file as opposed to hard-coding the location # #plugin_location = get_plugin_location(configuration_file) - plugin_location = "plugins.SamplePlugin.QuantumEchoPlugin" + plugin_location = "plugins.SamplePlugin.DummyDataPlugin" plugin_klass = utils.import_class(plugin_location) if not issubclass(plugin_klass, QuantumPluginBase): - raise Exception("Imported plugin didn't pass compatibility test") + raise Exception("Configured Quantum plug-in didn't pass compatibility test") else: - print("Imported plugin passed compatibility test\n") + print("Successfully imported Quantum plug-in. All compatibility tests passed\n") self.plugin = plugin_klass() def get_manager(self): diff --git a/quantum/plugins/SamplePlugin.py b/quantum/plugins/SamplePlugin.py index 8a0deae1aa6..5088b71fa39 100644 --- a/quantum/plugins/SamplePlugin.py +++ b/quantum/plugins/SamplePlugin.py @@ -128,4 +128,135 @@ class QuantumEchoPlugin(object): Retrieves all remote interfaces that are attached to a particular Virtual Network. """ - print("get_all_attached_interfaces() called\n") \ No newline at end of file + print("get_all_attached_interfaces() called\n") + +class DummyDataPlugin(object): + + """ + DummyDataPlugin is a demo plugin that provides + hard-coded data structures to aid in quantum + client/cli development + """ + + def get_all_networks(self, tenant_id): + """ + Returns a dictionary containing all + for + the specified tenant. + """ + nets = {"001": "lNet1", "002": "lNet2" , "003": "lNet3"} + print("get_all_networks() called\n") + return nets + + + def create_network(self, tenant_id, net_name): + """ + Creates a new Virtual Network, and assigns it + a symbolic name. + """ + print("create_network() called\n") + # return network_id of the created network + return 101 + + + def delete_network(self, tenant_id, net_id): + """ + Deletes the network with the specified network identifier + belonging to the specified tenant. + """ + print("delete_network() called\n") + + + def get_network_details(self, tenant_id, net_id): + """ + retrieved a list of all the remote vifs that + are attached to the network + """ + print("get_network_details() called\n") + vifs_on_net = ["/tenant1/networks/net_id/portid/vif2.0", "/tenant1/networks/10/121/vif1.1"] + return vifs_on_net + + + def rename_network(self, tenant_id, net_id, new_name): + """ + Updates the symbolic name belonging to a particular + Virtual Network. + """ + print("rename_network() called\n") + + + def get_all_ports(self, tenant_id, net_id): + """ + Retrieves all port identifiers belonging to the + specified Virtual Network. + """ + print("get_all_ports() called\n") + port_ids_on_net = ["2", "3", "4"] + return port_ids_on_net + + + def create_port(self, tenant_id, net_id): + """ + Creates a port on the specified Virtual Network. + """ + print("create_port() called\n") + #return the port id + return 201 + + + def delete_port(self, tenant_id, net_id, port_id): + """ + Deletes a port on a specified Virtual Network, + if the port contains a remote interface attachment, + the remote interface is first un-plugged and then the port + is deleted. + """ + print("delete_port() called\n") + + + def get_port_details(self, tenant_id, net_id, port_id): + """ + This method allows the user to retrieve a remote interface + that is attached to this particular port. + """ + print("get_port_details() called\n") + #returns the remote interface UUID + return "/tenant1/networks/net_id/portid/vif2.1" + + + def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id): + """ + Attaches a remote interface to the specified port on the + specified Virtual Network. + """ + print("plug_interface() called\n") + + + def unplug_interface(self, tenant_id, net_id, port_id): + """ + Detaches a remote interface from the specified port on the + specified Virtual Network. + """ + print("unplug_interface() called\n") + + + def get_interface_details(self, tenant_id, net_id, port_id): + """ + Retrieves the remote interface that is attached at this + particular port. + """ + print("get_interface_details() called\n") + #returns the remote interface UUID + return "/tenant1/networks/net_id/portid/vif2.0" + + + def get_all_attached_interfaces(self, tenant_id, net_id): + """ + Retrieves all remote interfaces that are attached to + a particular Virtual Network. + """ + print("get_all_attached_interfaces() called\n") + # returns a list of all attached remote interfaces + vifs_on_net = ["/tenant1/networks/net_id/portid/vif2.0", "/tenant1/networks/10/121/vif1.1"] + return vifs_on_net + \ No newline at end of file diff --git a/quantum/quantumCLI.py b/quantum/quantumCLI.py deleted file mode 100644 index 2da173d0bea..00000000000 --- a/quantum/quantumCLI.py +++ /dev/null @@ -1,33 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011, Nicira Networks, Inc. -# -# 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. -# @author: Somik Behera, Nicira Networks, Inc. - -from manager import QuantumManager - -class CLI(): - - def index(self): - pass - -def main(): - quantum = QuantumManager() - manager = quantum.get_manager() - manager.get_all_networks("tesst") - #print("is a plugin") - -# Standard boilerplate to call the main() function. -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/quantum/quantum_plugin_base.py b/quantum/quantum_plugin_base.py index 0ab80897928..b84940c706c 100644 --- a/quantum/quantum_plugin_base.py +++ b/quantum/quantum_plugin_base.py @@ -57,8 +57,8 @@ class QuantumPluginBase(object): @abstractmethod def get_network_details(self, tenant_id, net_id): """ - Deletes the Virtual Network belonging to a the - spec + retrieved a list of all the remote vifs that + are attached to the network """ pass