Syncing with Cisco extensions branch.

This commit is contained in:
Sumit Naiksatam 2011-08-25 19:54:08 -07:00
commit 0ab88c27a5
43 changed files with 901 additions and 548 deletions

View File

@ -47,12 +47,12 @@ class ViewBuilder(object):
return credential
def _build_simple(self, credential_data):
"""Return a simple model of a server."""
"""Return a simple description of credential."""
return dict(credential=dict(id=credential_data['credential_id']))
def _build_detail(self, credential_data):
"""Return a simple model of a server."""
"""Return a detailed description of credential."""
return dict(credential=dict(id=credential_data['credential_id'],
name=credential_data['user_name'],
password=credential_data['password']))
password=credential_data['password']))

View File

@ -1,181 +0,0 @@
"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, 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: Ying Liu, Cisco Systems, Inc.
#
"""
import logging
# pylint: disable-msg=E0602
class ExtensionException(Exception):
"""Quantum Cisco api Exception
Taken from nova.exception.NovaException
To correctly use this class, inherit from it and define
a 'message' property. That message will get printf'd
with the keyword arguments provided to the constructor.
"""
message = _("An unknown exception occurred.")
def __init__(self, **kwargs):
try:
self._error_string = self.message % kwargs
except Exception:
# at least get the core message out if something happened
self._error_string = self.message
def __str__(self):
"""Error Msg"""
return self._error_string
class ProcessExecutionError(IOError):
"""Process Exe Error"""
def __init__(self, stdout=None, stderr=None, exit_code=None, cmd=None,
description=None):
if description is None:
description = "Unexpected error while running command."
if exit_code is None:
exit_code = '-'
message = "%s\nCommand: %s\nExit code: %s\nStdout: %r\nStderr: %r" % (
description, cmd, exit_code, stdout, stderr)
IOError.__init__(self, message)
class Error(Exception):
"""Error Class"""
def __init__(self, message=None):
super(Error, self).__init__(message)
class ApiError(Error):
"""Api Error"""
def __init__(self, message='Unknown', code='Unknown'):
self.message = message
self.code = code
super(ApiError, self).__init__('%s: %s' % (code, message))
class NotFound(ExtensionException):
"""Error Msg"""
pass
class ClassNotFound(NotFound):
"""Extension Error Msg"""
message = _("Class %(class_name)s could not be found")
class PortprofileNotFound(NotFound):
"""Extension Error Msg"""
message = _("Portprofile %(_id)s could not be found")
class NovatenantNotFound(NotFound):
"""Extension Error Msg"""
message = _("Novatenant %(_id)s could not be found")
class PortNotFound(NotFound):
"""Extension Error"""
message = _("Port %(port_id)s could not be found " \
"on Network %(net_id)s")
class CredentialNotFound(NotFound):
"""Extension Error"""
message = _("Credential %(_id)s could not be found")
class QosNotFound(NotFound):
"""Extension Error"""
message = _("QoS %(_id)s could not be found")
"""
class PortprofileInUse(ExtensionException):
message = _("Unable to complete operation on Portprofile %(net_id)s. " \
"There is one or more attachments plugged into its ports.")
class PortInUse(ExtensionException):
message = _("Unable to complete operation on port %(port_id)s " \
"for Portprofile %(net_id)s. The attachment '%(att_id)s" \
"is plugged into the logical port.")
class AlreadyAttached(ExtensionException):
message = _("Unable to plug the attachment %(att_id)s into port " \
"%(port_id)s for Portprofile %(net_id)s. The attachment is " \
"already plugged into port %(att_port_id)s")
"""
class Duplicate(Error):
"""Duplication Error"""
pass
class NotAuthorized(Error):
"Not Auth Error"
pass
class NotEmpty(Error):
"""Not Empty Error"""
pass
class Invalid(Error):
"""Invalid Error"""
pass
class InvalidContentType(Invalid):
message = _("Invalid content type %(content_type)s.")
class BadInputError(Exception):
"""Error resulting from a client sending bad input to a server"""
pass
class MissingArgumentError(Error):
"""Miss arg error"""
pass
def wrap_exception(afunc):
"""Wrap Exception"""
def _wrap(*args, **kw):
"""Internal Wrap Exception func"""
try:
return afunc(*args, **kw)
except Exception, exp:
if not isinstance(exp, Error):
#exc_type, exc_value, exc_traceback = sys.exc_info()
logging.exception('Uncaught exception')
#logging.error(traceback.extract_stack(exc_traceback))
raise Error(str(exp))
raise
_wrap.func_name = afunc.func_name
return _wrap

View File

@ -18,6 +18,7 @@
# @author: Ying Liu, Cisco Systems, Inc.
#
"""
from quantum.plugins.cisco.common import cisco_constants as const
def get_view_builder(req):
@ -39,8 +40,8 @@ class ViewBuilder(object):
def build_host(self, host_data):
"""Return host description."""
return dict(host_list=host_data['host_list'])
return dict(host_list=host_data[const.HOST_LIST])
def build_vif(self, vif_data):
"""Return VIF description."""
return dict(vif_desc=vif_data['vif_desc'])
return dict(vif_desc=vif_data[const.VIF_DESC])

View File

@ -47,7 +47,7 @@ class ViewBuilder(object):
return portprofile
def _build_simple(self, portprofile_data):
"""Return a simple model of a portprofile"""
"""Return a simple description of a portprofile"""
return dict(portprofile=dict(id=portprofile_data['profile_id']))
def _build_detail(self, portprofile_data):

View File

@ -46,11 +46,11 @@ class ViewBuilder(object):
return qos
def _build_simple(self, qos_data):
"""Return a simple model of a server."""
"""Return a simple description of qos."""
return dict(qos=dict(id=qos_data['qos_id']))
def _build_detail(self, qos_data):
"""Return a simple model of a server."""
"""Return a detailed description of qos."""
return dict(qos=dict(id=qos_data['qos_id'],
name=qos_data['qos_name'],
description=qos_data['qos_desc']))

View File

