diff --git a/quantum/manager.py b/quantum/manager.py index b317023350..1d2c440b16 100644 --- a/quantum/manager.py +++ b/quantum/manager.py @@ -14,8 +14,50 @@ # 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. + """ -Manager is responsible for parsing a config file and instantiating the correct -set of plugins that concretely implement quantum_plugin_base class -""" \ No newline at end of file +Quantum's Manager class is responsible for parsing a config file and instantiating the correct +plugin that concretely implement quantum_plugin_base class + +The caller should make sure that QuantumManager is a singleton. +""" + +import utils +from quantum_plugin_base import QuantumPluginBase + +CONFIG_FILE = "quantum_plugin.conf" + +class QuantumManager(object): + + def __init__(self,config=CONFIG_FILE): + self.configuration_file = CONFIG_FILE + #TODO(somik): plugin location should be grabbed from a + # configuration file as opposed to hard-coding the location + # + #plugin_location = get_plugin_location(configuration_file) + plugin_location = "plugins.SamplePlugin.QuantumEchoPlugin" + plugin_klass = utils.import_class(plugin_location) + if not issubclass(plugin_klass, QuantumPluginBase): + raise Exception("Imported plugin didn't pass compatibility test") + else: + print("Imported plugin passed compatibility test\n") + self.plugin = plugin_klass() + + def get_manager(self): + return self.plugin + +# TODO(somik): rmove the main class +# Added for temporary testing purposes +def main(): + manager = QuantumManager() + myManager = manager.get_manager() + myManager.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/plugins/SamplePlugin.py b/quantum/plugins/SamplePlugin.py new file mode 100644 index 0000000000..8a0deae1aa --- /dev/null +++ b/quantum/plugins/SamplePlugin.py @@ -0,0 +1,131 @@ +# 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. + +class QuantumEchoPlugin(object): + + """ + QuantumEchoPlugin is a demo plugin that doesn't + do anything but demonstrated the concept of a + concrete Quantum Plugin. Any call to this plugin + will result in just a "print" to std. out with + the name of the method that was called. + """ + + def get_all_networks(self, tenant_id): + """ + Returns a dictionary containing all + for + the specified tenant. + """ + print("get_all_networks() called\n") + + + def create_network(self, tenant_id, net_name): + """ + Creates a new Virtual Network, and assigns it + a symbolic name. + """ + print("create_network() called\n") + + + 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): + """ + Deletes the Virtual Network belonging to a the + spec + """ + print("get_network_details() called\n") + + + 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") + + + def create_port(self, tenant_id, net_id): + """ + Creates a port on the specified Virtual Network. + """ + print("create_port() called\n") + + + 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") + + + 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") + + + 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") \ No newline at end of file diff --git a/quantum/plugins/__init__.py b/quantum/plugins/__init__.py new file mode 100644 index 0000000000..df928bbf1c --- /dev/null +++ b/quantum/plugins/__init__.py @@ -0,0 +1,16 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright 2011 Nicira Networks, 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. +# @author: Somik Behera, Nicira Networks, Inc. \ No newline at end of file diff --git a/quantum/quantumCLI.py b/quantum/quantumCLI.py new file mode 100644 index 0000000000..2da173d0be --- /dev/null +++ b/quantum/quantumCLI.py @@ -0,0 +1,33 @@ +# 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 59601e9dd9..7fedd528cf 100644 --- a/quantum/quantum_plugin_base.py +++ b/quantum/quantum_plugin_base.py @@ -132,4 +132,22 @@ class QuantumPluginBase(object): Retrieves all remote interfaces that are attached to a particular Virtual Network. """ - pass \ No newline at end of file + pass + + @classmethod + def __subclasshook__(cls, klass): + """ + The __subclasshook__ method is a class method + that will be called everytime a class is tested + using issubclass(klass, Plugin). + In that case, it will check that every method + marked with the abstractmethod decorator is + provided by the plugin class. + """ + if cls is QuantumPluginBase: + for method in cls.__abstractmethods__: + if any(method in base.__dict__ for base in klass.__mro__): + continue + return NotImplemented + return True + return NotImplemented \ No newline at end of file diff --git a/quantum/utils.py b/quantum/utils.py new file mode 100644 index 0000000000..284b184433 --- /dev/null +++ b/quantum/utils.py @@ -0,0 +1,57 @@ +# 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. +# +# Borrowed from nova code base, more utilities will be added/borrowed as and +# when needed. +# @author: Somik Behera, Nicira Networks, Inc. + +"""Utilities and helper functions.""" + +import base64 +import datetime +import functools +import inspect +import json +import os +import random +import re +import socket +import string +import struct +import sys +import time +import types + + +def import_class(import_str): + """Returns a class from a string including module and class.""" + mod_str, _sep, class_str = import_str.rpartition('.') + try: + __import__(mod_str) + return getattr(sys.modules[mod_str], class_str) + except (ImportError, ValueError, AttributeError), exc: + print(('Inner Exception: %s'), exc) + raise exception.ClassNotFound(class_name=class_str) + + +def import_object(import_str): + """Returns an object including a module or module and class.""" + try: + __import__(import_str) + return sys.modules[import_str] + except ImportError: + cls = import_class(import_str) + return cls()