implementation and enables them to switch out a plug-in by simple editing a
config file - plugins.ini
+# -- Layout
+
+ The Quantum project includes 3 core packages:
+
+ quantum-common (General utils for Quantum and its plugins)
+ quantum-server (The actual Quantum service itself)
+ quantum-client (The Quantum CLI and API Python library)
+
+ As well as some plugins.
+
# -- Dependencies
The following python packages are required to run quantum. These can be
3) Install packages with pip:
$ pip install <package name>
+# -- Running from the source code
+
+ bin/quantum-server #Server
+ bin/quantum #CLI
+ sh run_tests.sh #Tests
+
+# -- Installing from the source code
+
+ You have 3 options:
+ a) sudo python setup.py install
+ # Installs to /usr/lib, /usr/bin, /etc, etc
+
+ b) python setup.py install --user
+ # Install into $HOME/.local/...
+
+ c) python setup.py install --venv
+ # Creates and installs into a virtual-env at ~/.quantum-venv
+
# -- Configuring Quantum plug-in
1) Identify your desired plug-in. Choose a plugin from one of he options in
# -- Launching the Quantum Service
-1) Start quantum using the following command [on the quantum service host]:
-~/src/quantum$ PYTHONPATH=.:$PYTHONPATH python bin/quantum etc/quantum.conf
-
-# -- Making requests against the Quantum Service
+ # If you're running from the source
+ bin/quantum-server
-Please refer to sample Web Service client code in:
+ # If you installed Quantum
+ quantum-server
-../quantum/test_scripts/miniclient.py
+# -- Making requests against the Quantum Service
-# -- CLI tools to program the Quantum-managed Cloud networking fabric
+ Quantum comes with a programmatic CLI that is driven by the Quantum Web
+ Service. You can use the CLI by issuing the following command:
-Quantum comes with a programmatic CLI that is driven by the Quantum Web
-Service. You can use the CLI by issuing the following command:
+ # If you're running from the source
+ bin/quantum
-~/src/quantum$ PYTHONPATH=.:$PYTHONPATH python quantum/cli.py
+ # If you installed Quantum
+ quantum
-This will show help all of the available commands.
+ This will show help all of the available commands.
-An example session looks like this:
+ An example session looks like this:
-$ export TENANT=t1
-$ PYTHONPATH=. python quantum/cli.py -v create_net $TENANT network1
-Created a new Virtual Network with ID:e754e7c0-a8eb-40e5-861a-b182d30c3441
+ $ export TENANT=t1
+ $ quantum -v create_net $TENANT network1
+ Created a new Virtual Network with ID:e754e7c0-a8eb-40e5-861a-b182d30c3441
# -- Authentication and Authorization
The final step concerns configuring access to Keystone. The following attributes
must be specified in the [filter:authN] section of quantum.conf:
-auth_host IP address or host name of the server where Keystone is running
-auth_port Port where the Keystone Admin API is listening
-auth_protocol Protocol used for communicating with Keystone (http/https)
-auth_version Keystone API version (default: 2.0)
-auth_admin_token Keystone token for administrative access
-auth_admin_user Keystone user with administrative rights
+auth_host IP address or host name of the server where Keystone is running
+auth_port Port where the Keystone Admin API is listening
+auth_protocol Protocol used for communicating with Keystone (http/https)
+auth_version Keystone API version (default: 2.0)
+auth_admin_token Keystone token for administrative access
+auth_admin_user Keystone user with administrative rights
auth_admin_password Password for the user specified with auth_admin_user
NOTE: aut_admin_token and auth_admin_user/password are exclusive.
The QuantumEchoPlugin lists foxinsox in its supported_extension_aliases
and implements the method from FoxInSocksPluginInterface.
+
+# -- Building packages
+
+ rpms:
+ python setup.py build rpm
+
+ debs:
+ python setup.py build deb
# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2011 Nicira Networks, Inc.
+
+# Copyright 2011 Cisco Systems
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# 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.
+# @author: Tyler Smith, Cisco Systems
+import os
+import sys
+
+sys.path.append(os.path.join(os.getcwd(), 'tools'))
# If ../quantum/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
-import gettext
-import optparse
-import os
-import sys
+import __init__
+import source_environment
+from quantum.cli import main as cli
-
-possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
- os.pardir,
- os.pardir))
-if os.path.exists(os.path.join(possible_topdir, 'quantum', '__init__.py')):
- sys.path.insert(0, possible_topdir)
-
-gettext.install('quantum', unicode=1)
-
-from quantum import service
-from quantum.common import config
-
-
-def create_options(parser):
- """
- Sets up the CLI and config-file options that may be
- parsed and program commands.
- :param parser: The option parser
- """
- config.add_common_options(parser)
- config.add_log_options(parser)
-
-
-if __name__ == '__main__':
- oparser = optparse.OptionParser(version='%%prog VERSION')
- create_options(oparser)
- (options, args) = config.parse_options(oparser)
-
- try:
- service = service.serve_wsgi(service.QuantumApiService,
- options=options,
- args=args)
- service.wait()
- except RuntimeError, e:
- sys.exit("ERROR: %s" % e)
+cli()
--- /dev/null
+#!/usr/bin/env python
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Nicira Neworks, 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.
+
+# If ../quantum/__init__.py exists, add ../ to Python search path, so that
+# it will override what happens to be installed in /usr/(local/)lib/python...
+
+import __init__
+import source_environment
+from quantum.server import main as server
+
+server()
--- /dev/null
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
return args
-if __name__ == "__main__":
+def main():
usagestr = "Usage: %prog [OPTIONS] <command> [args]"
parser = OptionParser(usage=usagestr)
parser.add_option("-H", "--host", dest="host",
import urllib
from quantum.common import exceptions
-from quantum.common.wsgi import Serializer
+from quantum.common.serializer import Serializer
LOG = logging.getLogger('quantum.client')
EXCEPTIONS = {
# See http://code.google.com/p/python-nose/issues/detail?id=373
# The code below enables nosetests to work with i18n _() blocks
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
+
import __builtin__
import unittest
setattr(__builtin__, '_', lambda x: x)
import unittest
import re
-from quantum.common.wsgi import Serializer
+from quantum.common.serializer import Serializer
from quantum.client import Client
LOG = logging.getLogger('quantum.tests.test_api')
--- /dev/null
+try:
+ from setuptools import setup, find_packages
+except ImportError:
+ from ez_setup import use_setuptools
+ use_setuptools()
+ from setuptools import setup, find_packages
+
+Name = 'quantum-client'
+Url = "https://launchpad.net/quantum"
+Version = '2012.1-dev'
+License = 'Apache License 2.0'
+# Change as required
+Author = 'Netstack'
+AuthorEmail = 'netstack@lists.launchpad.net'
+Maintainer = ''
+Summary = 'Client functionalities for Quantum'
+ShortDescription = Summary
+Description = Summary
+
+requires = [
+ 'quantum-common'
+]
+
+EagerResources = [
+ 'quantum',
+]
+
+ProjectScripts = [
+]
+
+PackageData = {
+}
+
+
+setup(
+ name=Name,
+ version=Version,
+ url=Url,
+ author=Author,
+ author_email=AuthorEmail,
+ description=ShortDescription,
+ long_description=Description,
+ license=License,
+ scripts=ProjectScripts,
+ install_requires=requires,
+ include_package_data=True,
+ packages=find_packages('lib'),
+ package_data=PackageData,
+ package_dir={'': 'lib'},
+ eager_resources=EagerResources,
+ namespace_packages=['quantum'],
+ entry_points={
+ 'console_scripts': [
+ 'quantum = quantum.cli:main'
+ ]
+ },
+)
--- /dev/null
+# -- Welcome!
+
+ You have come across a cloud computing network fabric controller. It has
+ identified itself as "Quantum." It aims to tame your (cloud) networking!
+
+# -- Basics:
+
+1) Quantum REST API: Quantum supports a REST-ful programmatic interface to
+ manage your cloud networking fabric.
+
+2) Quantum Plugins: Quantum sports a plug-able architecture that allows
+ Quantum's REST API to be backed by various entities that can create a
+ cloud-class virtual networking fabric. The advantages of this plug-able
+ architecture is two-folds:
+
+ a) Allows for ANY open-source project or commercial vendor to write a
+ Quantum plug-in.
+
+ b) Allows Quantum users to not be tied down to a single Quantum
+ implementation and enables them to switch out a plug-in by simple editing a
+ config file - plugins.ini
+
+# -- Layout
+
+ The Quantum project includes 3 core packages:
+
+ quantum-common (General utils for Quantum and its plugins)
+ quantum-server (The actual Quantum service itself)
+ quantum-client (The Quantum CLI and API Python library)
+
+ As well as some plugins.
+
+# -- Dependencies
+
+ The following python packages are required to run quantum. These can be
+ installed using pip:
+
+ eventlet>=0.9.12
+ nose
+ Paste
+ PasteDeploy
+ pep8==0.5.0
+ python-gflags
+ routes
+ simplejson
+ webob
+ webtest
+
+1) Install easy_install (there is probably a distribution specific package for
+this)
+
+2) Install pip:
+ $ easy_install pip==dev
+3) Install packages with pip:
+ $ pip install <package name>
+
+# -- Running from the source code
+
+ bin/quantum-server #Server
+ bin/quantum #CLI
+ python run_tests.py #Tests
+
+# -- Installing from the source code
+
+ You have 3 options:
+ a) sudo python setup.py install
+ # Installs to /usr/lib, /usr/bin, /etc, etc
+
+ b) python setup.py install --user
+ # Install into $HOME/.local/...
+
+ c) python setup.py install --venv
+ # Creates and installs into a virtual-env at ~/.quantum-venv
+
+# -- Configuring Quantum plug-in
+
+1) Identify your desired plug-in. Choose a plugin from one of he options in
+ the quantum/plugins directory.
+
+2) Update plug-in configuration by editing the quantum/plugins.ini file and
+ modify "provider" property to point to the location of the Quantum plug-in.
+ It should specify the class path to the plugin and the class name (i.e. for
+ a plugin class MyPlugin in quantum/plugins/myplugin/myplugin.py the
+ provider would be: quantum.plugins.myplugin.myplugin.MyPlugin)
+
+3) Read the plugin specific README, this is usually found in the same
+ directory as your Quantum plug-in, and follow configuration instructions.
+
+# -- Launching the Quantum Service
+
+ # If you're running from the source
+ bin/quantum-server
+
+ # If you installed Quantum
+ quantum-server
+
+# -- Making requests against the Quantum Service
+
+ Quantum comes with a programmatic CLI that is driven by the Quantum Web
+ Service. You can use the CLI by issuing the following command:
+
+ # If you're running from the source
+ bin/quantum
+
+ # If you installed Quantum
+ quantum
+
+ This will show help all of the available commands.
+
+ An example session looks like this:
+
+ $ export TENANT=t1
+ $ quantum -v create_net $TENANT network1
+ Created a new Virtual Network with ID:e754e7c0-a8eb-40e5-861a-b182d30c3441
+
+# -- Authentication and Authorization
+
+Requests to Quantum API are authenticated with the Keystone identity service
+using a token-based authentication protocol.
+
+1) Enabling Authentication and Authorization
+The Keystone identity service is a requirement. It must be installed, although
+not necessarily on the same machine where Quantum is running; both Keystone's
+admin API and service API should be running
+
+Authentication and Authorization middleware should be enabled in the Quantum
+pipeline. To this aim, uncomment the following line in /etc/quantum.conf:
+
+pipeline = authN authZ extensions quantumapiapp
+
+The final step concerns configuring access to Keystone. The following attributes
+must be specified in the [filter:authN] section of quantum.conf:
+
+auth_host IP address or host name of the server where Keystone is running
+auth_port Port where the Keystone Admin API is listening
+auth_protocol Protocol used for communicating with Keystone (http/https)
+auth_version Keystone API version (default: 2.0)
+auth_admin_token Keystone token for administrative access
+auth_admin_user Keystone user with administrative rights
+auth_admin_password Password for the user specified with auth_admin_user
+
+NOTE: aut_admin_token and auth_admin_user/password are exclusive.
+If both are specified, auth_admin_token has priority.
+
+2) Authenticating and Authorizing request for Quantum API
+
+A user should first authenticate with Keystone, supplying user credentials;
+the Keystone service will return an authentication token, together with
+informations concerning token expirations and endpoint where that token can
+be used.
+
+The authentication token must be included in every request for the Quantum
+API, in the 'X_AUTH_TOKEN' header. Quantum will look for the authentication
+token in this header, and validate it with the Keystone service.
+
+In order to validate authentication tokens, Quantum uses Keystone's
+administrative API. It therefore requires credentials for an administrative
+user, which can be specified in Quantum's configuration file
+(etc/quantum.conf)
+Either username and password, or an authentication token for an administrative
+user can be specified in the configuration file:
+
+- Credentials:
+
+auth_admin_user = admin
+auth_admin_password = secrete
+
+- Admin token:
+
+auth_admin_token = 9a82c95a-99e9-4c3a-b5ee-199f6ba7ff04
+
+As of the current release, any user for a tenant is allowed to perform
+every operation on the networks owned by the tenant itself, except for
+plugging interfaces. In order to perform such operation, the user must have
+the Quantum:NetworkAdmin roles. Roles can be configured in Keystone using
+the administrative API.
+
+
+# -- Writing your own Quantum plug-in
+
+If you wish the write your own Quantum plugin, please refer to some concrete as
+well as sample plugins available in:
+
+../quantum/quantum/plugins/.. directory.
+
+There are a few requirements to writing your own plugin:
+
+1) Your plugin should implement all methods defined in the
+ quantum/quantum_plugin_base.QuantumPluginBase class
+
+2) Copy your Quantum plug-in over to the quantum/quantum/plugins/.. directory
+
+3) The next step is to edit the plugins.ini file in the same directory
+ as QuantumPluginBase class and specify the location of your custom plugin
+ as the "provider"
+
+4) Launch the Quantum Service, and your plug-in is configured and ready to
+ manage a Cloud Networking Fabric.
+
+# -- Extensions
+
+1) Creating Extensions:
+ a) Extension files should be placed under ./extensions folder.
+ b) The extension file should have a class with the same name as the filename.
+ This class should implement the contract required by the extension framework.
+ See ExtensionDescriptor class in ./quantum/common/extensions.py for details
+ c) To stop a file in ./extensions folder from being loaded as an extension,
+ the filename should start with an "_"
+ For an example of an extension file look at Foxinsocks class in
+ ./tests/unit/extensions/foxinsocks.py
+ The unit tests in ./tests/unit/test_extensions.py document all the ways in
+ which you can use extensions
+
+2) Associating plugins with extensions:
+ a) A Plugin can advertize all the extensions it supports through the
+ 'supported_extension_aliases' attribute. Eg:
+
+ class SomePlugin:
+ ...
+ supported_extension_aliases = ['extension1_alias',
+ 'extension2_alias',
+ 'extension3_alias']
+ Any extension not in this list will not be loaded for the plugin
+
+ b) Extension Interfaces for plugins (optional)
+ The extension can mandate an interface that plugins have to support with the
+ 'get_plugin_interface' method in the extension.
+ For an example see the FoxInSocksPluginInterface in foxinsocks.py.
+
+ The QuantumEchoPlugin lists foxinsox in its supported_extension_aliases
+ and implements the method from FoxInSocksPluginInterface.
+
+# -- Building packages
+
+ rpms:
+ python setup.py build rpm
+
+ debs:
+ python setup.py build deb
--- /dev/null
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
FLAGS = flags.FLAGS
-LOG = logging.getLogger('quantum.common.wsgi')
+LOG = logging.getLogger('quantum.wsgi')
def parse_options(parser, cli_args=None):
root_logger.addHandler(handler)
-def find_config_file(options, args):
+def find_config_file(options, args, config_file='quantum.conf'):
"""
Return the first config file found.
We search for the paste config file in the following order:
* If --config-file option is used, use that
* If args[0] is a file, use that
- * Search for quantum.conf in standard directories:
+ * Search for the configuration file in standard directories:
* .
* ~.quantum/
* ~
if os.path.exists(args[0]):
return fix_path(args[0])
- # Handle standard directory search for quantum.conf
- config_file_dirs = [fix_path(os.getcwd()),
- fix_path(os.path.join('~', '.quantum')),
+ dir_to_common = os.path.dirname(os.path.abspath(__file__))
+ root = os.path.join(dir_to_common, '..', '..', '..', '..')
+ # Handle standard directory search for the config file
+ config_file_dirs = [fix_path(os.path.join(os.getcwd(), 'server', 'etc')),
+ fix_path(os.path.join('~', '.quantum-venv', 'etc',
+ 'quantum')),
fix_path('~'),
os.path.join(FLAGS.state_path, 'etc'),
os.path.join(FLAGS.state_path, 'etc', 'quantum'),
+ os.path.join(root, 'server', 'etc'),
+ fix_path(os.path.join('~', '.local',
+ 'etc', 'quantum')),
+ '/usr/etc/quantum',
+ '/usr/local/etc/quantum',
'/etc/quantum/',
'/etc']
+
+ if os.path.exists(os.path.join(root, 'plugins')):
+ plugins = [fix_path(os.path.join(root, 'plugins', p, 'etc'))
+ for p in os.listdir(os.path.join(root, 'plugins'))]
+ plugins = [p for p in plugins if os.path.isdir(p)]
+ config_file_dirs.extend(plugins)
+
for cfg_dir in config_file_dirs:
- cfg_file = os.path.join(cfg_dir, 'quantum.conf')
+ cfg_file = os.path.join(cfg_dir, config_file)
if os.path.exists(cfg_file):
return cfg_file
from abc import ABCMeta
from quantum.common import exceptions
from quantum.manager import QuantumManager
-from quantum.common import wsgi
+from quantum import wsgi
LOG = logging.getLogger('quantum.common.extensions')
--- /dev/null
+from xml.dom import minidom
+import webob.exc
+
+from quantum.common import utils
+
+
+class Serializer(object):
+ """Serializes and deserializes dictionaries to certain MIME types."""
+
+ def __init__(self, metadata=None, default_xmlns=None):
+ """Create a serializer based on the given WSGI environment.
+
+ 'metadata' is an optional dict mapping MIME types to information
+ needed to serialize a dictionary to that type.
+
+ """
+ self.metadata = metadata or {}
+ self.default_xmlns = default_xmlns
+
+ def _get_serialize_handler(self, content_type):
+ handlers = {
+ 'application/json': self._to_json,
+ 'application/xml': self._to_xml,
+ }
+
+ try:
+ return handlers[content_type]
+ except Exception:
+ raise exception.InvalidContentType(content_type=content_type)
+
+ def serialize(self, data, content_type):
+ """Serialize a dictionary into the specified content type."""
+ return self._get_serialize_handler(content_type)(data)
+
+ def deserialize(self, datastring, content_type):
+ """Deserialize a string to a dictionary.
+
+ The string must be in the format of a supported MIME type.
+
+ """
+ try:
+ return self.get_deserialize_handler(content_type)(datastring)
+ except Exception:
+ raise webob.exc.HTTPBadRequest("Could not deserialize data")
+
+ def get_deserialize_handler(self, content_type):
+ handlers = {
+ 'application/json': self._from_json,
+ 'application/xml': self._from_xml,
+ }
+
+ try:
+ return handlers[content_type]
+ except Exception:
+ raise exception.InvalidContentType(content_type=content_type)
+
+ def _from_json(self, datastring):
+ return utils.loads(datastring)
+
+ def _from_xml(self, datastring):
+ xmldata = self.metadata.get('application/xml', {})
+ plurals = set(xmldata.get('plurals', {}))
+ node = minidom.parseString(datastring).childNodes[0]
+ return {node.nodeName: self._from_xml_node(node, plurals)}
+
+ def _from_xml_node(self, node, listnames):
+ """Convert a minidom node to a simple Python type.
+
+ listnames is a collection of names of XML nodes whose subnodes should
+ be considered list items.
+
+ """
+ if len(node.childNodes) == 1 and node.childNodes[0].nodeType == 3:
+ return node.childNodes[0].nodeValue
+ elif node.nodeName in listnames:
+ return [self._from_xml_node(n, listnames)
+ for n in node.childNodes if n.nodeType != node.TEXT_NODE]
+ else:
+ result = dict()
+ for attr in node.attributes.keys():
+ result[attr] = node.attributes[attr].nodeValue
+ for child in node.childNodes:
+ if child.nodeType != node.TEXT_NODE:
+ result[child.nodeName] = self._from_xml_node(child,
+ listnames)
+ return result
+
+ def _to_json(self, data):
+ return utils.dumps(data)
+
+ def _to_xml(self, data):
+ metadata = self.metadata.get('application/xml', {})
+ # We expect data to contain a single key which is the XML root.
+ root_key = data.keys()[0]
+ doc = minidom.Document()
+ node = self._to_xml_node(doc, metadata, root_key, data[root_key])
+
+ xmlns = node.getAttribute('xmlns')
+ if not xmlns and self.default_xmlns:
+ node.setAttribute('xmlns', self.default_xmlns)
+
+ return node.toprettyxml(indent='', newl='')
+
+ def _to_xml_node(self, doc, metadata, nodename, data):
+ """Recursive method to convert data members to XML nodes."""
+ result = doc.createElement(nodename)
+
+ # Set the xml namespace if one is specified
+ # TODO(justinsb): We could also use prefixes on the keys
+ xmlns = metadata.get('xmlns', None)
+ if xmlns:
+ result.setAttribute('xmlns', xmlns)
+ if type(data) is list:
+ collections = metadata.get('list_collections', {})
+ if nodename in collections:
+ metadata = collections[nodename]
+ for item in data:
+ node = doc.createElement(metadata['item_name'])
+ node.setAttribute(metadata['item_key'], str(item))
+ result.appendChild(node)
+ return result
+ singular = metadata.get('plurals', {}).get(nodename, None)
+ if singular is None:
+ if nodename.endswith('s'):
+ singular = nodename[:-1]
+ else:
+ singular = 'item'
+ for item in data:
+ node = self._to_xml_node(doc, metadata, singular, item)
+ result.appendChild(node)
+ elif type(data) is dict:
+ collections = metadata.get('dict_collections', {})
+ if nodename in collections:
+ metadata = collections[nodename]
+ for k, v in data.items():
+ node = doc.createElement(metadata['item_name'])
+ node.setAttribute(metadata['item_key'], str(k))
+ text = doc.createTextNode(str(v))
+ node.appendChild(text)
+ result.appendChild(node)
+ return result
+ attrs = metadata.get('attributes', {}).get(nodename, {})
+ for k, v in data.items():
+ if k in attrs:
+ result.setAttribute(k, str(v))
+ else:
+ node = self._to_xml_node(doc, metadata, k, v)
+ result.appendChild(node)
+ else:
+ # Type is atom.
+ node = doc.createTextNode(str(data))
+ result.appendChild(node)
+ return result
# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2011 Nicira Networks, Inc
-# All Rights Reserved.
+# 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
# 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."""
-"""
-System-level utilities and helper functions.
-"""
import ConfigParser
import datetime
import exceptions as exception
-import flags
import inspect
import logging
import os
import subprocess
import socket
import sys
+import base64
+import functools
+import json
+import re
+import string
+import struct
+import time
+import types
+
+from quantum.common import flags
+from quantum.common import exceptions as exception
+from quantum.common.exceptions import ProcessExecutionError
+
+
+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()
+
+
+def to_primitive(value):
+ if type(value) is type([]) or type(value) is type((None,)):
+ o = []
+ for v in value:
+ o.append(to_primitive(v))
+ return o
+ elif type(value) is type({}):
+ o = {}
+ for k, v in value.iteritems():
+ o[k] = to_primitive(v)
+ return o
+ elif isinstance(value, datetime.datetime):
+ return str(value)
+ elif hasattr(value, 'iteritems'):
+ return to_primitive(dict(value.iteritems()))
+ elif hasattr(value, '__iter__'):
+ return to_primitive(list(value))
+ else:
+ return value
+
+def dumps(value):
+ try:
+ return json.dumps(value)
+ except TypeError:
+ pass
+ return json.dumps(to_primitive(value))
-from exceptions import ProcessExecutionError
+def loads(s):
+ return json.loads(s)
TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
FLAGS = flags.FLAGS
return getattr(sys.modules[mod_str], class_str)
except (ImportError, ValueError, AttributeError) as e:
print e
- raise exception.NotFound('Class %s cannot be found' % class_str)
+ raise exception.ClassNotFound(class_name=class_str)
def import_object(import_str):
--- /dev/null
+#!/usr/bin/env python
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2010 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.
+
+
+"""Unittest runner for quantum
+
+To run all test::
+ python run_tests.py
+
+To run all unit tests::
+ python run_tests.py unit
+
+To run all functional tests::
+ python run_tests.py functional
+
+To run a single unit test::
+ python run_tests.py unit.test_stores:TestSwiftBackend.test_get
+
+To run a single functional test::
+ python run_tests.py functional.test_service:TestController.test_create
+
+To run a single unit test module::
+ python run_tests.py unit.test_stores
+
+To run a single functional test module::
+ python run_tests.py functional.test_stores
+"""
+
+import gettext
+import os
+import unittest
+import sys
+
+from quantum.common.test_lib import run_tests
+from nose import config
+from nose import core
+
+import quantum.tests.unit
+
+
+def main():
+ c = config.Config(stream=sys.stdout,
+ env=os.environ,
+ verbosity=3,
+ includeExe=True,
+ traverseNamespace=True,
+ plugins=core.DefaultPluginManager())
+ c.configureWhere(quantum.tests.unit.__path__)
+ sys.exit(run_tests(c))
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+try:
+ from setuptools import setup, find_packages
+except ImportError:
+ from ez_setup import use_setuptools
+ use_setuptools()
+ from setuptools import setup, find_packages
+
+Name = 'quantum-common'
+Url = "https://launchpad.net/quantum"
+Version = '2012.1-dev'
+License = 'Apache License 2.0'
+# Change as required
+Author = 'Netstack'
+AuthorEmail = 'netstack@lists.launchpad.net'
+Maintainer = ''
+Summary = 'Common functionalities for Quantum'
+ShortDescription = Summary
+Description = Summary
+
+requires = [
+ 'eventlet>=0.9.12',
+ 'Routes>=1.12.3',
+ 'nose',
+ 'Paste',
+ 'PasteDeploy',
+ 'pep8>=0.6.1',
+ 'python-gflags',
+ 'simplejson',
+ 'sqlalchemy',
+ 'webob',
+ 'webtest'
+]
+
+EagerResources = [
+ 'quantum',
+]
+
+ProjectScripts = [
+]
+
+PackageData = {
+}
+
+
+setup(
+ name=Name,
+ version=Version,
+ url=Url,
+ author=Author,
+ author_email=AuthorEmail,
+ description=ShortDescription,
+ long_description=Description,
+ license=License,
+ scripts=ProjectScripts,
+ install_requires=requires,
+ include_package_data=True,
+ packages=find_packages('lib'),
+ package_data=PackageData,
+ package_dir={'': 'lib'},
+ eager_resources=EagerResources,
+ namespace_packages=['quantum'],
+ entry_points={
+ 'console_scripts': [
+ 'quantum-tests = quantum.run_tests:main'
+ ]
+ },
+)
--- /dev/null
+include etc/*
--- /dev/null
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
--- /dev/null
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
"""
import os
+import logging as LOG
+from quantum.common.config import find_config_file
from quantum.plugins.cisco.common import cisco_configparser as confp
from quantum.plugins.cisco.common import cisco_constants as const
from quantum.plugins.cisco.common import cisco_exceptions as cexc
from quantum.plugins.cisco.db import l2network_db as cdb
-TENANT = const.NETWORK_ADMIN
+LOG.basicConfig(level=LOG.WARN)
+LOG.getLogger(const.LOGGER_COMPONENT_NAME)
-CREDENTIALS_FILE = "../conf/credentials.ini"
+CREDENTIALS_FILE = find_config_file({}, None, "credentials.ini")
+TENANT = const.NETWORK_ADMIN
-cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \
- + "/" + CREDENTIALS_FILE)
+cp = confp.CiscoConfigParser(CREDENTIALS_FILE)
_creds_dictionary = cp.walk(cp.dummy)
"""
import os
-
+from quantum.common.config import find_config_file
from quantum.plugins.cisco.common import cisco_configparser as confp
-CONF_FILE = "conf/l2network_plugin.ini"
-
-CONF_PARSER_OBJ = confp.\
-CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \
-"/" + CONF_FILE)
+CONF_FILE = find_config_file({}, None, "l2network_plugin.ini")
+CONF_PARSER_OBJ = confp.CiscoConfigParser(CONF_FILE)
"""
Reading the conf for the l2network_plugin
SECTION_CONF = CONF_PARSER_OBJ['MODEL']
MODEL_CLASS = SECTION_CONF['model_class']
+CONF_FILE = find_config_file({}, None, "cisco_plugins.ini")
+
SECTION_CONF = CONF_PARSER_OBJ['SEGMENTATION']
MANAGER_CLASS = SECTION_CONF['manager_class']
-CONF_FILE = "conf/plugins.ini"
-CONF_PARSER_OBJ = confp.\
-CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \
-"/" + CONF_FILE)
+CONF_PARSER_OBJ = confp.CiscoConfigParser(CONF_FILE)
"""
Reading the config for the device plugins
"""
PLUGINS = CONF_PARSER_OBJ.walk(CONF_PARSER_OBJ.dummy)
-CONF_FILE = "conf/db_conn.ini"
+CONF_FILE = find_config_file({}, None, "db_conn.ini")
-CONF_PARSER_OBJ = confp.\
-CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \
-"/" + CONF_FILE)
+CONF_PARSER_OBJ = confp.CiscoConfigParser(CONF_FILE)
"""
Reading DB config for the Quantum DB
"""
import os
-
+from quantum.common.config import find_config_file
from quantum.plugins.cisco.common import cisco_configparser as confp
-CONF_FILE = "../conf/ucs.ini"
-
-CP = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \
- + "/" + CONF_FILE)
+CP = confp.CiscoConfigParser(find_config_file({}, [], 'ucs.ini'))
SECTION = CP['UCSM']
UCSM_IP_ADDRESS = SECTION['ip_address']
SECTION = CP['DRIVER']
UCSM_DRIVER = SECTION['name']
-CONF_FILE = "../conf/ucs_inventory.ini"
-
-CP = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \
- + "/" + CONF_FILE)
+CP = confp.CiscoConfigParser(find_config_file({}, [],
+ 'ucs_inventory.ini'))
INVENTORY = CP.walk(CP.dummy)
"""
import os
-
+from quantum.common.config import find_config_file
from quantum.plugins.cisco.common import cisco_configparser as confp
-CONF_FILE = "../conf/ucs_inventory.ini"
-
-CP = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \
- + "/" + CONF_FILE)
+CP = confp.CiscoConfigParser(find_config_file({}, [],
+ 'plugins/cisco/ucs_inventory.ini'))
INVENTORY = CP.walk(CP.dummy)
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
# See http://code.google.com/p/python-nose/issues/detail?id=373
# The code below enables nosetests to work with i18n _() blocks
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
+
import __builtin__
import unittest
setattr(__builtin__, '_', lambda x: x)
--- /dev/null
+try:
+ from setuptools import setup, find_packages
+except ImportError:
+ from ez_setup import use_setuptools
+ use_setuptools()
+ from setuptools import setup, find_packages
+
+import sys
+
+Name = 'quantum-cisco-plugin'
+ProjecUrl = ""
+Version = '0.1'
+License = 'Apache License 2.0'
+# Change as required
+Author = 'Cisco Systems'
+AuthorEmail = ''
+Maintainer = ''
+Summary = 'Cisco plugin for Quantum'
+ShortDescription = Summary
+Description = Summary
+
+requires = [
+ 'quantum-common',
+ 'quantum-server',
+]
+
+EagerResources = [
+ 'quantum',
+]
+
+ProjectScripts = [
+]
+
+PackageData = {
+}
+
+# If we're installing server-wide, use an aboslute path for config
+# if not, use a relative path
+config_path = '/etc/quantum/plugins/cisco'
+relative_locations = ['--user', '--virtualenv', '--venv']
+if [x for x in relative_locations if x in sys.argv]:
+ config_path = 'etc/quantum/plugins/cisco'
+
+DataFiles = [
+ (config_path,
+ ['etc/credentials.ini', 'etc/l2network_plugin.ini', 'etc/nexus.ini',
+ 'etc/ucs.ini', 'etc/cisco_plugins.ini', 'etc/db_conn.ini'])
+]
+
+setup(
+ name=Name,
+ version=Version,
+ author=Author,
+ author_email=AuthorEmail,
+ description=ShortDescription,
+ long_description=Description,
+ license=License,
+ scripts=ProjectScripts,
+ install_requires=requires,
+ include_package_data=True,
+ packages=find_packages('lib'),
+ package_data=PackageData,
+ data_files=DataFiles,
+ package_dir={'': 'lib'},
+ eager_resources=EagerResources,
+ namespace_packages=['quantum'],
+ entry_points={
+ 'console_scripts': [
+ 'quantum-cisco-tests = quantum.plugins.cisco.run_tests:main'
+ ]
+ },
+)
--- /dev/null
+include etc/*
--- /dev/null
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
--- /dev/null
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
import sys
from quantum.common import exceptions as q_exc
+from quantum.common.config import find_config_file
from quantum.quantum_plugin_base import QuantumPluginBase
import quantum.db.api as db
import ovs_db
-CONF_FILE = "ovs_quantum_plugin.ini"
+CONF_FILE = find_config_file({}, None, "ovs_quantum_plugin.ini")
LOG.basicConfig(level=LOG.WARN)
LOG.getLogger("ovs_quantum_plugin")
-def find_config(basepath):
- for root, dirs, files in os.walk(basepath):
- if CONF_FILE in files:
- return os.path.join(root, CONF_FILE)
- return None
-
-
class VlanMap(object):
vlans = {}
--- /dev/null
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
--- /dev/null
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
--- /dev/null
+try:
+ from setuptools import setup, find_packages
+except ImportError:
+ from ez_setup import use_setuptools
+ use_setuptools()
+ from setuptools import setup, find_packages
+
+import sys
+
+Name = 'quantum-openvswitch-plugin'
+ProjecUrl = ""
+Version = '0.1'
+License = 'Apache License 2.0'
+# Change as required
+Author = 'Open vSwitch Team'
+AuthorEmail = 'discuss@openvswitch.org'
+Maintainer = ''
+Summary = 'OpenVSwitch plugin for Quantum'
+ShortDescription = Summary
+Description = Summary
+
+requires = [
+ 'quantum-common',
+ 'quantum-server',
+]
+
+EagerResources = [
+ 'quantum',
+]
+
+ProjectScripts = [
+]
+
+PackageData = {
+}
+
+# If we're installing server-wide, use an aboslute path for config
+# if not, use a relative path
+config_path = '/etc/quantum/plugins/openvswitch'
+relative_locations = ['--user', '--virtualenv', '--venv']
+if [x for x in relative_locations if x in sys.argv]:
+ config_path = 'etc/quantum/plugins/openvswitch'
+
+DataFiles = [
+ (config_path,
+ ['etc/ovs_quantum_plugin.ini'])
+]
+
+setup(
+ name=Name,
+ version=Version,
+ author=Author,
+ author_email=AuthorEmail,
+ description=ShortDescription,
+ long_description=Description,
+ license=License,
+ scripts=ProjectScripts,
+ install_requires=requires,
+ include_package_data=True,
+ packages=find_packages('lib'),
+ package_data=PackageData,
+ data_files=DataFiles,
+ package_dir={'': 'lib'},
+ eager_resources=EagerResources,
+ namespace_packages=['quantum'],
+)
--- /dev/null
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
--- /dev/null
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
--- /dev/null
+try:
+ from setuptools import setup, find_packages
+except ImportError:
+ from ez_setup import use_setuptools
+ use_setuptools()
+ from setuptools import setup, find_packages
+
+Name = 'quantum-sample-plugin'
+ProjecUrl = "https://launchpad.net/quantum"
+Version = '2012.1-dev'
+License = 'Apache License 2.0'
+# Change as required
+Author = 'Netstack'
+AuthorEmail = 'netstack@lists.launchpad.net'
+Maintainer = ''
+Summary = 'Sample functionalities for Quantum'
+ShortDescription = Summary
+Description = Summary
+
+requires = [
+ 'quantum-common',
+ 'quantum-server',
+]
+
+EagerResources = [
+ 'quantum',
+]
+
+ProjectScripts = [
+]
+
+PackageData = {
+}
+
+DataFiles = [
+]
+
+setup(
+ name=Name,
+ version=Version,
+ author=Author,
+ author_email=AuthorEmail,
+ description=ShortDescription,
+ long_description=Description,
+ license=License,
+ scripts=ProjectScripts,
+ install_requires=requires,
+ include_package_data=True,
+ packages=find_packages('lib'),
+ package_data=PackageData,
+ data_files=DataFiles,
+ package_dir={'': 'lib'},
+ eager_resources=EagerResources,
+ namespace_packages=['quantum'],
+)
+++ /dev/null
-#!/usr/bin/env python
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2010 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.
-
-
-"""Unittest runner for quantum Cisco plugin
-
-This file should be run from the top dir in the quantum directory
-
-To run all test::
- python quantum/plugins/cisco/run_tests.py
-
-To run all unit tests::
- python quantum/plugins/cisco/run_tests.py quantum.plugins.cisco.tests.unit
-
-To run all functional tests::
- python quantum/plugins/cisco/run_tests.py functional
-
-To run a single unit test::
- python quantum/plugins/cisco/run_tests.py \
- quantum.plugins.cisco.tests.unit.test_stores:TestSwiftBackend.test_get
-
-To run a single functional test::
- python quantum/plugins/cisco/run_tests.py \
- quantum.plugins.cisco.tests.functional.test_service \
- :TestController.test_create
-
-To run a single unit test module::
- python quantum/plugins/cisco/run_tests.py unit.test_stores
-
-To run a single functional test module::
- python quantum/plugins/cisco/run_tests.py functional.test_stores
-"""
-
-import gettext
-import logging
-import os
-import unittest
-import sys
-
-from nose import config
-
-sys.path.append(os.getcwd())
-
-from quantum.common.test_lib import run_tests, test_config
-
-if __name__ == '__main__':
- exit_status = False
-
- # if a single test case was specified,
- # we should only invoked the tests once
- invoke_once = len(sys.argv) > 1
-
- cwd = os.getcwd()
-
- working_dir = os.path.abspath("tests")
- c = config.Config(stream=sys.stdout,
- env=os.environ,
- verbosity=3,
- workingDir=working_dir)
- exit_status = run_tests(c)
-
- if invoke_once:
- sys.exit(0)
-
- os.chdir(cwd)
-
- working_dir = os.path.abspath("quantum/plugins/cisco/tests")
- c = config.Config(stream=sys.stdout,
- env=os.environ,
- verbosity=3,
- workingDir=working_dir)
- exit_status = exit_status or run_tests(c)
-
- sys.exit(exit_status)
--- /dev/null
+try:
+ from setuptools import setup, find_packages
+except ImportError:
+ from ez_setup import use_setuptools
+ use_setuptools()
+ from setuptools import setup, find_packages
+
+Name = 'quantum'
+Url = "https://launchpad.net/quantum"
+Version = '2012.1-dev'
+License = 'Apache License 2.0'
+Author = 'Netstack'
+AuthorEmail = 'netstack@lists.launchpad.net'
+Maintainer = ''
+Summary = 'Layer 2 network as a service for Openstack'
+ShortDescription = Summary
+Description = Summary
+
+requires = [
+ 'quantum-common',
+ 'quantum-client',
+ 'quantum-server'
+]
+
+EagerResources = [
+ 'quantum',
+]
+
+ProjectScripts = [
+]
+
+PackageData = {
+}
+
+
+setup(
+ name=Name,
+ version=Version,
+ url=Url,
+ author=Author,
+ author_email=AuthorEmail,
+ description=ShortDescription,
+ long_description=Description,
+ license=License,
+ scripts=ProjectScripts,
+ install_requires=requires,
+ include_package_data=True,
+ package_data=PackageData,
+)
+++ /dev/null
-# 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
-
-from common import exceptions as exception
-
-
-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()
-
-
-def to_primitive(value):
- if type(value) is type([]) or type(value) is type((None,)):
- o = []
- for v in value:
- o.append(to_primitive(v))
- return o
- elif type(value) is type({}):
- o = {}
- for k, v in value.iteritems():
- o[k] = to_primitive(v)
- return o
- elif isinstance(value, datetime.datetime):
- return str(value)
- elif hasattr(value, 'iteritems'):
- return to_primitive(dict(value.iteritems()))
- elif hasattr(value, '__iter__'):
- return to_primitive(list(value))
- else:
- return value
-
-
-def dumps(value):
- try:
- return json.dumps(value)
- except TypeError:
- pass
- return json.dumps(to_primitive(value))
-
-
-def loads(s):
- return json.loads(s)
#!/usr/bin/env python
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
+import tools.source_nonplugin_environment
+from quantum.run_tests import main as tests
-# Copyright 2010 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.
-
-
-"""Unittest runner for quantum
-
-To run all test::
- python run_tests.py
-
-To run all unit tests::
- python run_tests.py unit
-
-To run all functional tests::
- python run_tests.py functional
-
-To run a single unit test::
- python run_tests.py unit.test_stores:TestSwiftBackend.test_get
-
-To run a single functional test::
- python run_tests.py functional.test_service:TestController.test_create
-
-To run a single unit test module::
- python run_tests.py unit.test_stores
-
-To run a single functional test module::
- python run_tests.py functional.test_stores
-"""
-
-import gettext
-import os
-import unittest
-import sys
-
-from quantum.common.test_lib import run_tests
-from nose import config
-from nose import core
-
-
-if __name__ == '__main__':
- working_dir = os.path.abspath("tests")
- c = config.Config(stream=sys.stdout,
- env=os.environ,
- verbosity=3,
- workingDir=working_dir,
- plugins=core.DefaultPluginManager())
- sys.exit(run_tests(c))
+tests()
#
PEP8_EXCLUDE=vcsversion.py
PEP8_OPTIONS="--exclude=$PEP8_EXCLUDE --repeat --show-source"
-PEP8_INCLUDE="bin/* quantum tests tools run_tests.py"
+PEP8_INCLUDE="bin/* quantum server client common plugins tools run_tests.py setup.py"
RV=0
run_tests && pep8 $PEP8_OPTIONS $PEP8_INCLUDE || RV=1
--- /dev/null
+include etc/*
+include etc/init.d/*
--- /dev/null
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides: quantum-server
+# Required-Start: $remote_fs $syslog
+# Required-Stop: $remote_fs $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: quantum-server
+# Description: Provides the Quantum networking service
+### END INIT INFO
+
+set -e
+
+PIDFILE=/var/run/quantum/quantum-server.pid
+LOGFILE=/var/log/quantum/quantum-server.log
+
+DAEMON=/usr/bin/quantum-server
+DAEMON_ARGS="--log-file=$LOGFILE"
+DAEMON_DIR=/var/run
+
+ENABLED=true
+
+if test -f /etc/default/quantum-server; then
+ . /etc/default/quantum-server
+fi
+
+mkdir -p /var/run/quantum
+mkdir -p /var/log/quantum
+
+. /lib/lsb/init-functions
+
+export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
+export TMPDIR=/var/lib/quantum/tmp
+
+if [ ! -x ${DAEMON} ] ; then
+ exit 0
+fi
+
+case "$1" in
+ start)
+ test "$ENABLED" = "true" || exit 0
+ log_daemon_msg "Starting quantum server" "quantum-server"
+ start-stop-daemon -Sbmv --pidfile $PIDFILE --chdir $DAEMON_DIR --exec $DAEMON -- $DAEMON_ARGS
+ log_end_msg $?
+ ;;
+ stop)
+ test "$ENABLED" = "true" || exit 0
+ log_daemon_msg "Stopping quantum server" "quantum-server"
+ start-stop-daemon --stop --oknodo --pidfile ${PIDFILE}
+ log_end_msg $?
+ ;;
+ restart|force-reload)
+ test "$ENABLED" = "true" || exit 1
+ $0 stop
+ sleep 1
+ $0 start
+ ;;
+ status)
+ test "$ENABLED" = "true" || exit 0
+ status_of_proc -p $PIDFILE $DAEMON quantum-server && exit 0 || exit $?
+ ;;
+ *)
+ log_action_msg "Usage: /etc/init.d/quantum-server {start|stop|restart|force-reload|status}"
+ exit 1
+ ;;
+esac
+
+exit 0
paste.filter_factory = quantum.common.extensions:plugin_aware_extension_middleware_factory
[app:extensions_test_app]
-paste.app_factory = tests.unit.test_extensions:app_factory
+paste.app_factory = quantum.tests.unit.test_extensions:app_factory
--- /dev/null
+# 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.
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
from quantum.api import networks
from quantum.api import ports
from quantum.common import flags
-from quantum.common import wsgi
+from quantum import wsgi
LOG = logging.getLogger('quantum.api')
from webob import exc
-from quantum.common import wsgi
+from quantum import wsgi
XML_NS_V01 = 'http://netstack.org/quantum/api/v0.1'
XML_NS_V10 = 'http://netstack.org/quantum/api/v1.0'
import webob.exc
from quantum.api import api_common as common
-from quantum.common import wsgi
+from quantum import wsgi
class Fault(webob.exc.HTTPException):
import logging
import webob.dec
-from quantum.common import wsgi
+from quantum import wsgi
from quantum.api.views import versions as versions_view
LOG = logging.getLogger('quantum.api.versions')
gettext.install('quantum', unicode=1)
-from common import utils
+from quantum.common import utils
+from quantum.common.config import find_config_file
+from quantum.common.exceptions import ClassNotFound
from quantum_plugin_base import QuantumPluginBase
LOG = logging.getLogger('quantum.manager')
_instance = None
def __init__(self, options=None, config_file=None):
- if config_file == None:
- self.configuration_file = find_config(
- os.path.abspath(os.path.dirname(__file__)))
- else:
- self.configuration_file = config_file
# If no options have been provided, create an empty dict
if not options:
options = {}
+
+ if config_file:
+ config_file = [config_file]
+
+ self.configuration_file = find_config_file(options, config_file,
+ CONFIG_FILE)
if not 'plugin_provider' in options:
options['plugin_provider'] = \
utils.get_plugin_from_config(self.configuration_file)
LOG.debug("Plugin location:%s", options['plugin_provider'])
- plugin_klass = utils.import_class(options['plugin_provider'])
+
+ # If the plugin can't be found let them know gracefully
+ try:
+ plugin_klass = utils.import_class(options['plugin_provider'])
+ except ClassNotFound:
+ raise Exception("Plugin not found. You can install a " \
+ "plugin with: pip install <plugin-name>\n" \
+ "Example: pip install quantum-sample-plugin")
+
if not issubclass(plugin_klass, QuantumPluginBase):
raise Exception("Configured Quantum plug-in " \
"didn't pass compatibility test")
--- /dev/null
+#!/usr/bin/env python
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Nicira Neworks, 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.
+
+# If ../quantum/__init__.py exists, add ../ to Python search path, so that
+# it will override what happens to be installed in /usr/(local/)lib/python...
+
+import gettext
+import optparse
+import os
+import sys
+
+
+possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
+ os.pardir,
+ os.pardir))
+if os.path.exists(os.path.join(possible_topdir, 'quantum', '__init__.py')):
+ sys.path.insert(0, possible_topdir)
+
+gettext.install('quantum', unicode=1)
+
+from quantum import service
+from quantum.common import config
+
+
+def create_options(parser):
+ """
+ Sets up the CLI and config-file options that may be
+ parsed and program commands.
+ :param parser: The option parser
+ """
+ config.add_common_options(parser)
+ config.add_log_options(parser)
+
+
+def main():
+ oparser = optparse.OptionParser(version='%%prog VERSION')
+ create_options(oparser)
+ (options, args) = config.parse_options(oparser)
+
+ try:
+ quantum_service = service.serve_wsgi(service.QuantumApiService,
+ options=options,
+ args=args)
+ quantum_service.wait()
+ except RuntimeError, e:
+ sys.exit("ERROR: %s" % e)
+
+if __name__ == "__main__":
+ main()
import logging
from quantum.common import config
-from quantum.common import wsgi
+from quantum import wsgi
from quantum.common import exceptions as exception
# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2011 Nicira Networks, Inc.
+
+# Copyright 2011 OpenStack LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# 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 logging
+logging.basicConfig()
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 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.
+
+# See http://code.google.com/p/python-nose/issues/detail?id=373
+# The code below enables nosetests to work with i18n _() blocks
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
+
+import __builtin__
+import unittest
+setattr(__builtin__, '_', lambda x: x)
+
+
+class BaseTest(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+
+def setUp():
+ pass
from quantum import api as server
-from tests.unit import testlib_api
+from quantum.tests.unit import testlib_api
class FakeStdout:
from abc import abstractmethod
from quantum.common import extensions
-from quantum.common import wsgi
+from quantum import wsgi
class StubExtension(object):
import json
-from quantum.common import wsgi
+from quantum import wsgi
from quantum.common import extensions
from abc import abstractmethod
import logging
import unittest
-import tests.unit.testlib_api as testlib
+
+import quantum.tests.unit.testlib_api as testlib
from quantum import api as server
-from quantum.db import api as db
+from quantum.common.serializer import Serializer
from quantum.common.test_lib import test_config
-from quantum.common.wsgi import Serializer
+from quantum.db import api as db
LOG = logging.getLogger('quantum.tests.test_api')
from quantum import cli_lib as cli
from quantum.client import Client
from quantum.db import api as db
-from tests.unit.client_tools import stubs as client_stubs
+from quantum.tests.unit.client_tools import stubs as client_stubs
LOG = logging.getLogger('quantum.tests.test_cli')
FORMAT = 'json'
from quantum.db import api as db
-from tests.unit import database_stubs as db_stubs
+from quantum.tests.unit import database_stubs as db_stubs
LOG = logging.getLogger('quantum.tests.test_database')
# License for the specific language governing permissions and limitations
# under the License.
import json
-import os.path
+import logging
+import os
import routes
import unittest
-from tests.unit import BaseTest
+from quantum.tests.unit import BaseTest
from webtest import TestApp
-from quantum.common import wsgi
+from quantum import wsgi
from quantum.common import config
from quantum.common import extensions
from quantum.plugins.SamplePlugin import QuantumEchoPlugin
-from tests.unit.extension_stubs import (StubExtension, StubPlugin,
+from quantum.tests.unit.extension_stubs import (StubExtension, StubPlugin,
StubPluginInterface,
StubBaseAppController,
ExtensionExpectingPluginInterface)
PluginAwareExtensionManager,
ExtensionMiddleware)
+LOG = logging.getLogger('test_extensions')
-test_conf_file = os.path.join(os.path.dirname(__file__), os.pardir,
- os.pardir, 'etc', 'quantum.conf.test')
+test_conf_file = config.find_config_file({}, None, "quantum.conf.test")
extensions_path = os.path.join(os.path.dirname(__file__), "extensions")
import webob
-from quantum.common.wsgi import Serializer
+from quantum.common.serializer import Serializer
def create_request(path, body, content_type, method='GET'):
from quantum.common import exceptions as exception
-from quantum import utils
+from quantum.common import utils
LOG = logging.getLogger('quantum.common.wsgi')
--- /dev/null
+try:
+ from setuptools import setup, find_packages
+except ImportError:
+ from ez_setup import use_setuptools
+ use_setuptools()
+ from setuptools import setup, find_packages
+
+import os
+import sys
+
+Name = 'quantum-server'
+Url = "https://launchpad.net/quantum"
+Version = '2012.1-dev'
+License = 'Apache License 2.0'
+Author = 'Netstatck'
+AuthorEmail = 'netstack@lists.launchpad.net'
+Maintainer = ''
+Summary = 'Server functionalities for Quantum'
+ShortDescription = Summary
+Description = Summary
+
+requires = [
+ 'quantum-common'
+]
+
+EagerResources = [
+ 'quantum',
+]
+
+ProjectScripts = [
+]
+
+PackageData = {
+}
+
+# If we're installing server-wide, use an aboslute path for config
+# if not, use a relative path
+config_path = '/etc/quantum/'
+init_path = '/etc/init.d'
+
+relative_locations = ['--user', '--virtualenv', '--venv']
+if [x for x in relative_locations if x in sys.argv]:
+ config_path = 'etc/quantum/'
+ init_path = 'etc/init.d'
+
+DataFiles = [
+ (config_path,
+ ['etc/quantum.conf', 'etc/quantum.conf.sample',
+ 'etc/quantum.conf.test', 'etc/plugins.ini']),
+ (init_path, ['etc/init.d/quantum-server'])
+]
+
+setup(
+ name=Name,
+ version=Version,
+ url=Url,
+ author=Author,
+ author_email=AuthorEmail,
+ description=ShortDescription,
+ long_description=Description,
+ license=License,
+ scripts=ProjectScripts,
+ install_requires=requires,
+ include_package_data=True,
+ packages=find_packages('lib'),
+ package_data=PackageData,
+ data_files=DataFiles,
+ package_dir={'': 'lib'},
+ eager_resources=EagerResources,
+ namespace_packages=['quantum'],
+ entry_points={
+ 'console_scripts': [
+ 'quantum-server = quantum.server:main'
+ ]
+ },
+)
-import os
+from copy import deepcopy
+from optparse import OptionParser
+from os import path
+import re
import sys
-from setuptools import setup, find_packages
-
-
-def read(fname):
- return open(os.path.join(os.path.dirname(__file__), fname)).read()
-
-requirements = ['httplib2', 'eventlet', 'routes', 'webob']
-
-setup(
- name='Quantum',
- version='0.1',
- description='Layer 2 network as a service for Openstack',
- long_description=read('README'),
- url='http://launchpad.net/quantum',
- license='Apache',
- author='Netstack',
- author_email='netstack@launchpad.net',
- packages=find_packages(exclude=['tests']),
- classifiers=[
- 'Development Status :: 4 - Beta',
- 'Environment :: Console',
- 'Intended Audience :: Developers',
- 'Intended Audience :: Information Technology',
- 'License :: OSI Approved :: BSD License',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- ],
- namespace_packages=["quantum"],
- install_requires=requirements,
-
- tests_require=["nose"],
- test_suite="nose.collector",
-)
+
+from tools import install_venv
+
+ROOT = path.abspath(path.dirname(__file__))
+CONFIG_PATH = path.abspath('/etc/quantum')
+BASE_PACKAGES = ['common', 'server', 'client']
+PLUGINS = ['plugins/sample-plugin', 'plugins/cisco-plugin',
+ 'plugins/openvswitch-plugin']
+
+RELATIVE = False
+
+
+def clean_path(dirty):
+ """Makes sure path delimiters are OS compliant"""
+ return path.join(*dirty.split('/'))
+
+
+def script_dir():
+ script_dir = '/usr/sbin/'
+ if RELATIVE:
+ script_dir = 'usr/sbin/'
+ return script_dir
+
+
+def create_parser():
+ """Setup the option parser"""
+ usagestr = "Usage: %prog [OPTIONS] <command> [args]"
+ parser = OptionParser(usage=usagestr)
+ parser.add_option("-V", "--virtualenv", "--venv", dest="venv",
+ action="store_true", default=False, help="Install to a virtual-env")
+ parser.add_option("-U", "--user", dest="user", action="store_true",
+ default=False, help="Install to users's home")
+ options, args = parser.parse_args()
+
+ if args.__len__() is 0:
+ print usagestr
+ print "Commands:\ninstall\nuninstall\nbuild\nclean"
+ exit(0)
+
+ cmd = args[0]
+ args = args[1:]
+ return (options, cmd, args)
+
+
+def install_packages(options, args=None):
+ """Builds and installs packages"""
+ # Start building a command list
+ cmd = ['pip', 'install']
+
+ # If no options, just a regular install. If venv, create, prepare and
+ # install in venv. If --user install in user's local dir. Usually
+ # ~/.local/
+ if options.venv:
+ if install_venv.VENV_EXISTS:
+ print "Virtual-env exists"
+ else:
+ install_venv.create_virtualenv(install_pip=False)
+ install_venv.install_dependencies()
+ cmd.extend(['-E', install_venv.VENV])
+ elif options.user:
+ cmd.append('--user')
+
+ # Install packages
+ # TODO(Tyler) allow users to pass in packages in cli
+ for package in BASE_PACKAGES + PLUGINS:
+ print "Installing %s" % package
+ # Each package needs its own command list, and it needs the path
+ # in the correct place (after "pip install")
+ pcmd = deepcopy(cmd)
+ pcmd.insert(2, path.join(ROOT, clean_path(package)))
+
+ if package is 'server':
+ pcmd.append("--install-option=--install-scripts=%s" %\
+ script_dir())
+ print pcmd
+ install_venv.run_command(pcmd)
+ print "done."
+
+
+def uninstall_packages(options, args=None):
+ """Removes packages"""
+ cmd = ['pip', 'uninstall', '-y']
+
+ for package in ['quantum-' + x.split('/')[-1] \
+ for x in BASE_PACKAGES + PLUGINS]:
+ print "Uninstalling %s" % package
+ # Each package needs its own command list, and it needs the path
+ # in the correct place (after "pip uninstall"
+ pcmd = deepcopy(cmd)
+ pcmd.insert(2, package)
+ print pcmd
+ install_venv.run_command(pcmd)
+ print "done."
+
+
+def build_packages(options, args=None):
+ """Build RPM and/or deb packages"""
+ if not args:
+ print "To build packages you must specifiy either 'rpm', " \
+ "'deb', or 'all'"
+ exit(0)
+ if args[0] not in ['rpm', 'deb', 'all']:
+ raise Exception("Packge type must be rpm, deb, or all")
+
+ if 'rpm' in args or 'all' in args:
+ # Since we need to cd to build rpms, we call this sh script
+ cmd = ['tools/build_rpms.sh']
+ for package in BASE_PACKAGES + PLUGINS:
+ print "Building %s rpm" % package
+ pcmd = deepcopy(cmd)
+ pcmd.append(package)
+ install_venv.run_command(pcmd)
+ print "done."
+
+ if 'deb' in args or 'all' in args:
+ cmd = ['tools/build_debs.sh']
+ for p in BASE_PACKAGES + PLUGINS:
+ print "Building %s deb" % p
+ pcmd = deepcopy(cmd)
+ pcmd.append(p)
+ install_venv.run_command(pcmd)
+ print "done."
+
+
+def clean_packages(options, args):
+ """Cleans build packages"""
+ cmd = ["tools/clean.sh"]
+ install_venv.run_command(cmd)
+
+
+def main():
+ """Main Build script for Quantum"""
+ options, cmd, args = create_parser()
+
+ if options.user:
+ RELATIVE = True
+
+ print "Checking for virtual-env and easy_install"
+ install_venv.check_dependencies()
+
+ # Execute command
+ try:
+ globals()["%s_packages" % cmd](options, args)
+ except KeyError as exc:
+ print "Command %s' not found" % exc.__str__().split('_')[0]
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+#!/bin/bash
+ALIEN=`which alien`
+if [ $? -ne 0 ]; then
+ echo "You must have alien installed to build debian packages"
+ exit 1
+fi
+FAKEROOT=""
+if [ `id -u` != 0 ]; then
+ FAKEROOT=`which fakeroot`
+ if [ $? -ne 0 ]; then
+ echo "You must be root or have fakeroot installed to build debian packages"
+ exit 1
+ fi
+fi
+
+ls $@/dist/*.rpm >/dev/null 2>&1
+if [ $? -ne 0 ]; then
+ echo "You must build rpms before building debian packages"
+ exit 1
+fi
+
+cd $@
+if [ $? -ne 0 ]; then
+ echo "Directory $@ doesn't exist -- what do you want me to build?"
+ exit 1
+fi
+$FAKEROOT $ALIEN -c -v -d dist/*.noarch.rpm
--- /dev/null
+#!/bin/bash
+cd $@ && python setup.py bdist_rpm
--- /dev/null
+#!/bin/bash
+rm -rf ./*.deb ./*.tar.gz ./*.dsc ./*.changes
+rm -rf */*.deb
+rm -rf ./plugins/**/build/ ./plugins/**/dist
+rm -rf ./plugins/**/lib/quantum_*_plugin.egg-info ./plugins/quantum-*
+#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-VENV = os.path.join(ROOT, '.quantum-venv')
+VENV = os.path.expanduser('~/.quantum-venv')
+VENV_EXISTS = bool(os.path.exists(VENV))
PIP_REQUIRES = os.path.join(ROOT, 'tools', 'pip-requires')
stdout = subprocess.PIPE
else:
stdout = None
-
proc = subprocess.Popen(cmd, cwd=ROOT, stdout=stdout)
output = proc.communicate()[0]
if check_exit_code and proc.returncode != 0:
- die('Command "%s" failed.\n%s', ' '.join(cmd), output)
+ raise Exception('Command "%s" failed.\n%s' % (' '.join(cmd), output))
return output
"""Make sure virtualenv is in the path."""
if not HAS_VIRTUALENV:
- print 'not found.'
- # Try installing it via easy_install...
- if HAS_EASY_INSTALL:
- print 'Installing virtualenv via easy_install...',
- if not run_command(['which', 'easy_install']):
- die('ERROR: virtualenv not found.\n\n'
- 'Quantum requires virtualenv, please install'
- ' it using your favorite package management tool')
- print 'done.'
+ raise Exception('Virtualenv not found. ' + \
+ 'Try installing python-virtualenv')
print 'done.'
-def create_virtualenv(venv=VENV):
+def create_virtualenv(venv=VENV, install_pip=False):
"""Creates the virtual environment and installs PIP only into the
virtual environment
"""
print 'Creating venv...',
- run_command(['virtualenv', '-q', '--no-site-packages', VENV])
+
+ install = ['virtualenv', '-q', venv]
+ run_command(install)
+
print 'done.'
print 'Installing pip in virtualenv...',
- if not run_command(['tools/with_venv.sh', 'easy_install', 'pip']).strip():
+ if install_pip and \
+ not run_command(['tools/with_venv.sh', 'easy_install', 'pip']):
die("Failed to install pip.")
print 'done.'
# Install greenlet by hand - just listing it in the requires file does not
# get it in stalled in the right order
- venv_tool = 'tools/with_venv.sh'
- run_command([venv_tool, 'pip', 'install', '-E', venv, '-r', PIP_REQUIRES],
- redirect_output=False)
+ run_command(['tools/with_venv.sh', 'pip', 'install', '-E', venv,
+ '-r', PIP_REQUIRES], redirect_output=False)
# Tell the virtual env how to "import quantum"
pthfile = os.path.join(venv, "lib", "python2.6", "site-packages",
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Cisco Systems
+# 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: Tyler Smith, Cisco Systems
+import os
+import sys
+
+# To run from the source code, we need to add the various packages
+# to our path so we can find all of the modules correctly
+packages = ['common', 'server', 'client']
+plugins = ["plugins/%s" % p for p in
+ os.listdir(os.path.join(os.getcwd(), 'plugins'))]
+
+for project in packages + plugins:
+ sys.path.insert(0, os.path.join(os.getcwd(), project, 'lib'))
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Cisco Systems
+# 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: Tyler Smith, Cisco Systems
+import os
+import sys
+
+# To run from the source code, we need to add the various packages
+# to our path so we can find all of the modules correctly
+packages = ['common', 'server', 'client']
+
+for project in packages + ["plugins/sample-plugin"]:
+ sys.path.insert(0, os.path.join(os.getcwd(), project, 'lib'))
# under the License.
TOOLS=`dirname $0`
-VENV=$TOOLS/../.quantum-venv
+VENV=~/.quantum-venv
source $VENV/bin/activate && $@