@ -21,14 +21,13 @@
import logging
from webob import exc
from extensions import _credential_view as credential_view
from quantum.plugins.cisco.common import cisco_exceptions as exception
#from extensions import _exceptions as exception
from extensions import _faults as faults
from extensions import _credential_view as credential_view
from quantum.api import api_common as common
from quantum.common import extensions
from quantum.manager import QuantumManager
from quantum.plugins.cisco.common import cisco_exceptions as exception
from quantum.plugins.cisco.common import cisco_faults as faults
LOG = logging.getLogger('quantum.api.credentials')
@ -37,7 +36,7 @@ class Credential(object):
"""extension class Credential"""
def __init__(self):
pass
@classmethod
def get_name(cls):
""" Returns Ext Resource Name """
@ -60,7 +59,7 @@ class Credential(object):
@classmethod
def get_updated(cls):
""" Returns Ext Resource Name """
""" Returns Ext Resource Update Time """
return "2011-07-25T13:25:27-06:00"
@classmethod
@ -68,7 +67,6 @@ class Credential(object):
""" Returns Ext Resources """
parent_resource = dict(member_name="tenant",
collection_name="extensions/csco/tenants")
controller = CredentialController(QuantumManager.get_plugin())
return [extensions.ResourceExtension('credentials', controller,
parent=parent_resource)]
@ -85,7 +83,7 @@ class CredentialController(common.QuantumController):
'required': True}, {
'param-name': 'password',
'required': True}]
_serialization_metadata = {
"application/xml": {
"attributes": {
@ -97,8 +95,7 @@ class CredentialController(common.QuantumController):
def __init__(self, plugin):
self._resource_name = 'credential'
self._plugin = plugin
#super(CredentialController, self).__init__(plugin)
def index(self, request, tenant_id):
""" Returns a list of credential ids """
return self._items(request, tenant_id, is_detail=False)
@ -126,7 +123,6 @@ class CredentialController(common.QuantumController):
def create(self, request, tenant_id):
""" Creates a new credential for a given tenant """
#look for credential name in request
try:
req_params = \
self._parse_request_params(request,
@ -168,4 +164,3 @@ class CredentialController(common.QuantumController):
return exc.HTTPAccepted()
except exception.CredentialNotFound as exp:
return faults.Fault(faults.CredentialNotFound(exp))

View File

@ -21,13 +21,11 @@
from webob import exc
from extensions import _novatenant_view as novatenant_view
from quantum.common import exceptions as qexception
#from extensions import _exceptions as exception
from extensions import _faults as faults
from quantum.api import api_common as common
from quantum.common import exceptions as qexception
from quantum.common import extensions
from quantum.manager import QuantumManager
from quantum.plugins.cisco.common import cisco_faults as faults
class Novatenant(object):
@ -42,27 +40,27 @@ class Novatenant(object):
@classmethod
def get_alias(cls):
""" Returns Ext Resource Name """
""" Returns Ext Resource alias"""
return "Cisco Nova Tenant"
@classmethod
def get_description(cls):
""" Returns Ext Resource Name """
""" Returns Ext Resource Description """
return "novatenant resource is used by nova side to invoke quantum api"
@classmethod
def get_namespace(cls):
""" Returns Ext Resource Name """
""" Returns Ext Resource Namespace """
return "http://docs.ciscocloud.com/api/ext/novatenant/v1.0"
@classmethod
def get_updated(cls):
""" Returns Ext Resource Name """
""" Returns Ext Resource Updated Time """
return "2011-08-09T13:25:27-06:00"
@classmethod
def get_resources(cls):
""" Returns Ext Resource Name """
""" Returns Ext Resource """
parent_resource = dict(member_name="tenant",
collection_name="extensions/csco/tenants")
member_actions = {'schedule_host': "PUT",
@ -98,16 +96,8 @@ class NovatenantsController(common.QuantumController):
def __init__(self, plugin):
self._resource_name = 'novatenant'
self._plugin = plugin
#super(NovatenantsController, self).__init__(plugin)
def index(self, request, tenant_id):
""" Returns a list of novatenant ids """
return "novatenant is a dummy resource"
def _items(self, request, tenant_id, is_detail):
""" Returns a list of novatenants. """
return "novatenant is a dummy resource"
#added for cisco's extension
# pylint: disable-msg=E1101,W0613
def show(self, request, tenant_id, id):
""" Returns novatenant details for the given novatenant id """
@ -144,7 +134,6 @@ class NovatenantsController(common.QuantumController):
builder = novatenant_view.get_view_builder(request)
result = builder.build_host(host)
return result
#return exc.HTTPAccepted()
except qexception.PortNotFound as exp:
return faults.Fault(faults.PortNotFound(exp))

View File

@ -22,14 +22,12 @@
from webob import exc
from extensions import _pprofiles as pprofiles_view
from quantum.plugins.cisco.common import cisco_exceptions as exception
from quantum.common import exceptions as qexception
#from extensions import _exceptions as exception
from extensions import _faults as faults
from quantum.api import api_common as common
from quantum.common import exceptions as qexception
from quantum.common import extensions
from quantum.manager import QuantumManager
from quantum.plugins.cisco.common import cisco_exceptions as exception
from quantum.plugins.cisco.common import cisco_faults as faults
class Portprofile(object):
@ -59,7 +57,7 @@ class Portprofile(object):
@classmethod
def get_updated(cls):
""" Returns Ext Resource Updateed time """
""" Returns Ext Resource Updated time """
return "2011-07-23T13:25:27-06:00"
@classmethod
@ -68,7 +66,7 @@ class Portprofile(object):
parent_resource = dict(member_name="tenant",
collection_name="extensions/csco/tenants")
member_actions = {'associate_portprofile': "PUT",
'disassociate_portprofile': "POST"}
'disassociate_portprofile': "PUT"}
controller = PortprofilesController(QuantumManager.get_plugin())
return [extensions.ResourceExtension('portprofiles', controller,
parent=parent_resource,
@ -82,7 +80,6 @@ class PortprofilesController(common.QuantumController):
def __init__(self, plugin):
self._resource_name = 'portprofile'
self._plugin = plugin
#super(PortprofilesController, self).__init__(plugin)
self._portprofile_ops_param_list = [{
'param-name': 'portprofile_name',
@ -130,7 +127,6 @@ class PortprofilesController(common.QuantumController):
return dict(portprofiles=result)
except exception.PortProfileNotFound as exp:
return faults.Fault(faults.PortprofileNotFound(exp))
#return faults.Fault(exp)
def create(self, request, tenant_id):
""" Creates a new portprofile for a given tenant """
@ -188,7 +184,6 @@ class PortprofilesController(common.QuantumController):
except exc.HTTPError as exp:
return faults.Fault(exp)
net_id = req_params['network-id'].strip()
#print "*****net id "+net_id
port_id = req_params['port-id'].strip()
try:
self._plugin.associate_portprofile(tenant_id,
@ -212,7 +207,6 @@ class PortprofilesController(common.QuantumController):
except exc.HTTPError as exp:
return faults.Fault(exp)
net_id = req_params['network-id'].strip()
#print "*****net id "+net_id
port_id = req_params['port-id'].strip()
try:
self._plugin. \

View File

@ -22,13 +22,12 @@ import logging
from webob import exc
from extensions import _qos_view as qos_view
from quantum.plugins.cisco.common import cisco_exceptions as exception
from extensions import _exceptions as exte
from extensions import _faults as faults
from quantum.api import api_common as common
from quantum.common import extensions
from quantum.manager import QuantumManager
from quantum.plugins.cisco.common import cisco_exceptions as exception
from quantum.plugins.cisco.common import cisco_faults as faults
LOG = logging.getLogger('quantum.api.qoss')
@ -94,7 +93,6 @@ class QosController(common.QuantumController):
def __init__(self, plugin):
self._resource_name = 'qos'
self._plugin = plugin
#super(QosController, self).__init__(plugin)
def index(self, request, tenant_id):
""" Returns a list of qos ids """

View File

@ -240,7 +240,7 @@ def api_plug_iface(client, *args):
res = client.attach_resource(nid, pid, data)
except Exception, e:
LOG.error("Failed to plug iface \"%s\" to port \"%s\": %s" % (vid,
pid, output))
pid, e))
return
LOG.debug(res)
print "Plugged interface \"%s\" to port:%s on network:%s" % (vid, pid, nid)
@ -386,6 +386,6 @@ if __name__ == "__main__":
commands[cmd]["api_func"](client, *args)
else:
quantum = QuantumManager()
manager = quantum.get_manager()
manager = quantum.get_plugin()
commands[cmd]["func"](manager, *args)
sys.exit(0)

View File

@ -20,16 +20,32 @@ import httplib
import socket
import urllib
from quantum.common.wsgi import Serializer
from quantum.common import exceptions
EXCEPTIONS = {
400: exceptions.BadInputError,
401: exceptions.NotAuthorized,
420: exceptions.NetworkNotFound,
421: exceptions.NetworkInUse,
422: exceptions.NetworkNameExists,
430: exceptions.PortNotFound,
431: exceptions.StateInvalid,
432: exceptions.PortInUse,
440: exceptions.AlreadyAttached,
441: exceptions.AttachmentNotReady,
}
class api_call(object):
class ApiCall(object):
"""A Decorator to add support for format and tenant overriding"""
def __init__(self, f):
self.f = f
def __init__(self, function):
self.function = function
def __get__(self, instance, owner):
def with_params(*args, **kwargs):
# Temporarily set format and tenant for this request
"""
Temporarily sets the format and tenant for this request
"""
(format, tenant) = (instance.format, instance.tenant)
if 'format' in kwargs:
@ -37,7 +53,7 @@ class api_call(object):
if 'tenant' in kwargs:
instance.tenant = kwargs['tenant']
ret = self.f(instance, *args)
ret = self.function(instance, *args)
(instance.format, instance.tenant) = (format, tenant)
return ret
return with_params
@ -47,9 +63,7 @@ class Client(object):
"""A base client class - derived from Glance.BaseClient"""
action_prefix = '/v0.1/tenants/{tenant_id}'
"""Action query strings"""
# Action query strings
networks_path = "/networks"
network_path = "/networks/%s"
ports_path = "/networks/%s/ports"
@ -58,7 +72,7 @@ class Client(object):
def __init__(self, host="127.0.0.1", port=9696, use_ssl=False, tenant=None,
format="xml", testingStub=None, key_file=None, cert_file=None,
logger=None):
logger=None, action_prefix="/v0.1/tenants/{tenant_id}"):
"""
Creates a new client to some service.
@ -81,6 +95,7 @@ class Client(object):
self.key_file = key_file
self.cert_file = cert_file
self.logger = logger
self.action_prefix = action_prefix
def get_connection_type(self):
"""
@ -114,7 +129,7 @@ class Client(object):
# Add format and tenant_id
action += ".%s" % self.format
action = Client.action_prefix + action
action = self.action_prefix + action
action = action.replace('{tenant_id}', self.tenant)
if type(params) is dict:
@ -133,9 +148,9 @@ class Client(object):
certs = dict((x, certs[x]) for x in certs if certs[x] != None)
if self.use_ssl and len(certs):
c = connection_type(self.host, self.port, **certs)
conn = connection_type(self.host, self.port, **certs)
else:
c = connection_type(self.host, self.port)
conn = connection_type(self.host, self.port)
if self.logger:
self.logger.debug("Quantum Client Request:\n" \
@ -143,8 +158,8 @@ class Client(object):
if body:
self.logger.debug(body)
c.request(method, action, body, headers)
res = c.getresponse()
conn.request(method, action, body, headers)
res = conn.getresponse()
status_code = self.get_status_code(res)
data = res.read()
@ -158,6 +173,8 @@ class Client(object):
httplib.NO_CONTENT):
return self.deserialize(data, status_code)
else:
if res.status in EXCEPTIONS:
raise EXCEPTIONS[res.status]()
raise Exception("Server returned error: %s" % res.read())
except (socket.error, IOError), e:
@ -175,6 +192,10 @@ class Client(object):
return response.status
def serialize(self, data):
"""
Serializes a dictionary with a single key (which can contain any
structure) into either xml or json
"""
if data is None:
return None
elif type(data) is dict:
@ -184,65 +205,72 @@ class Client(object):
% type(data))
def deserialize(self, data, status_code):
"""
Deserializes a an xml or json string into a dictionary
"""
if status_code == 202:
return data
return Serializer().deserialize(data, self.content_type())
def content_type(self, format=None):
"""
Returns the mime-type for either 'xml' or 'json'. Defaults to the
currently set format
"""
if not format:
format = self.format
return "application/%s" % (format)
@api_call
@ApiCall
def list_networks(self):
"""
Fetches a list of all networks for a tenant
"""
return self.do_request("GET", self.networks_path)
@api_call
@ApiCall
def show_network_details(self, network):
"""
Fetches the details of a certain network
"""
return self.do_request("GET", self.network_path % (network))
@api_call
@ApiCall
def create_network(self, body=None):
"""
Creates a new network
"""
return self.do_request("POST", self.networks_path, body=body)
@api_call
@ApiCall
def update_network(self, network, body=None):
"""
Updates a network
"""
return self.do_request("PUT", self.network_path % (network), body=body)
@api_call
@ApiCall
def delete_network(self, network):
"""
Deletes the specified network
"""
return self.do_request("DELETE", self.network_path % (network))
@api_call
@ApiCall
def list_ports(self, network):
"""
Fetches a list of ports on a given network
"""
return self.do_request("GET", self.ports_path % (network))
@api_call
@ApiCall
def show_port_details(self, network, port):
"""
Fetches the details of a certain port
"""
return self.do_request("GET", self.port_path % (network, port))
@api_call
@ApiCall
def create_port(self, network, body=None):
"""
Creates a new port on a given network
@ -250,14 +278,14 @@ class Client(object):
body = self.serialize(body)
return self.do_request("POST", self.ports_path % (network), body=body)
@api_call
@ApiCall
def delete_port(self, network, port):
"""
Deletes the specified port from a network
"""
return self.do_request("DELETE", self.port_path % (network, port))
@api_call
@ApiCall
def set_port_state(self, network, port, body=None):
"""
Sets the state of the specified port
@ -265,14 +293,14 @@ class Client(object):
return self.do_request("PUT",
self.port_path % (network, port), body=body)
@api_call
@ApiCall
def show_port_attachment(self, network, port):
"""
Fetches the attachment-id associated with the specified port
"""
return self.do_request("GET", self.attachment_path % (network, port))
@api_call
@ApiCall
def attach_resource(self, network, port, body=None):
"""
Sets the attachment-id of the specified port
@ -280,7 +308,7 @@ class Client(object):
return self.do_request("PUT",
self.attachment_path % (network, port), body=body)
@api_call
@ApiCall
def detach_resource(self, network, port):
"""
Removes the attachment-id of the specified port

View File

@ -111,6 +111,10 @@ class AlreadyAttached(QuantumException):
"already plugged into port %(att_port_id)s")
class AttachmentNotReady(QuantumException):
message = _("The attachment %(att_id)s is not ready")
class NetworkNameExists(QuantumException):
message = _("Unable to set network name to %(net_name). " \
"Network with id %(net_id) already has this name for " \

View File

@ -226,9 +226,22 @@ class ExtensionMiddleware(wsgi.Middleware):
for resource in self.ext_mgr.get_resources():
LOG.debug(_('Extended resource: %s'),
resource.collection)
for action, method in resource.collection_actions.iteritems():
path_prefix = ""
parent = resource.parent
conditions = dict(method=[method])
path = "/%s/%s" % (resource.collection, action)
if parent:
path_prefix = "/%s/{%s_id}" % (parent["collection_name"],
parent["member_name"])
with mapper.submapper(controller=resource.controller,
action=action,
path_prefix=path_prefix,
conditions=conditions) as submap:
submap.connect(path)
submap.connect("%s.:(format)" % path)
mapper.resource(resource.collection, resource.collection,
controller=resource.controller,
collection=resource.collection_actions,
member=resource.member_actions,
parent_resource=resource.parent)

View File

@ -134,7 +134,8 @@ nexus_ip_address=10.0.0.1
# Use shortened interface syntax, e.g. "1/10" not "Ethernet1/10".
nexus_first_port=1/10
nexus_second_port=1/11
#Port number where the SSH will be running at Nexus Switch, e.g.: 22 (Default)
#Port number where SSH will be running on the Nexus switch. Typically this is 22
#unless you've configured your switch otherwise.
nexus_ssh_port=22
[DRIVER]
@ -153,8 +154,15 @@ name=quantum.plugins.cisco.nexus.cisco_nexus_network_driver.CiscoNEXUSDriver
mysql -u<mysqlusername> -p<mysqlpassword> -e "create database quantum_l2network"
5b. Enter the quantum_l2netowrk database configuration info in the
5b. Enter the quantum_l2network database configuration info in the
quantum/plugins/cisco/conf/db_conn.ini file.
5c. If there is a change in the plugin configuration, service would need
to be restarted after dropping and re-creating the database using
the following commands -
mysql -u<mysqlusername> -p<mysqlpassword> -e "drop database quantum_l2network"
mysql -u<mysqlusername> -p<mysqlpassword> -e "create database quantum_l2network"
6. Verify that you have the correct credentials for each IP address listed
in quantum/plugins/cisco/conf/credentials.ini. Example:
@ -229,7 +237,8 @@ result the quantum/plugins/cisco/run_tests.py script.
Set the environment variable PLUGIN_DIR to the location of the plugin
directory. This is manadatory if the run_tests.sh script is used.
export PLUGIN_DIR=quantum/plugins/cisco
In bash : export PLUGIN_DIR=quantum/plugins/cisco
tcsh/csh : setenv PLUGIN_DIR quantum/plugins/cisco
./run_tests.sh quantum.plugins.cisco.tests.unit.test_l2networkApi
or
@ -240,7 +249,8 @@ result the quantum/plugins/cisco/run_tests.py script.
2. Specific Plugin unit test (needs environment setup as indicated in the
pre-requisites):
export PLUGIN_DIR=quantum/plugins/cisco
In bash : export PLUGIN_DIR=quantum/plugins/cisco
tcsh/csh : setenv PLUGIN_DIR quantum/plugins/cisco
./run_tests.sh quantum.plugins.cisco.tests.unit.<name_of_the file>
or
@ -254,7 +264,9 @@ result the quantum/plugins/cisco/run_tests.py script.
3. All unit tests (needs environment setup as indicated in the pre-requisites):
export PLUGIN_DIR=quantum/plugins/cisco
In bash : export PLUGIN_DIR=quantum/plugins/cisco
tcsh/csh : setenv PLUGIN_DIR quantum/plugins/cisco
./run_tests.sh quantum.plugins.cisco.tests.unit
or
@ -266,6 +278,13 @@ result the quantum/plugins/cisco/run_tests.py script.
change later.
Location quantum/plugins/cisco/tests/unit/test_cisco_extension.py
The script can be executed by :
./run_tests.sh quantum.plugins.cisco.tests.unit.test_cisco_extension
or
python run_tests.py quantum.plugins.cisco.tests.unit.test_cisco_extension
Bingo bango bongo! That's it! Thanks for taking the leap into Quantum.
...Oh, boy!

View File

@ -22,8 +22,8 @@
import logging as LOG
import os
from quantum.plugins.cisco.common import cisco_constants as const
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

View File

@ -1,4 +1,3 @@
"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
@ -17,7 +16,7 @@
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
# @author: Rohit Agarwalla, Cisco Systems, Inc.
"""
"""
Exceptions used by the Cisco plugin
"""
@ -86,18 +85,18 @@ class VlanIDNotFound(exceptions.QuantumException):
class VlanIDNotAvailable(exceptions.QuantumException):
"""VLAN ID is reserved"""
message = _("No available Vlan ID found")
"""No VLAN ID available"""
message = _("No Vlan ID available")
class QosNotFound(exceptions.QuantumException):
"""QoS ID could not be found"""
"""QoS level with this ID cannot be found"""
message = _("QoS level %(qos_id)s could not be found " \
"for tenant %(tenant_id)s")
class QoSLevelInvalidDelete(exceptions.QuantumException):
"""QoS ID could not be deleted"""
"""QoS is associated with a port profile, hence cannot be deleted"""
message = _("QoS level %(qos_id)s could not be deleted " \
"for tenant %(tenant_id)s since association exists")
@ -109,7 +108,7 @@ class QosNameAlreadyExists(exceptions.QuantumException):
class CredentialNotFound(exceptions.QuantumException):
"""Credential ID could not be found"""
"""Credential with this ID cannot be found"""
message = _("Credential %(credential_id)s could not be found " \
"for tenant %(tenant_id)s")

View File

@ -20,7 +20,6 @@
"""
import webob.dec
from quantum.api import api_common as common
from quantum.common import wsgi
@ -30,12 +29,7 @@ class Fault(webob.exc.HTTPException):
_fault_names = {
400: "malformedRequest",
401: "unauthorized",
420: "networkNotFound",
421: "PortprofileInUse",
430: "portNotFound",
431: "requestedStateInvalid",
432: "portInUse",
440: "alreadyAttached",
450: "PortprofileNotFound",
451: "CredentialNotFound",
452: "QoSNotFound",
@ -49,21 +43,19 @@ class Fault(webob.exc.HTTPException):
@webob.dec.wsgify(RequestClass=wsgi.Request)
def __call__(self, req):
"""Generate a WSGI response based on the exception passed to ctor."""
"""Generate a WSGI response based on the
exception passed to constructor."""
# Replace the body with fault details.
code = self.wrapped_exc.status_int
fault_name = self._fault_names.get(code, "quantumServiceFault")
fault_data = {
fault_name: {
'code': code,
'message': self.wrapped_exc.explanation,
'detail': self.wrapped_exc.detail}}
'message': self.wrapped_exc.explanation}}
# 'code' is an attribute on the fault tag itself
metadata = {'application/xml': {'attributes': {fault_name: 'code'}}}
default_xmlns = common.XML_NS_V10
serializer = wsgi.Serializer(metadata, default_xmlns)
content_type = req.best_match_content_type()
#self.wrapped_exc.body = serializer.serialize(fault_data, content_type)
self.wrapped_exc.body = wsgi.Serializer().\
serialize(fault_data, content_type)
self.wrapped_exc.content_type = content_type
return self.wrapped_exc
@ -79,7 +71,7 @@ class PortprofileNotFound(webob.exc.HTTPClientError):
"""
code = 450
title = 'Portprofile Not Found'
explanation = ('Unable to find a Portprofile with'
explanation = ('Unable to find a Portprofile with'
+ ' the specified identifier.')
@ -95,8 +87,8 @@ class PortNotFound(webob.exc.HTTPClientError):
code = 430
title = 'Port not Found'
explanation = ('Unable to find a port with the specified identifier.')
class CredentialNotFound(webob.exc.HTTPClientError):
"""
subclass of :class:`~HTTPClientError`
@ -108,10 +100,10 @@ class CredentialNotFound(webob.exc.HTTPClientError):
"""
code = 451
title = 'Credential Not Found'
explanation = ('Unable to find a Credential with'
explanation = ('Unable to find a Credential with'
+ ' the specified identifier.')
class QosNotFound(webob.exc.HTTPClientError):
"""
subclass of :class:`~HTTPClientError`
@ -123,10 +115,10 @@ class QosNotFound(webob.exc.HTTPClientError):
"""
code = 452
title = 'QoS Not Found'
explanation = ('Unable to find a QoS with'
explanation = ('Unable to find a QoS with'
+ ' the specified identifier.')
class NovatenantNotFound(webob.exc.HTTPClientError):
"""
subclass of :class:`~HTTPClientError`
@ -138,7 +130,7 @@ class NovatenantNotFound(webob.exc.HTTPClientError):
"""
code = 453
title = 'Nova tenant Not Found'
explanation = ('Unable to find a Novatenant with'
explanation = ('Unable to find a Novatenant with'
+ ' the specified identifier.')

View File

@ -12,7 +12,7 @@ bind_host = 0.0.0.0
bind_port = 9696
# Path to the extensions
api_extensions_path = ../extensions
api_extensions_path = ../../../../extensions
[pipeline:extensions_app_with_filter]
pipeline = extensions extensions_test_app
@ -21,4 +21,4 @@ pipeline = extensions extensions_test_app
paste.filter_factory = quantum.common.extensions:plugin_aware_extension_middleware_factory
[app:extensions_test_app]
paste.app_factory = tests.unit.test_cisco_extension:app_factory
paste.app_factory = quantum.plugins.cisco.tests.unit.test_cisco_extension:app_factory

View File

@ -20,8 +20,8 @@ from sqlalchemy.orm import exc
from quantum.common import exceptions as q_exc
from quantum.plugins.cisco import l2network_plugin_configuration as conf
from quantum.plugins.cisco.common import cisco_exceptions as c_exc
from quantum.plugins.cisco.db import l2network_models
import l2network_models
import logging as LOG
import quantum.plugins.cisco.db.api as db
import quantum.plugins.cisco.db.nexus_db as ndb
@ -117,17 +117,16 @@ def reserve_vlanid():
LOG.debug("reserve_vlanid() called")
session = db.get_session()
try:
vlanids = session.query(l2network_models.VlanID).\
rvlan = session.query(l2network_models.VlanID).\
filter_by(vlan_used=False).\
all()
rvlan = vlanids[0]
first()
rvlanid = session.query(l2network_models.VlanID).\
filter_by(vlan_id=rvlan["vlan_id"]).\
one()
rvlanid["vlan_used"] = True
session.merge(rvlanid)
session.flush()
return vlanids[0]["vlan_id"]
return rvlan["vlan_id"]
except exc.NoResultFound:
raise c_exc.VlanIDNotAvailable()

View File

@ -185,6 +185,6 @@ class Credential(BASE, L2NetworkBase):
self.password = password
def __repr__(self):
return "<Credentials(%s,%s,%s,%s)>" % \
return "<Credentials(%s,%s,%s,%s,%s)>" % \
(self.credential_id, self.tenant_id, self.credential_name,
self.user_name, self.password)

View File

@ -20,9 +20,9 @@ import logging as LOG
from sqlalchemy.orm import exc
import quantum.plugins.cisco.db.api as db
import nexus_models
from quantum.plugins.cisco.common import cisco_exceptions as c_exc
from quantum.plugins.cisco.db import nexus_models
def get_all_nexusport_bindings():

View File

@ -27,8 +27,6 @@ class NexusPortBinding(BASE, L2NetworkBase):
id = Column(Integer, primary_key=True, autoincrement=True)
port_id = Column(String(255))
#vlan_id = Column(Integer, ForeignKey("vlan_bindings.vlan_id"), \
# nullable=False)
vlan_id = Column(Integer, nullable=False)
def __init__(self, port_id, vlan_id):

View File

@ -26,10 +26,11 @@ import platform
from quantum.common import exceptions as exc
from quantum.common import utils
from quantum.quantum_plugin_base import QuantumPluginBase
from quantum.plugins.cisco import l2network_plugin_configuration as conf
from quantum.plugins.cisco.common import cisco_constants as const
from quantum.plugins.cisco.common import cisco_exceptions as cexc
from quantum.plugins.cisco.common import cisco_credentials as cred
from quantum.plugins.cisco.common import cisco_exceptions as cexc
from quantum.plugins.cisco.common import cisco_utils as cutil
from quantum.plugins.cisco.db import api as db
from quantum.plugins.cisco.db import l2network_db as cdb
@ -441,7 +442,7 @@ class L2Network(QuantumPluginBase):
return credential
def rename_credential(self, tenant_id, credential_id, new_name):
"""Do nothing for this resource"""
"""Rename the particular credential resource"""
LOG.debug("rename_credential() called\n")
try:
credential = cdb.get_credential(tenant_id, credential_id)

View File

@ -29,6 +29,9 @@ CONF_PARSER_OBJ = confp.\
CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \
"/" + CONF_FILE)
"""
Reading the conf for the l2network_plugin
"""
SECTION_CONF = CONF_PARSER_OBJ['VLANS']
VLAN_NAME_PREFIX = SECTION_CONF['vlan_name_prefix']
VLAN_START = SECTION_CONF['vlan_start']
@ -55,6 +58,9 @@ CONF_PARSER_OBJ = confp.\
CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \
"/" + CONF_FILE)
"""
Reading the config for the device plugins
"""
PLUGINS = CONF_PARSER_OBJ.walk(CONF_PARSER_OBJ.dummy)
CONF_FILE = "conf/db_conn.ini"
@ -63,6 +69,9 @@ CONF_PARSER_OBJ = confp.\
CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \
"/" + CONF_FILE)
"""
Reading DB config for the Quantum DB
"""
SECTION_CONF = CONF_PARSER_OBJ['DATABASE']
DB_NAME = SECTION_CONF['name']
DB_USER = SECTION_CONF['user']

View File

@ -49,12 +49,19 @@ class CiscoNEXUSDriver():
username=nexus_user, password=nexus_password)
return man
def create_xml_snippet(self, cutomized_config):
"""
Creates the Proper XML structure for the Nexus Switch Configuration
"""
conf_xml_snippet = snipp.EXEC_CONF_SNIPPET % (cutomized_config)
return conf_xml_snippet
def enable_vlan(self, mgr, vlanid, vlanname):
"""
Creates a VLAN on Nexus Switch given the VLAN ID and Name
"""
confstr = snipp.CMD_VLAN_CONF_SNIPPET % (vlanid, vlanname)
confstr = snipp.EXEC_CONF_PREFIX + confstr + snipp.EXEC_CONF_POSTFIX
confstr = self.create_xml_snippet(confstr)
mgr.edit_config(target='running', config=confstr)
def disable_vlan(self, mgr, vlanid):
@ -62,7 +69,7 @@ class CiscoNEXUSDriver():
Delete a VLAN on Nexus Switch given the VLAN ID
"""
confstr = snipp.CMD_NO_VLAN_CONF_SNIPPET % vlanid
confstr = snipp.EXEC_CONF_PREFIX + confstr + snipp.EXEC_CONF_POSTFIX
confstr = self.create_xml_snippet(confstr)
mgr.edit_config(target='running', config=confstr)
def enable_port_trunk(self, mgr, interface):
@ -70,7 +77,7 @@ class CiscoNEXUSDriver():
Enables trunk mode an interface on Nexus Switch
"""
confstr = snipp.CMD_PORT_TRUNK % (interface)
confstr = snipp.EXEC_CONF_PREFIX + confstr + snipp.EXEC_CONF_POSTFIX
confstr = self.create_xml_snippet(confstr)
LOG.debug("NexusDriver: %s" % confstr)
mgr.edit_config(target='running', config=confstr)
@ -79,7 +86,7 @@ class CiscoNEXUSDriver():
Disables trunk mode an interface on Nexus Switch
"""
confstr = snipp.CMD_NO_SWITCHPORT % (interface)
confstr = snipp.EXEC_CONF_PREFIX + confstr + snipp.EXEC_CONF_POSTFIX
confstr = self.create_xml_snippet(confstr)
LOG.debug("NexusDriver: %s" % confstr)
mgr.edit_config(target='running', config=confstr)
@ -89,7 +96,7 @@ class CiscoNEXUSDriver():
VLANID
"""
confstr = snipp.CMD_VLAN_INT_SNIPPET % (interface, vlanid)
confstr = snipp.EXEC_CONF_PREFIX + confstr + snipp.EXEC_CONF_POSTFIX
confstr = self.create_xml_snippet(confstr)
LOG.debug("NexusDriver: %s" % confstr)
mgr.edit_config(target='running', config=confstr)
@ -99,7 +106,7 @@ class CiscoNEXUSDriver():
VLANID
"""
confstr = snipp.CMD_NO_VLAN_INT_SNIPPET % (interface, vlanid)
confstr = snipp.EXEC_CONF_PREFIX + confstr + snipp.EXEC_CONF_POSTFIX
confstr = self.create_xml_snippet(confstr)
LOG.debug("NexusDriver: %s" % confstr)
mgr.edit_config(target='running', config=confstr)

View File

@ -29,14 +29,10 @@ LOG.getLogger(const.LOGGER_COMPONENT_NAME)
# The following are standard strings, messages used to communicate with Nexus,
EXEC_CONF_PREFIX = """
EXEC_CONF_SNIPPET = """
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<configure xmlns="http://www.cisco.com/nxos:1.0:vlan_mgr_cli">
<__XML__MODE__exec_configure>
"""
EXEC_CONF_POSTFIX = """
<__XML__MODE__exec_configure>%s
</__XML__MODE__exec_configure>
</configure>
</config>
@ -156,4 +152,5 @@ FILTER_SHOW_VLAN_BRIEF_SNIPPET = """
<vlan>
<brief/>
</vlan>
</show> """
</show>
"""

View File

View File

@ -0,0 +1,96 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, 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: Sumit Naiksatam, Cisco Systems, Inc.
#
from nova import exception as excp
from nova import flags
from nova import log as logging
from nova.scheduler import driver
from quantum.client import Client
from quantum.common.wsgi import Serializer
LOG = logging.getLogger('quantum.plugins.cisco.nova.quantum_aware_scheduler')
FLAGS = flags.FLAGS
flags.DEFINE_string('quantum_host', "127.0.0.1",
'IP address of the quantum network service.')
flags.DEFINE_integer('quantum_port', 9696,
'Listening port for Quantum network service')
HOST = FLAGS.quantum_host
PORT = FLAGS.quantum_port
USE_SSL = False
ACTION_PREFIX_EXT = '/v0.1'
ACTION_PREFIX_CSCO = ACTION_PREFIX_EXT + \
'/extensions/csco/tenants/{tenant_id}'
TENANT_ID = 'nova'
CSCO_EXT_NAME = 'Cisco Nova Tenant'
class QuantumScheduler(driver.Scheduler):
"""
Quantum network service dependent scheduler
Obtains the hostname from Quantum using an extension API
"""
def __init__(self):
# We have to send a dummy tenant name here since the client
# needs some tenant name, but the tenant name will not be used
# since the extensions URL does not require it
client = Client(HOST, PORT, USE_SSL, format='json',
action_prefix=ACTION_PREFIX_EXT, tenant="dummy")
request_url = "/extensions"
data = client.do_request('GET', request_url)
LOG.debug("Obtained supported extensions from Quantum: %s" % data)
for ext in data['extensions']:
name = ext['name']
if name == CSCO_EXT_NAME:
LOG.debug("Quantum plugin supports required \"%s\" extension"
"for the scheduler." % name)
return
LOG.error("Quantum plugin does not support required \"%s\" extension"
" for the scheduler. Scheduler will quit." % CSCO_EXT_NAME)
raise excp.ServiceUnavailable()
def schedule(self, context, topic, *args, **kwargs):
"""Gets the host name from the Quantum service"""
instance_id = kwargs['instance_id']
user_id = \
kwargs['request_spec']['instance_properties']['user_id']
project_id = \
kwargs['request_spec']['instance_properties']['project_id']
instance_data_dict = \
{'novatenant': \
{'instance_id': instance_id,
'instance_desc': \
{'user_id': user_id,
'project_id': project_id}}}
client = Client(HOST, PORT, USE_SSL, format='json', tenant=TENANT_ID,
action_prefix=ACTION_PREFIX_CSCO)
request_url = "/novatenants/" + project_id + "/get_host"
data = client.do_request('PUT', request_url, body=instance_data_dict)
hostname = data["host_list"]["host_1"]
if not hostname:
raise driver.NoValidHost(_("Scheduler was unable to locate a host"
" for this request. Is the appropriate"
" service running?"))
LOG.debug(_("Quantum service returned host: %s") % hostname)
return hostname

View File

@ -0,0 +1,112 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 Cisco Systems, 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: Sumit Naiksatam, Cisco Systems, Inc.
#
"""VIF drivers for interface type direct."""
from nova import exception as excp
from nova import flags
from nova import log as logging
from nova.network import linux_net
from nova.virt.libvirt import netutils
from nova import utils
from nova.virt.vif import VIFDriver
from quantum.client import Client
from quantum.common.wsgi import Serializer
LOG = logging.getLogger('quantum.plugins.cisco.nova.vifdirect')
FLAGS = flags.FLAGS
flags.DEFINE_string('quantum_host', "127.0.0.1",
'IP address of the quantum network service.')
flags.DEFINE_integer('quantum_port', 9696,
'Listening port for Quantum network service')
HOST = FLAGS.quantum_host
PORT = FLAGS.quantum_port
USE_SSL = False
TENANT_ID = 'nova'
ACTION_PREFIX_EXT = '/v0.1'
ACTION_PREFIX_CSCO = ACTION_PREFIX_EXT + \
'/extensions/csco/tenants/{tenant_id}'
TENANT_ID = 'nova'
CSCO_EXT_NAME = 'Cisco Nova Tenant'
class Libvirt802dot1QbhDriver(VIFDriver):
"""VIF driver for Linux bridge."""
def __init__(self):
# We have to send a dummy tenant name here since the client
# needs some tenant name, but the tenant name will not be used
# since the extensions URL does not require it
client = Client(HOST, PORT, USE_SSL, format='json',
action_prefix=ACTION_PREFIX_EXT, tenant="dummy")
request_url = "/extensions"
data = client.do_request('GET', request_url)
LOG.debug("Obtained supported extensions from Quantum: %s" % data)
for ext in data['extensions']:
name = ext['name']
if name == CSCO_EXT_NAME:
LOG.debug("Quantum plugin supports required \"%s\" extension"
"for the VIF driver." % name)
return
LOG.error("Quantum plugin does not support required \"%s\" extension"
" for the VIF driver. nova-compute will quit." \
% CSCO_EXT_NAME)
raise excp.ServiceUnavailable()
def _get_configurations(self, instance, network, mapping):
"""Gets the device name and the profile name from Quantum"""
instance_id = instance['id']
user_id = instance['user_id']
project_id = instance['project_id']
vif_id = mapping['vif_uuid']
instance_data_dict = \
{'novatenant': \
{'instance_id': instance_id,
'instance_desc': \
{'user_id': user_id,
'project_id': project_id,
'vif_id': vif_id}}}
client = Client(HOST, PORT, USE_SSL, format='json', tenant=TENANT_ID,
action_prefix=ACTION_PREFIX_CSCO)
request_url = "/novatenants/" + project_id + "/get_instance_port"
data = client.do_request('PUT', request_url, body=instance_data_dict)
device = data['vif_desc']['device']
portprofile = data['vif_desc']['portprofile']
LOG.debug(_("Quantum provided the device: %s") % device)
LOG.debug(_("Quantum provided the portprofile: %s") % portprofile)
mac_id = mapping['mac'].replace(':', '')
result = {
'id': mac_id,
'mac_address': mapping['mac'],
'device_name': device,
'profile_name': portprofile,
}
return result
def plug(self, instance, network, mapping):
return self._get_configurations(instance, network, mapping)
def unplug(self, instance, network, mapping):
pass

View File

@ -17,12 +17,12 @@
# @authors: Shweta Padubidri, Cisco Systems, Inc.
# Peter Strunk , Cisco Systems, Inc.
# Shubhangi Satras , Cisco Systems, Inc.
import json
import os.path
import routes
import unittest
import logging
import webob
import json
import os.path
import routes
from webtest import TestApp
from extensions import credential
from extensions import portprofile
@ -41,9 +41,9 @@ from quantum.manager import QuantumManager
from quantum.plugins.cisco import l2network_plugin
TEST_CONF_FILE = os.path.join(os.path.dirname(__file__), os.pardir,
os.pardir, 'etc', 'quantum.conf.ciscoext')
EXTENSIONS_PATH = os.path.join(os.path.dirname(__file__), os.pardir,
os.pardir, "extensions")
os.pardir, 'conf', 'quantum.conf.ciscoext')
EXTENSIONS_PATH = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
os.pardir, os.pardir, os.pardir, "extensions")
LOG = logging.getLogger('quantum.plugins.cisco.tests.test_cisco_extensions')
@ -62,10 +62,13 @@ class ExtensionsTestApp(wsgi.Router):
class PortprofileExtensionTest(unittest.TestCase):
def setUp(self):
""" Set up function """
parent_resource = dict(member_name="tenant",
collection_name="extensions/csco/tenants")
member_actions = {'associate_portprofile': "PUT",
'disassociate_portprofile': "POST"}
'disassociate_portprofile': "PUT"}
controller = portprofile.PortprofilesController(
QuantumManager.get_plugin())
res_ext = extensions.ResourceExtension('portprofiles', controller,
@ -89,6 +92,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def test_list_portprofile(self):
""" Test List Portprofile"""
LOG.debug("test_list_portprofile - START")
req_body1 = json.dumps(self.test_port_profile)
create_response1 = self.test_app.post(
@ -121,6 +126,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def test_create_portprofile(self):
""" Test create Portprofile"""
LOG.debug("test_create_portprofile - START")
req_body = json.dumps(self.test_port_profile)
index_response = self.test_app.post(self.profile_path, req_body,
@ -138,6 +145,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def test_create_portprofileBADRequest(self):
""" Test create Portprofile Bad Request"""
LOG.debug("test_create_portprofileBADRequest - START")
index_response = self.test_app.post(self.profile_path, 'BAD_REQUEST',
content_type=self.contenttype,
@ -147,6 +156,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def test_show_portprofile(self):
""" Test show Portprofile """
LOG.debug("test_show_portprofile - START")
req_body = json.dumps(self.test_port_profile)
index_response = self.test_app.post(self.profile_path, req_body,
@ -165,6 +176,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def test_show_portprofileDNE(self, portprofile_id='100'):
""" Test show Portprofile does not exist"""
LOG.debug("test_show_portprofileDNE - START")
show_path_temp = self.portprofile_path + portprofile_id
show_port_path = str(show_path_temp)
@ -174,6 +187,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def test_update_portprofile(self):
""" Test update Portprofile"""
LOG.debug("test_update_portprofile - START")
req_body = json.dumps(self.test_port_profile)
index_response = self.test_app.post(
@ -191,12 +206,14 @@ class PortprofileExtensionTest(unittest.TestCase):
rename_response = self.test_app.put(rename_path, rename_req_body)
self.assertEqual(200, rename_response.status_int)
# Clean Up - Delete the Port Profile
# Clean Up - Delete the Port Profile
self.tear_down_profile(rename_path)
LOG.debug("test_update_portprofile - END")
def test_update_portprofileBADRequest(self):
""" Test update Portprofile Bad Request"""
LOG.debug("test_update_portprofileBADRequest - START")
req_body = json.dumps(self.test_port_profile)
index_response = self.test_app.post(
@ -217,6 +234,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def test_update_portprofileDNE(self, portprofile_id='100'):
""" Test update Portprofile does not exist"""
LOG.debug("test_update_portprofileiDNE - START")
rename_port_profile = {'portprofile':
{'portprofile_name': 'cisco_rename_portprofile',
@ -231,6 +250,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def test_delete_portprofile(self):
""" Test delete Portprofile"""
LOG.debug("test_delete_portprofile - START")
req_body = json.dumps(self.test_port_profile)
index_response = self.test_app.post(
@ -248,6 +269,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def test_delete_portprofileDNE(self, portprofile_id='100'):
""" Test delete Portprofile does not exist"""
LOG.debug("test_delete_portprofileDNE - START")
delete_path_temp = self.portprofile_path + portprofile_id
delete_path = str(delete_path_temp)
@ -257,6 +280,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def create_request(self, path, body, content_type, method='GET'):
""" Test create request"""
LOG.debug("test_create_request - START")
req = webob.Request.blank(path)
req.method = method
@ -268,6 +293,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def _create_network(self, name=None):
""" Test create network"""
LOG.debug("Creating network - START")
if name:
net_name = name
@ -286,6 +313,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def _create_port(self, network_id, port_state):
""" Test create port"""
LOG.debug("Creating port for network %s - START", network_id)
port_path = "/tenants/tt/networks/%s/ports" % network_id
port_req_data = {'port': {'port-state': '%s' % port_state}}
@ -301,6 +330,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def test_associate_portprofile(self):
""" Test associate portprofile"""
LOG.debug("test_associate_portprofile - START")
net_id = self._create_network()
port_id = self._create_port(net_id, "ACTIVE")
@ -336,6 +367,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def test_associate_portprofileDNE(self, portprofile_id='100'):
""" Test associate portprofile does not exist"""
LOG.debug("test_associate_portprofileDNE - START")
test_port_assign_data = {'portprofile': {'network-id': '001',
'port-id': '1'}}
@ -350,6 +383,8 @@ class PortprofileExtensionTest(unittest.TestCase):
def test_disassociate_portprofile(self):
""" Test disassociate portprofile"""
LOG.debug("test_disassociate_portprofile - START")
net_id = self._create_network()
port_id = self._create_port(net_id, "ACTIVE")
@ -375,7 +410,7 @@ class PortprofileExtensionTest(unittest.TestCase):
"/disassociate_portprofile"
disassociate_path = str(disassociate_path_temp)
disassociate_response = self.test_app.post(
disassociate_response = self.test_app.put(
disassociate_path, req_assign_body,
content_type=self.contenttype)
self.assertEqual(202, disassociate_response.status_int)
@ -388,21 +423,33 @@ class PortprofileExtensionTest(unittest.TestCase):
LOG.debug("test_disassociate_portprofile - END")
def tear_down_profile(self, delete_profile_path):
""" Tear down profile"""
self.test_app.delete(delete_profile_path)
def tear_down_associate_profile(self, delete_profile_path,
dissociate_profile_path, req_body):
self.test_app.post(dissociate_profile_path, req_body,
""" Tear down associate profile"""
self.test_app.put(dissociate_profile_path, req_body,
content_type=self.contenttype)
self.tear_down_profile(delete_profile_path)
def tearDown(self):
""" Tear down """
db.clear_db()
class NovatenantExtensionTest(unittest.TestCase):
def setUp(self):
""" Set up function"""
parent_resource = dict(member_name="tenant",
collection_name="extensions/csco/tenants")
member_actions = {'schedule_host': "PUT",
@ -416,44 +463,49 @@ class NovatenantExtensionTest(unittest.TestCase):
SimpleExtensionManager(res_ext))
self.contenttype = 'application/json'
self.novatenants_path = '/extensions/csco/tenants/tt/novatenants/'
self.test_instance_data = {'novatenant': {'instance_id': 1,
self.test_associate_data = {'novatenant': {'instance_id': 1,
'instance_desc': {'key1': '1',
'key2': '2'}}}
def test_schedule_host(self):
""" Test get host"""
LOG.debug("test_schedule_host - START")
req_body = json.dumps(self.test_instance_data)
req_body = json.dumps(self.test_associate_data)
host_path = self.novatenants_path + "001/schedule_host"
host_response = self.test_app.put(
host_path, req_body,
content_type=self.contenttype)
host_path, req_body,
content_type=self.contenttype)
self.assertEqual(200, host_response.status_int)
LOG.debug("test_schedule_host - END")
def test_schedule_hostBADRequest(self):
""" Test get host bad request"""
LOG.debug("test_schedule_hostBADRequest - START")
host_path = self.novatenants_path + "001/schedule_host"
host_response = self.test_app.put(
host_path, 'BAD_REQUEST',
content_type=self.contenttype, status='*')
host_path, 'BAD_REQUEST',
content_type=self.contenttype, status='*')
self.assertEqual(400, host_response.status_int)
LOG.debug("test_schedule_hostBADRequest - END")
def test_instance_port(self):
LOG.debug("test_instance_port - START")
req_body = json.dumps(self.test_instance_data)
instance_port_path = self.novatenants_path + "001/associate_port"
instance_port_response = self.test_app.put(
instance_port_path, req_body,
def test_associate_port(self):
""" Test get associate port """
LOG.debug("test_associate_port - START")
req_body = json.dumps(self.test_associate_data)
associate_port_path = self.novatenants_path + "001/associate_port"
associate_port_response = self.test_app.put(
associate_port_path, req_body,
content_type=self.contenttype)
self.assertEqual(200, instance_port_response.status_int)
LOG.debug("test_instance_port - END")
self.assertEqual(200, associate_port_response.status_int)
LOG.debug("test_associate_port - END")
class QosExtensionTest(unittest.TestCase):
def setUp(self):
""" Set up function """
parent_resource = dict(member_name="tenant",
collection_name="extensions/csco/tenants")
controller = qos.QosController(QuantumManager.get_plugin())
@ -470,6 +522,8 @@ class QosExtensionTest(unittest.TestCase):
def test_create_qos(self):
""" Test create qos """
LOG.debug("test_create_qos - START")
req_body = json.dumps(self.test_qos_data)
index_response = self.test_app.post(self.qos_path,
@ -488,6 +542,8 @@ class QosExtensionTest(unittest.TestCase):
def test_create_qosBADRequest(self):
""" Test create qos bad request """
LOG.debug("test_create_qosBADRequest - START")
index_response = self.test_app.post(self.qos_path,
'BAD_REQUEST',
@ -497,6 +553,9 @@ class QosExtensionTest(unittest.TestCase):
LOG.debug("test_create_qosBADRequest - END")
def test_list_qoss(self):
""" Test list qoss """
LOG.debug("test_list_qoss - START")
req_body1 = json.dumps(self.test_qos_data)
create_resp1 = self.test_app.post(self.qos_path, req_body1,
@ -524,6 +583,9 @@ class QosExtensionTest(unittest.TestCase):
LOG.debug("test_list_qoss - END")
def test_show_qos(self):
""" Test show qos """
LOG.debug("test_show_qos - START")
req_body = json.dumps(self.test_qos_data)
index_response = self.test_app.post(self.qos_path, req_body,
@ -541,6 +603,9 @@ class QosExtensionTest(unittest.TestCase):
LOG.debug("test_show_qos - END")
def test_show_qosDNE(self, qos_id='100'):
""" Test show qos does not exist"""
LOG.debug("test_show_qosDNE - START")
show_path_temp = self.qos_second_path + qos_id
show_qos_path = str(show_path_temp)
@ -550,6 +615,8 @@ class QosExtensionTest(unittest.TestCase):
def test_update_qos(self):
""" Test update qos """
LOG.debug("test_update_qos - START")
req_body = json.dumps(self.test_qos_data)
index_response = self.test_app.post(self.qos_path, req_body,
@ -567,6 +634,9 @@ class QosExtensionTest(unittest.TestCase):
LOG.debug("test_update_qos - END")
def test_update_qosDNE(self, qos_id='100'):
""" Test update qos does not exist """
LOG.debug("test_update_qosDNE - START")
rename_req_body = json.dumps({'qos': {'qos_name': 'cisco_rename_qos',
'qos_desc': {'PPS': 50, 'TTL': 5}}})
@ -578,6 +648,9 @@ class QosExtensionTest(unittest.TestCase):
LOG.debug("test_update_qosDNE - END")
def test_update_qosBADRequest(self):
""" Test update qos bad request """
LOG.debug("test_update_qosBADRequest - START")
req_body = json.dumps(self.test_qos_data)
index_response = self.test_app.post(self.qos_path, req_body,
@ -597,6 +670,8 @@ class QosExtensionTest(unittest.TestCase):
def test_delete_qos(self):
""" Test delte qos """
LOG.debug("test_delete_qos - START")
req_body = json.dumps({'qos': {'qos_name': 'cisco_test_qos',
'qos_desc': {'PPS': 50, 'TTL': 5}}})
@ -612,6 +687,9 @@ class QosExtensionTest(unittest.TestCase):
LOG.debug("test_delete_qos - END")
def test_delete_qosDNE(self, qos_id='100'):
""" Test delte qos does not exist"""
LOG.debug("test_delete_qosDNE - START")
delete_path_temp = self.qos_second_path + qos_id
delete_path = str(delete_path_temp)
@ -620,12 +698,18 @@ class QosExtensionTest(unittest.TestCase):
LOG.debug("test_delete_qosDNE - END")
def tearDownQos(self, delete_profile_path):
""" Tear Down Qos """
self.test_app.delete(delete_profile_path)
class CredentialExtensionTest(unittest.TestCase):
def setUp(self):
""" Set up function """
parent_resource = dict(member_name="tenant",
collection_name="extensions/csco/tenants")
controller = credential.CredentialController(
@ -643,6 +727,9 @@ class CredentialExtensionTest(unittest.TestCase):
'password': 'newPasswd1'}}
def test_list_credentials(self):
""" Test list credentials """
#Create Credential before listing
LOG.debug("test_list_credentials - START")
req_body1 = json.dumps(self.test_credential_data)
@ -675,6 +762,9 @@ class CredentialExtensionTest(unittest.TestCase):
LOG.debug("test_list_credentials - END")
def test_create_credential(self):
""" Test create credential """
LOG.debug("test_create_credential - START")
req_body = json.dumps(self.test_credential_data)
index_response = self.test_app.post(
@ -691,6 +781,9 @@ class CredentialExtensionTest(unittest.TestCase):
LOG.debug("test_create_credential - END")
def test_create_credentialBADRequest(self):
""" Test create credential bad request """
LOG.debug("test_create_credentialBADRequest - START")
index_response = self.test_app.post(
self.credential_path, 'BAD_REQUEST',
@ -699,6 +792,9 @@ class CredentialExtensionTest(unittest.TestCase):
LOG.debug("test_create_credentialBADRequest - END")
def test_show_credential(self):
""" Test show credential """
LOG.debug("test_show_credential - START")
req_body = json.dumps(self.test_credential_data)
index_response = self.test_app.post(
@ -714,6 +810,9 @@ class CredentialExtensionTest(unittest.TestCase):
LOG.debug("test_show_credential - END")
def test_show_credentialDNE(self, credential_id='100'):
""" Test show credential does not exist """
LOG.debug("test_show_credentialDNE - START")
show_path_temp = self.cred_second_path + credential_id
show_cred_path = str(show_path_temp)
@ -722,6 +821,9 @@ class CredentialExtensionTest(unittest.TestCase):
LOG.debug("test_show_credentialDNE - END")
def test_update_credential(self):
""" Test update credential """
LOG.debug("test_update_credential - START")
req_body = json.dumps(self.test_credential_data)
@ -744,6 +846,9 @@ class CredentialExtensionTest(unittest.TestCase):
LOG.debug("test_update_credential - END")
def test_update_credBADReq(self):
""" Test update credential bad request """
LOG.debug("test_update_credBADReq - START")
req_body = json.dumps(self.test_credential_data)
index_response = self.test_app.post(
@ -760,6 +865,9 @@ class CredentialExtensionTest(unittest.TestCase):
LOG.debug("test_update_credBADReq - END")
def test_update_credentialDNE(self, credential_id='100'):
""" Test update credential does not exist"""
LOG.debug("test_update_credentialDNE - START")
rename_req_body = json.dumps({'credential':
{'credential_name': 'cred3',
@ -773,6 +881,9 @@ class CredentialExtensionTest(unittest.TestCase):
LOG.debug("test_update_credentialDNE - END")
def test_delete_credential(self):
""" Test delete credential """
LOG.debug("test_delete_credential - START")
req_body = json.dumps(self.test_credential_data)
index_response = self.test_app.post(
@ -788,6 +899,9 @@ class CredentialExtensionTest(unittest.TestCase):
LOG.debug("test_delete_credential - END")
def test_delete_credentialDNE(self, credential_id='100'):
""" Test delete credential does not exist """
LOG.debug("test_delete_credentialDNE - START")
delete_path_temp = self.cred_second_path + credential_id
delete_path = str(delete_path_temp)

View File

@ -19,13 +19,11 @@
import logging
import unittest
#import time
from quantum.common import exceptions as exc
from quantum.plugins.cisco.common import cisco_constants as const
from quantum.plugins.cisco.common import cisco_exceptions as cexc
from quantum.plugins.cisco import l2network_plugin
from quantum.plugins.cisco import l2network_plugin_configuration as conf
#from quantum.plugins.cisco.common import cisco_utils as utils
from quantum.plugins.cisco.db import api as db
from quantum.plugins.cisco.db import l2network_db as cdb
@ -72,7 +70,6 @@ class CoreAPITestFunc(unittest.TestCase):
tenant_id, new_net_dict[const.NET_ID])
self.assertRaises(exc.NetworkNotFound, db.network_get,
new_net_dict[const.NET_ID])
#self.assertEqual(net, None)
self.assertEqual(
new_net_dict[const.NET_ID], delete_net_dict[const.NET_ID])
LOG.debug("test_delete_network - END")
@ -303,11 +300,6 @@ class CoreAPITestFunc(unittest.TestCase):
port_dict[const.PORT_ID])
self.assertRaises(exc.PortNotFound, db.port_get,
new_net_dict[const.NET_ID], port_dict[const.PORT_ID])
#self.assertEqual(port, None)
# self.assertEqual(delete_port_dict[const.PORT_STATE], port_state)
# self.assertEqual(delete_port_dict[const.NET_ID], new_net_dict[NET_ID])
# self.assertEqual(delete_port_dict[const.PORT_ID],
# new_net_dict[PORT_ID])
self.tearDownNetwork(tenant_id, new_net_dict[const.NET_ID])
self.assertEqual(delete_port_dict[const.PORT_ID],
port_dict[const.PORT_ID])
@ -470,10 +462,6 @@ class CoreAPITestFunc(unittest.TestCase):
port_dict[const.PORT_ID], remote_interface)
port = db.port_get(new_net_dict[const.NET_ID],
port_dict[const.PORT_ID])
# self.assertEqual(
# self._l2network_plugin._networks[new_net_dict[const.NET_ID]]
# [const.NET_PORTS][port_dict[const.PORT_ID]]
# [const.ATTACHMENT], remote_interface)
self.assertEqual(port[const.INTERFACEID], remote_interface)
self.tearDownNetworkPortInterface(
tenant_id, new_net_dict[const.NET_ID],
@ -553,9 +541,6 @@ class CoreAPITestFunc(unittest.TestCase):
port_dict[const.PORT_ID])
port = db.port_get(new_net_dict[const.NET_ID],
port_dict[const.PORT_ID])
# self.assertEqual(self._l2network_plugin._networks
# [new_net_dict[const.NET_ID]][const.NET_PORTS]
# [port_dict[const.PORT_ID]][const.ATTACHMENT], None)
self.assertEqual(port[const.INTERFACEID], None)
self.tearDownNetworkPort(tenant_id, new_net_dict[const.NET_ID],
port_dict[const.PORT_ID])
@ -616,12 +601,6 @@ class CoreAPITestFunc(unittest.TestCase):
port_profile = cdb.get_portprofile(tenant_id, port_profile_id)
self.assertEqual(port_profile[const.PPNAME], profile_name)
self.assertEqual(port_profile[const.PPQOS], qos)
# self.assertEqual(
# self._l2network_plugin._portprofiles[port_profile_id]['vlan-id'],
# vlan_id)
#self.assertEqual(
# self._l2network_plugin._portprofiles[port_profile_id]
# ['profile-name'], profile_name)
self.tearDownPortProfile(tenant_id, port_profile_id)
LOG.debug("test_create_portprofile - tenant id: %s - END",
net_tenant_id)
@ -641,10 +620,7 @@ class CoreAPITestFunc(unittest.TestCase):
tenant_id, self.profile_name, self.qos)
port_profile_id = port_profile_dict['profile_id']
self._l2network_plugin.delete_portprofile(tenant_id, port_profile_id)
# port_profile = cdb.get_portprofile(tenant_id, port_profile_id)
self.assertRaises(Exception, cdb.get_portprofile, port_profile_id)
# self.assertEqual(port_profile, {})
# self.assertEqual(self._l2network_plugin._portprofiles, {})
LOG.debug("test_delete_portprofile - tenant id: %s - END",
net_tenant_id)
@ -714,14 +690,6 @@ class CoreAPITestFunc(unittest.TestCase):
new_pplist.append(new_pp)
self.assertTrue(new_pplist[0] in port_profile_list)
self.assertTrue(new_pplist[1] in port_profile_list)
# self.assertEqual(self._l2network_plugin._portprofiles
# [port_profile_id1]['vlan-id'], self.vlan_id)
# self.assertEqual(self._l2network_plugin._portprofiles
# [port_profile_id1]['profile-name'], self.profile_name)
# self.assertEqual(self._l2network_plugin._portprofiles
# [port_profile_id2]['vlan-id'], vlan_id2)
# self.assertEqual(self._l2network_plugin._portprofiles
# [port_profile_id2]['profile-name'], profile_name2)
self.tearDownPortProfile(tenant_id, port_profile_id1)
self.tearDownPortProfile(tenant_id, port_profile_id2)
@ -816,9 +784,6 @@ class CoreAPITestFunc(unittest.TestCase):
port_profile_associate = cdb.get_pp_binding(tenant_id, port_profile_id)
self.assertEqual(port_profile_associate[const.PORTID],
port_dict[const.PORT_ID])
#self.assertEqual(
# self._l2network_plugin._portprofiles[port_profile_id]
# [const.PROFILE_ASSOCIATIONS][0], port_id)
self.tearDownAssociatePortProfile(
tenant_id, new_net_dict[const.NET_ID],
port_dict[const.PORT_ID], port_profile_id)
@ -863,8 +828,6 @@ class CoreAPITestFunc(unittest.TestCase):
port_dict[const.PORT_ID], port_profile_id)
port_profile_associate = cdb.get_pp_binding(tenant_id, port_profile_id)
self.assertEqual(port_profile_associate, [])
# self.assertEqual(self._l2network_plugin._portprofiles
# [port_profile_id][const.PROFILE_ASSOCIATIONS], [])
self.tearDownPortProfile(tenant_id, port_profile_id)
self.tearDownNetworkPort(
tenant_id, new_net_dict[const.NET_ID],
@ -883,7 +846,6 @@ class CoreAPITestFunc(unittest.TestCase):
tenant_id, net_id, port_id, profile_id)
LOG.debug("test_disassociate_portprofileDNE - END")
# def test_disassociate_portprofile_Unassociated
def test_get_vlan_name(self, net_tenant_id=None, vlan_id="NewVlan",
vlan_prefix=conf.VLAN_NAME_PREFIX):
"""
@ -923,22 +885,17 @@ class CoreAPITestFunc(unittest.TestCase):
LOG.debug("test_validate_port_state - END")
def setUp(self):
"""
Set up function
"""
self.tenant_id = "test_tenant"
self.network_name = "test_network"
self.profile_name = "test_tenant_port_profile"
# self.vlan_id = "test_tenant_vlanid300"
self.qos = "test_qos"
self.port_state = const.PORT_UP
self.net_id = '00005'
self.port_id = 'p0005'
self.remote_interface = 'new_interface'
#sql_query = "drop database quantum_l2network"
#sql_query_2 = "create database quantum_l2network"
#self._utils = utils.DBUtils()
#self._utils.execute_db_query(sql_query)
#time.sleep(10)
#self._utils.execute_db_query(sql_query_2)
#time.sleep(10)
self._l2network_plugin = l2network_plugin.L2Network()
"""
@ -950,29 +907,50 @@ class CoreAPITestFunc(unittest.TestCase):
db.clear_db()
def tearDownNetwork(self, tenant_id, network_dict_id):
"""
Tear down the Network
"""
self._l2network_plugin.delete_network(tenant_id, network_dict_id)
def tearDownPortOnly(self, tenant_id, network_dict_id, port_id):
"""
Tear doen the port
"""
self._l2network_plugin.delete_port(tenant_id, network_dict_id, port_id)
def tearDownNetworkPort(self, tenant_id, network_dict_id, port_id):
"""
Tear down Network Port
"""
self._l2network_plugin.delete_port(tenant_id, network_dict_id, port_id)
self.tearDownNetwork(tenant_id, network_dict_id)
def tearDownNetworkPortInterface(self, tenant_id, network_dict_id,
port_id):
"""
Tear down Network Port Interface
"""
self._l2network_plugin.unplug_interface(tenant_id,
network_dict_id, port_id)
self.tearDownNetworkPort(tenant_id, network_dict_id, port_id)
def tearDownPortProfile(self, tenant_id, port_profile_id):
"""
Tear down Port Profile
"""
self._l2network_plugin.delete_portprofile(tenant_id, port_profile_id)
def tearDownPortProfileBinding(self, tenant_id, port_profile_id):
"""
Tear down port profile binding
"""
self._l2network_plugin.delete_portprofile(tenant_id, port_profile_id)
def tearDownAssociatePortProfile(self, tenant_id, net_id, port_id,
port_profile_id):
"""
Tear down associate port profile
"""
self._l2network_plugin.disassociate_portprofile(
tenant_id, net_id, port_id, port_profile_id)
self.tearDownPortProfile(tenant_id, port_profile_id)

View File

@ -28,6 +28,9 @@ LOG = logging.getLogger('quantum.tests.test_nexus')
class TestNexusPlugin(unittest.TestCase):
def setUp(self):
"""
Set up function
"""
self.tenant_id = "test_tenant_cisco1"
self.net_name = "test_network_cisco1"
@ -281,18 +284,3 @@ class TestNexusPlugin(unittest.TestCase):
Clean up functions after the tests
"""
self._cisco_nexus_plugin.delete_network(tenant_id, network_dict_id)
# def test_create_network(self):
# _test_create_network(self._cisco_nexus_plugin)
# def test_delete_network(self):
# _test_delete_network(self._cisco_nexus_plugin)
# def test_rename_network(self):
# _test_rename_network(self._cisco_nexus_plugin)
# def test_show_network(self):
# _test_get_network_details(self._cisco_nexus_plugin)
# def test_list_networks(self):
# _test_list_all_networks(self._cisco_nexus_plugin)

View File

@ -73,6 +73,7 @@ ASSOCIATE_PROFILE_OUTPUT = "<configConfMos cookie=\"cookie_placeholder\" "\
class TestUCSDriver(unittest.TestCase):
def setUp(self):
""" Set up function"""
self.ucsm_driver = cisco_ucs_network_driver.CiscoUCSMDriver()
self.vlan_name = 'New Vlan'
self.vlan_id = '200'
@ -136,8 +137,6 @@ class TestUCSDriver(unittest.TestCase):
"""
LOG.debug("test_create_profile_post_data - START")
#profile_details = self.ucsm_driver._create_profile_post_data(
# self.profile_name, self.vlan_name)
self.ucsm_driver._create_profile_post_data(
self.profile_name, self.vlan_name)
profile_delete_details = self.ucsm_driver._delete_profile_post_data(

View File

@ -29,6 +29,9 @@ LOG.getLogger("cisco_plugin")
class UCSVICTestPlugin(unittest.TestCase):
def setUp(self):
"""
Set up function.
"""
self.tenant_id = "test_tenant_cisco12"
self.net_name = "test_network_cisco12"
@ -141,6 +144,9 @@ class UCSVICTestPlugin(unittest.TestCase):
self.tearDownNetwork(self.tenant_id, self.net_id)
def test_rename_network(self):
"""
Tests rename network.
"""
self._test_rename_network("new_test_network1")
def _test_create_port(self, port_state):
@ -166,6 +172,9 @@ class UCSVICTestPlugin(unittest.TestCase):
self.tearDownNetworkPort(self.tenant_id, self.net_id, self.port_id)
def test_create_port(self):
"""
Tests create port.
"""
self._test_create_port(const.PORT_UP)
def _test_delete_port(self, port_state):
@ -188,6 +197,9 @@ class UCSVICTestPlugin(unittest.TestCase):
self.tearDownNetwork(self.tenant_id, self.net_id)
def test_delete_port(self):
"""
Tests delete port.
"""
self._test_delete_port(const.PORT_UP)
def _test_update_port(self, port_state):
@ -207,9 +219,15 @@ class UCSVICTestPlugin(unittest.TestCase):
self.tearDownNetworkPort(self.tenant_id, self.net_id, self.port_id)
def test_update_port_state_up(self):
"""
Tests update port state up
"""
self._test_update_port(const.PORT_UP)
def test_update_port_state_down(self):
"""
Tests update port state down
"""
self._test_update_port(const.PORT_DOWN)
def _test_get_port_details_state_up(self, port_state):
@ -266,12 +284,21 @@ class UCSVICTestPlugin(unittest.TestCase):
self.tearDownNetworkPort(self.tenant_id, self.net_id, self.port_id)
def test_get_port_details_state_up(self):
"""
Tests get port details state up
"""
self._test_get_port_details_state_up(const.PORT_UP)
def test_show_port_state_down(self):
"""
Tests show port state down
"""
self._test_show_port_state_down(const.PORT_DOWN)
def test_create_port_profile(self):
"""
Tests create port profile
"""
LOG.debug("UCSVICTestPlugin:test_create_port_profile() called\n")
new_port_profile = self._cisco_ucs_plugin._create_port_profile(
self.tenant_id, self.net_id, self.port_id,
@ -284,6 +311,9 @@ class UCSVICTestPlugin(unittest.TestCase):
self._cisco_ucs_plugin._delete_port_profile(self.port_id, profile_name)
def test_delete_port_profile(self):
"""
Tests delete port profile
"""
LOG.debug("UCSVICTestPlugin:test_delete_port_profile() called\n")
self._cisco_ucs_plugin._create_port_profile(
self.tenant_id, self.net_id, self.port_id, self.vlan_name,
@ -313,7 +343,6 @@ class UCSVICTestPlugin(unittest.TestCase):
self.tenant_id, self.net_id, self.port_id)
self.assertEqual(port[const.ATTACHMENT], remote_interface_id)
port_profile = port[const.PORT_PROFILE]
#profile_name = port_profile[const.PROFILE_NAME]
new_vlan_name = self._cisco_ucs_plugin._get_vlan_name_for_network(
self.tenant_id, self.net_id)
new_vlan_id = self._cisco_ucs_plugin._get_vlan_id_for_network(
@ -323,7 +352,10 @@ class UCSVICTestPlugin(unittest.TestCase):
self.tearDownNetworkPortInterface(self.tenant_id, self.net_id,
self.port_id)
def test_plug_interface(self):
def test_plug_interface(self):
"""
Tests test plug interface
"""
self._test_plug_interface("4")
def _test_unplug_interface(self, remote_interface_id):
@ -346,17 +378,22 @@ class UCSVICTestPlugin(unittest.TestCase):
self.tenant_id, self.net_id, self.port_id)
self.assertEqual(port[const.ATTACHMENT], None)
port_profile = port[const.PORT_PROFILE]
#profile_name = port_profile[const.PROFILE_NAME]
self.assertEqual(port_profile[const.PROFILE_VLAN_NAME],
conf.DEFAULT_VLAN_NAME)
self.assertEqual(port_profile[const.PROFILE_VLAN_ID],
conf.DEFAULT_VLAN_ID)
self.tearDownNetworkPort(self.tenant_id, self.net_id, self.port_id)
def test_unplug_interface(self):
def test_unplug_interface(self):
"""
Tests unplug interface
"""
self._test_unplug_interface("4")
def test_get_vlan_name_for_network(self):
"""
Tests get vlan name for network
"""
LOG.debug("UCSVICTestPlugin:test_get_vlan_name_for_network() called\n")
net = self._cisco_ucs_plugin.create_network(
self.tenant_id, self.net_name, self.net_id,
@ -365,6 +402,9 @@ class UCSVICTestPlugin(unittest.TestCase):
self.tearDownNetwork(self.tenant_id, self.net_id)
def test_get_vlan_id_for_network(self):
"""
Tests get vlan id for network
"""
LOG.debug("UCSVICTestPlugin:test_get_vlan_id_for_network() called\n")
net = self._cisco_ucs_plugin.create_network(
self.tenant_id, self.net_name, self.net_id, self.vlan_name,
@ -373,6 +413,9 @@ class UCSVICTestPlugin(unittest.TestCase):
self.tearDownNetwork(self.tenant_id, self.net_id)
def test_get_network(self):
"""
Tests get network
"""
LOG.debug("UCSVICTestPlugin:test_get_network() called\n")
net = self._cisco_ucs_plugin.create_network(
self.tenant_id, self.net_name, self.net_id, self.vlan_name,
@ -381,6 +424,9 @@ class UCSVICTestPlugin(unittest.TestCase):
self.tearDownNetwork(self.tenant_id, self.net_id)
def test_get_port(self):
"""
Tests get port
"""
LOG.debug("UCSVICTestPlugin:test_get_port() called\n")
self._cisco_ucs_plugin.create_network(self.tenant_id, self.net_name,
self.net_id, self.vlan_name,
@ -392,19 +438,31 @@ class UCSVICTestPlugin(unittest.TestCase):
self.tearDownNetworkPort(self.tenant_id, self.net_id, self.port_id)
def test_get_network_NetworkNotFound(self):
"""
Tests get network not found
"""
self.assertRaises(exc.NetworkNotFound,
self._cisco_ucs_plugin._get_network,
self.tenant_id, self.net_id)
def test_delete_network_NetworkNotFound(self):
"""
Tests delete network not found
"""
self.assertRaises(exc.NetworkNotFound,
self._cisco_ucs_plugin.delete_network,
self.tenant_id, self.net_id)
def test_delete_port_PortInUse(self):
"""
Tests delete port in use
"""
self._test_delete_port_PortInUse("4")
def _test_delete_port_PortInUse(self, remote_interface_id):
"""
Tests delete port in use
"""
self._cisco_ucs_plugin.create_network(self.tenant_id, self.net_name,
self.net_id, self.vlan_name,
self.vlan_id)
@ -419,6 +477,9 @@ class UCSVICTestPlugin(unittest.TestCase):
self.port_id)
def test_delete_port_PortNotFound(self):
"""
Tests delete port not found
"""
self._cisco_ucs_plugin.create_network(self.tenant_id, self.net_name,
self.net_id, self.vlan_name,
self.vlan_id)
@ -427,10 +488,16 @@ class UCSVICTestPlugin(unittest.TestCase):
self.tearDownNetwork(self.tenant_id, self.net_id)
def test_plug_interface_PortInUse(self):
"""
Tests plug interface port in use
"""
self._test_plug_interface_PortInUse("6", "5")
def _test_plug_interface_PortInUse(self, remote_interface_id1,
remote_interface_id2):
"""
Tests plug interface port in use
"""
LOG.debug("UCSVICTestPlugin:_test_plug_interface_PortInUse() called\n")
self._cisco_ucs_plugin.create_network(self.tenant_id, self.net_name,
self.net_id, self.vlan_name,
@ -447,10 +514,16 @@ class UCSVICTestPlugin(unittest.TestCase):
self.port_id)
def test_attachment_exists(self):
"""
Tests attachment exists
"""
LOG.debug("UCSVICTestPlugin:testValidateAttachmentAlreadyAttached")
self._test_attachment_exists("4")
def _test_attachment_exists(self, remote_interface_id):
"""
Tests attachment exists
"""
LOG.debug("UCSVICTestPlugin:_test_validate_attachmentAlreadyAttached")
self._cisco_ucs_plugin.create_network(self.tenant_id, self.net_name,
self.net_id, self.vlan_name,
@ -467,14 +540,23 @@ class UCSVICTestPlugin(unittest.TestCase):
self.port_id)
def tearDownNetwork(self, tenant_id, net_id):
"""
Tear down network
"""
self._cisco_ucs_plugin.delete_network(tenant_id, net_id)
def tearDownNetworkPort(self, tenant_id, net_id, port_id):
"""
Tear down network port
"""
self._cisco_ucs_plugin.delete_port(tenant_id, net_id,
port_id)
self.tearDownNetwork(tenant_id, net_id)
def tearDownNetworkPortInterface(self, tenant_id, net_id, port_id):
"""
Tear down network port interface
"""
self._cisco_ucs_plugin.unplug_interface(tenant_id, net_id,
port_id)
self.tearDownNetworkPort(tenant_id, net_id, port_id)

View File

@ -27,8 +27,8 @@ import httplib
import logging as LOG
from xml.etree import ElementTree as et
from quantum.plugins.cisco.common import cisco_constants as const
from quantum.plugins.cisco.common import cisco_exceptions as cexc
from quantum.plugins.cisco.common import cisco_constants as const
from quantum.plugins.cisco.ucs import cisco_getvif as gvif

View File

@ -23,9 +23,9 @@ import logging as LOG
from quantum.common import exceptions as exc
from quantum.common import utils
from quantum.plugins.cisco.common import cisco_exceptions as cexc
from quantum.plugins.cisco.common import cisco_constants as const
from quantum.plugins.cisco.common import cisco_credentials as cred
from quantum.plugins.cisco.common import cisco_exceptions as cexc
from quantum.plugins.cisco.common import cisco_utils as cutil
from quantum.plugins.cisco.db import api as db
from quantum.plugins.cisco.db import l2network_db as cdb

View File

@ -22,7 +22,6 @@ import logging as LOG
from optparse import OptionParser
import os
import sys
import unittest
from quantum.common import exceptions as q_exc
from quantum.quantum_plugin_base import QuantumPluginBase
@ -200,41 +199,3 @@ class OVSQuantumPlugin(QuantumPluginBase):
def get_interface_details(self, tenant_id, net_id, port_id):
res = db.port_get(port_id, net_id)
return res.interface_id
class VlanMapTest(unittest.TestCase):
def setUp(self):
self.vmap = VlanMap()
def tearDown(self):
pass
def testAddVlan(self):
vlan_id = self.vmap.acquire("foobar")
self.assertTrue(vlan_id == 2)
def testReleaseVlan(self):
vlan_id = self.vmap.acquire("foobar")
self.vmap.release("foobar")
self.assertTrue(self.vmap.get(vlan_id) == None)
if __name__ == "__main__":
usagestr = "Usage: %prog [OPTIONS] <command> [args]"
parser = OptionParser(usage=usagestr)
parser.add_option("-v", "--verbose", dest="verbose",
action="store_true", default=False, help="turn on verbose logging")
options, args = parser.parse_args()
if options.verbose:
LOG.basicConfig(level=LOG.DEBUG)
else:
LOG.basicConfig(level=LOG.WARN)
# Make sqlalchemy quieter
LOG.getLogger('sqlalchemy.engine').setLevel(LOG.WARN)
# Run the tests
suite = unittest.TestLoader().loadTestsFromTestCase(VlanMapTest)
unittest.TextTestRunner(verbosity=2).run(suite)

View File

@ -0,0 +1,89 @@
#!/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 OVS plugin
This file should be run from the top dir in the quantum directory
To run all test::
python quantum/plugins/openvswitch/run_tests.py
To run all unit tests::
python quantum/plugins/openvswitch/run_tests.py unit
To run all functional tests::
python quantum/plugins/openvswitch/run_tests.py functional
To run a single unit test::
python quantum/plugins/openvswitch/run_tests.py \
unit.test_stores:TestSwiftBackend.test_get
To run a single functional test::
python quantum/plugins/openvswitch/run_tests.py \
functional.test_service:TestController.test_create
To run a single unit test module::
python quantum/plugins/openvswitch/run_tests.py unit.test_stores
To run a single functional test module::
python quantum/plugins/openvswitch/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
from quantum.plugins.openvswitch.tests.test_vlan_map import VlanMapTest
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/openvswitch/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)

View File

@ -0,0 +1,36 @@
# 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.
import unittest
from quantum.plugins.openvswitch.ovs_quantum_plugin import VlanMap
class VlanMapTest(unittest.TestCase):
def setUp(self):
self.vmap = VlanMap()
def tearDown(self):
pass
def testAddVlan(self):
vlan_id = self.vmap.acquire("foobar")
self.assertTrue(vlan_id == 2)
def testReleaseVlan(self):
vlan_id = self.vmap.acquire("foobar")
self.vmap.release("foobar")
self.assertTrue(self.vmap.get(vlan_id) == None)

34
setup.py Normal file
View File

@ -0,0 +1,34 @@
import os
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",
)

View File

@ -62,7 +62,7 @@ class ResourceExtensionTest(unittest.TestCase):
def custom_member_action(self, request, id):
return {'member_action': 'value'}
def custom_collection_action(self, request):
def custom_collection_action(self, request, **kwargs):
return {'collection': 'value'}
def test_resource_can_be_added_as_extension(self):
@ -87,7 +87,7 @@ class ResourceExtensionTest(unittest.TestCase):
self.assertEqual(200, response.status_int)
self.assertEqual(json.loads(response.body)['member_action'], "value")
def test_resource_extension_with_custom_collection_action(self):
def test_resource_extension_for_get_custom_collection_action(self):
controller = self.ResourceExtensionController()
collections = {'custom_collection_action': "GET"}
res_ext = extensions.ResourceExtension('tweedles', controller,
@ -98,6 +98,69 @@ class ResourceExtensionTest(unittest.TestCase):
self.assertEqual(200, response.status_int)
self.assertEqual(json.loads(response.body)['collection'], "value")
def test_resource_extension_for_put_custom_collection_action(self):
controller = self.ResourceExtensionController()
collections = {'custom_collection_action': "PUT"}
res_ext = extensions.ResourceExtension('tweedles', controller,
collection_actions=collections)
test_app = setup_extensions_test_app(SimpleExtensionManager(res_ext))
response = test_app.put("/tweedles/custom_collection_action")
self.assertEqual(200, response.status_int)
self.assertEqual(json.loads(response.body)['collection'], 'value')
def test_resource_extension_for_post_custom_collection_action(self):
controller = self.ResourceExtensionController()
collections = {'custom_collection_action': "POST"}
res_ext = extensions.ResourceExtension('tweedles', controller,
collection_actions=collections)
test_app = setup_extensions_test_app(SimpleExtensionManager(res_ext))
response = test_app.post("/tweedles/custom_collection_action")
self.assertEqual(200, response.status_int)
self.assertEqual(json.loads(response.body)['collection'], 'value')
def test_resource_extension_for_delete_custom_collection_action(self):
controller = self.ResourceExtensionController()
collections = {'custom_collection_action': "DELETE"}
res_ext = extensions.ResourceExtension('tweedles', controller,
collection_actions=collections)
test_app = setup_extensions_test_app(SimpleExtensionManager(res_ext))
response = test_app.delete("/tweedles/custom_collection_action")
self.assertEqual(200, response.status_int)
self.assertEqual(json.loads(response.body)['collection'], 'value')
def test_resource_ext_for_formatted_req_on_custom_collection_action(self):
controller = self.ResourceExtensionController()
collections = {'custom_collection_action': "GET"}
res_ext = extensions.ResourceExtension('tweedles', controller,
collection_actions=collections)
test_app = setup_extensions_test_app(SimpleExtensionManager(res_ext))
response = test_app.get("/tweedles/custom_collection_action.json")
self.assertEqual(200, response.status_int)
self.assertEqual(json.loads(response.body)['collection'], "value")
def test_resource_ext_for_nested_resource_custom_collection_action(self):
controller = self.ResourceExtensionController()
collections = {'custom_collection_action': "GET"}
parent = dict(collection_name='beetles', member_name='beetle')
res_ext = extensions.ResourceExtension('tweedles', controller,
collection_actions=collections,
parent=parent)
test_app = setup_extensions_test_app(SimpleExtensionManager(res_ext))
response = test_app.get("/beetles/beetle_id"
"/tweedles/custom_collection_action")
self.assertEqual(200, response.status_int)
self.assertEqual(json.loads(response.body)['collection'], "value")
def test_returns_404_for_non_existant_extension(self):
test_app = setup_extensions_test_app(SimpleExtensionManager(None))

View File

@ -15,106 +15,45 @@
# under the License.
# @author: Dan Wendlandt, Nicira Networks, Inc.
import httplib
import logging as LOG
import json
import socket
import sys
import urllib
from quantum.manager import QuantumManager
from optparse import OptionParser
from quantum.common.wsgi import Serializer
from quantum.cli import MiniClient
import sys
from quantum.client import Client
from quantum.manager import QuantumManager
FORMAT = "json"
CONTENT_TYPE = "application/" + FORMAT
def delete_all_nets(client, tenant_id):
res = client.do_request(tenant_id, 'GET', "/networks." + FORMAT)
resdict = json.loads(res.read())
LOG.debug(resdict)
for n in resdict["networks"]:
def delete_all_nets(client):
res = client.list_networks()
for n in res["networks"]:
nid = n["id"]
res = client.do_request(tenant_id, 'GET',
"/networks/%s/ports.%s" % (nid, FORMAT))
output = res.read()
if res.status != 200:
LOG.error("Failed to list ports: %s" % output)
continue
rd = json.loads(output)
LOG.debug(rd)
for port in rd["ports"]:
pid = port["id"]
data = {'port': {'attachment-id': ''}}
body = Serializer().serialize(data, CONTENT_TYPE)
res = client.do_request(tenant_id, 'DELETE',
"/networks/%s/ports/%s/attachment.%s" % \
(nid, pid, FORMAT), body=body)
output = res.read()
LOG.debug(output)
if res.status != 202:
LOG.error("Failed to unplug iface from port \"%s\": %s" % (vid,
pid, output))
continue
LOG.info("Unplugged interface from port:%s on network:%s" % (pid,
nid))
res = client.do_request(tenant_id, 'DELETE',
"/networks/%s/ports/%s.%s" % (nid, pid, FORMAT))
output = res.read()
if res.status != 202:
LOG.error("Failed to delete port: %s" % output)
continue
pres = client.list_ports(nid)
for port in pres["ports"]:
pid = port['id']
client.detach_resource(nid, pid)
client.delete_port(nid, pid)
print "Deleted Virtual Port:%s " \
"on Virtual Network:%s" % (pid, nid)
res = client.do_request(tenant_id, 'DELETE',
"/networks/" + nid + "." + FORMAT)
status = res.status
if status != 202:
Log.error("Failed to delete network: %s" % nid)
output = res.read()
print output
else:
print "Deleted Virtual Network with ID:%s" % nid
client.delete_network(nid)
print "Deleted Virtual Network with ID:%s" % nid
def create_net_with_attachments(net_name, iface_ids):
def create_net_with_attachments(client, net_name, iface_ids):
data = {'network': {'net-name': '%s' % net_name}}
body = Serializer().serialize(data, CONTENT_TYPE)
res = client.do_request(tenant_id, 'POST',
"/networks." + FORMAT, body=body)
rd = json.loads(res.read())
LOG.debug(rd)
nid = rd["networks"]["network"]["id"]
res = client.create_network(data)
nid = res["networks"]["network"]["id"]
print "Created a new Virtual Network %s with ID:%s" % (net_name, nid)
for iface_id in iface_ids:
res = client.do_request(tenant_id, 'POST',
"/networks/%s/ports.%s" % (nid, FORMAT))
output = res.read()
if res.status != 200:
LOG.error("Failed to create port: %s" % output)
continue
rd = json.loads(output)
new_port_id = rd["ports"]["port"]["id"]
res = client.create_port(nid)
new_port_id = res["ports"]["port"]["id"]
print "Created Virtual Port:%s " \
"on Virtual Network:%s" % (new_port_id, nid)
data = {'port': {'attachment-id': '%s' % iface_id}}
body = Serializer().serialize(data, CONTENT_TYPE)
res = client.do_request(tenant_id, 'PUT',
"/networks/%s/ports/%s/attachment.%s" %\
(nid, new_port_id, FORMAT), body=body)
output = res.read()
LOG.debug(output)
if res.status != 202:
LOG.error("Failed to plug iface \"%s\" to port \"%s\": %s" % \
(iface_id, new_port_id, output))
continue
client.attach_resource(nid, new_port_id, data)
print "Plugged interface \"%s\" to port:%s on network:%s" % \
(iface_id, new_port_id, nid)
@ -149,7 +88,6 @@ if __name__ == "__main__":
if len(args) < 1:
parser.print_help()
help()
sys.exit(1)
nets = {}
@ -163,12 +101,13 @@ if __name__ == "__main__":
print "nets: %s" % str(nets)
client = MiniClient(options.host, options.port, options.ssl)
client = Client(options.host, options.port, options.ssl,
format='json', tenant=tenant_id)
if options.delete:
delete_all_nets(client, tenant_id)
delete_all_nets(client)
for net_name, iface_ids in nets.items():
create_net_with_attachments(net_name, iface_ids)
create_net_with_attachments(client, net_name, iface_ids)
sys.exit(0)