--- /dev/null
-
+
+import os
+import sys
+
+import gettext
+
+#gettext.install('quantum', unicode=1)
+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 test_scripts.miniclient import MiniClient
+from test_client import ExtClient
+from quantum.common.wsgi import Serializer
+
+HOST = '127.0.0.1'
+PORT = 9696
+USE_SSL = False
+TENANT_ID = 'ucs_user'
+
+
+test_network_data = \
+ {'network': {'net-name': 'cisco_test_network',
+ 'valn-id': 28}}
+test_portprofile_data = \
+ {'portprofile': {'portprofile_name': 'cisco_test_portprofile',
+ 'qos_name': 2,
+ 'qos_name': 'test-qos'}}
+test_cred_data = \
+ {'credential': {'credential_name': 'cred3',
+ 'user_name': 'newUser',
+ 'password': 'newPasswd'
+ }}
+test_qos_data = \
+ {'qos': {'qos_name': 'plantimum',
+ 'qos_desc': {'PPS': 50, 'TTL': 5}}}
+
+
+#we put this assignment under portprofile resources
+#therefore we need to create such a test data
+test_port_assign_data = {'portprofile': {'network-id': '001',
+ 'port-id': '1'}}
+test_attach_data = {'port': {'attachment-id': 'v01'}}
+
+test_act_data = {"get_available_host":123}
+
+test_instance_data={'novatenant':{'instance_id' : 1,
+ 'instance_desc' : {'key1' : '1',
+ 'key2' : '2'
+ }}}
+
+def test_get_host(format='json'):
+ client = ExtClient(HOST, PORT, USE_SSL)
+ content_type = "application/" + format
+ body = Serializer().serialize(test_instance_data, content_type)
+ res = client.do_request(TENANT_ID,
+ 'PUT', "/novatenants/001/get_host." + format, body=body)
+ print "XML Response"
+ print_response(res)
+ print "COMPLETED"
+ print "----------------------------"
+
+def test_get_instance_port(format='json'):
+ client = ExtClient(HOST, PORT, USE_SSL)
+ content_type = "application/" + format
+ body = Serializer().serialize(test_instance_data, content_type)
+ res = client.do_request(TENANT_ID,
+ 'PUT', "/novatenants/001/get_instance_port." + format, body=body)
+ print "XML Response"
+ print_response(res)
+ print "COMPLETED"
+ print "----------------------------"
+
+def test_action_ext(format='json'):
+ client = ExtClient(HOST, PORT, USE_SSL)
+ content_type = "application/" + format
+ action_name = 'get_available_host'
+ action_params = dict(name='test')
+ body = Serializer().serialize(test_act_data, content_type)
+
+
+ res = client.do_request(TENANT_ID, 'POST', "/act_resources/1/action." + format, body=body)
+ content = print_response(res)
+
+def print_response(res):
+ content = res.read()
+ print "Status: %s" % res.status
+ print "Content: %s" % content
+ return content
+
+
+def create_cisco_network(format='xml'):
+
+ client = MiniClient(HOST, PORT, USE_SSL)
+ print "CREATE NETWORK -- FORMAT:%s" % format
+ print "----------------------------"
+ content_type = "application/" + format
+ body = Serializer().serialize(test_network_data, content_type)
+ res = client.do_request(TENANT_ID,
+ 'POST', "/networks." + format, body=body)
+ print "XML Response"
+ print_response(res)
+ print "COMPLETED"
+ print "----------------------------"
+
+
+def create_cisco_portprofile(format='xml'):
+ client = ExtClient(HOST, PORT, USE_SSL)
+ content_type = "application/" + format
+ print "List all Profile -- FORMat%s" % format
+ print "----------------------------"
+ res = client.do_request(TENANT_ID, 'GET', "/portprofiles." + format)
+ content = print_response(res)
+ portprofile_data = Serializer().deserialize(content, content_type)
+ print portprofile_data
-
++
++ """
+ print "List a specific Profile -- FORMAT:%s" % format
+ profile_id = portprofile_data['portprofiles'][0]['id']
+ #profile_id='001'
+ print "profile_id " + profile_id
+ res = client.do_request(TENANT_ID,
+ 'GET', "/portprofiles/"
+ + profile_id + "." + format)
+ print_response(res)
- test_attach_resource('json')
++ """
+ print "CREATE Profile -- FORMAT:%s" % format
+ print "----------------------------"
+ content_type = "application/" + format
+ body = Serializer().serialize(test_portprofile_data, content_type)
+ print "***BODY is "
+ print body
+ res = client.do_request(TENANT_ID, 'POST',
+ "/portprofiles." + format, body=body)
+ print "XML Response"
+ print_response(res)
+ print "COMPLETED"
+ print "----------------------------"
+
+def test_credential (format='xml'):
+ client = ExtClient(HOST, PORT, USE_SSL)
+ content_type = "application/" + format
+ print "----------------------------"
+ print "List all credentials -- FORMat%s" % format
+ print "----------------------------"
+ res = client.do_request(TENANT_ID, 'GET', "/credentials." + format)
+ content = print_response(res)
+ credential_data = Serializer().deserialize(content, content_type)
+ print credential_data
+
+ print "----------------------------"
+ print "CREATE Credential -- FORMAT:%s" % format
+ print "----------------------------"
+ content_type = "application/" + format
+ body = Serializer().serialize(test_cred_data, content_type)
+ print "***BODY is "
+ print body
+ res = client.do_request(TENANT_ID, 'POST',
+ "/credentials." + format, body=body)
+ print "XML Response"
+ print_response(res)
+
+ print "----------------------------"
+ print "List all credentials -- FORMat%s" % format
+ print "----------------------------"
+ res = client.do_request(TENANT_ID, 'GET', "/credentials." + format)
+ content = print_response(res)
+ credential_data = Serializer().deserialize(content, content_type)
+ print credential_data
+ print "----------------------------"
+ print "List a specific cred -- FORMAT:%s" % format
+ print "----------------------------"
+ cred_id = credential_data['credentials'][0]['id']
+ #cred_id='001'
+ print "cred_id " + cred_id
+ res = client.do_request(TENANT_ID,
+ 'GET', "/credentials/"
+ + cred_id + "." + format)
+ print_response(res)
+
+ print "----------------------------"
+ print "TEST DELETE Credential -- FORMAT:%s" % format
+ print "----------------------------"
+ res = client.do_request(TENANT_ID, 'DELETE',
+ "/credentials/" + cred_id + "." + format)
+ print_response(res)
+
+ print "----------------------------"
+ print "List all credentials -- FORMat%s" % format
+ print "----------------------------"
+ res = client.do_request(TENANT_ID, 'GET', "/credentials." + format)
+ content = print_response(res)
+ credential_data = Serializer().deserialize(content, content_type)
+ print credential_data
+
+ print "COMPLETED"
+ print "----------------------------"
+
+def test_qos (format='xml'):
+ client = ExtClient(HOST, PORT, USE_SSL)
+ content_type = "application/" + format
+ print "----------------------------"
+ print "List all qoss -- FORMat%s" % format
+ print "----------------------------"
+ res = client.do_request(TENANT_ID, 'GET', "/qoss." + format)
+ content = print_response(res)
+ qos_data = Serializer().deserialize(content, content_type)
+ print qos_data
+
+ print "----------------------------"
+ print "CREATE qos -- FORMAT:%s" % format
+ print "----------------------------"
+ content_type = "application/" + format
+ body = Serializer().serialize(test_qos_data, content_type)
+ print "***BODY is "
+ print body
+ res = client.do_request(TENANT_ID, 'POST',
+ "/qoss." + format, body=body)
+ print "XML Response"
+ print_response(res)
+
+ print "----------------------------"
+ print "List all qoss -- FORMat%s" % format
+ print "----------------------------"
+ res = client.do_request(TENANT_ID, 'GET', "/qoss." + format)
+ content = print_response(res)
+ qos_data = Serializer().deserialize(content, content_type)
+ print qos_data
+ print "----------------------------"
+ print "List a specific cred -- FORMAT:%s" % format
+ print "----------------------------"
+ qos_id = qos_data['qoss'][0]['id']
+ #cred_id='001'
+ print "qos_id " + qos_id
+ res = client.do_request(TENANT_ID,
+ 'GET', "/qoss/"
+ + qos_id + "." + format)
+ print_response(res)
+
+ print "----------------------------"
+ print "TEST DELETE qos -- FORMAT:%s" % format
+ print "----------------------------"
+ res = client.do_request(TENANT_ID, 'DELETE',
+ "/qoss/" + qos_id + "." + format)
+ print_response(res)
+
+ print "----------------------------"
+ print "List all qoss -- FORMat%s" % format
+ print "----------------------------"
+ res = client.do_request(TENANT_ID, 'GET', "/qoss." + format)
+ content = print_response(res)
+ qos_data = Serializer().deserialize(content, content_type)
+ print qos_data
+
+ print "COMPLETED"
+ print "----------------------------"
+
+def test_delete_network(format='xml'):
+ client = MiniClient(HOST, PORT, USE_SSL)
+ content_type = "application/" + format
+ print "TEST DELETE NETWORK -- FORMAT:%s" % format
+ print "----------------------------"
+ print "--> Step 1 - List All Networks"
+ res = client.do_request(TENANT_ID, 'GET', "/networks." + format)
+ content = print_response(res)
+ network_data = Serializer().deserialize(content, content_type)
+ print network_data
+ net_id = network_data['networks'][0]['id']
+ print "--> Step 2 - Delete network %s" % net_id
+ res = client.do_request(TENANT_ID, 'DELETE',
+ "/networks/" + net_id + "." + format)
+ print_response(res)
+ print "--> Step 3 - List All Networks (Again)"
+ res = client.do_request(TENANT_ID, 'GET', "/networks." + format)
+ print_response(res)
+ print "COMPLETED"
+ print "----------------------------"
+
+
+def test_delete_portprofile(format='xml'):
+ client = ExtClient(HOST, PORT, USE_SSL)
+ content_type = "application/" + format
+ print "TEST DELETE PROFILE -- FORMAT:%s" % format
+ print "----------------------------"
+ print "--> Step 1 - List All Profiles"
+ res = client.do_request(TENANT_ID, 'GET', "/portprofiles." + format)
+ content = print_response(res)
+ portprofile_data = Serializer().deserialize(content, content_type)
+ print portprofile_data
+ profile_id = portprofile_data['portprofiles'][0]['id']
+ print "--> Step 2 - Delete portprofile %s" % profile_id
+ res = client.do_request(TENANT_ID, 'DELETE',
+ "/portprofiles/" + profile_id + "." + format)
+ print_response(res)
+ print "--> Step 3 - List All Profiles (Again)"
+ res = client.do_request(TENANT_ID, 'GET', "/portprofiles." + format)
+ print_response(res)
+ print "COMPLETED"
+ print "----------------------------"
+
+
+def test_create_port(format='xml'):
+ client = MiniClient(HOST, PORT, USE_SSL)
+ print "TEST CREATE PORT -- FORMAT:%s" % format
+ print "----------------------------"
+ print "--> Step 1 - List Ports for network 001"
+ res = client.do_request(TENANT_ID, 'GET', "/networks/001/ports." + format)
+ print_response(res)
+ print "--> Step 2 - Create Port for network 001"
+ res = client.do_request(TENANT_ID, 'POST', "/networks/001/ports." + format)
+ print_response(res)
+ print "--> Step 3 - List Ports for network 001 (again)"
+ res = client.do_request(TENANT_ID, 'GET', "/networks/001/ports." + format)
+ print_response(res)
+ print "COMPLETED"
+ print "----------------------------"
+
+
+#assuming network 001 and ports 1 are created in the plug-in
+def test_attach_resource(format='xml'):
+ client = MiniClient(HOST, PORT, USE_SSL)
+ print "TEST attach resources to port"
+ content_type = "application/" + format
+ body = Serializer().serialize(test_attach_data, content_type)
+ #attach virtual interface to the port
+ res = client.do_request(TENANT_ID, 'PUT',
+ "/networks/001/ports/1/attachment."
+ + format, body=body)
+ print_response(res)
+ #list existing interface of the port
+ res = client.do_request(TENANT_ID, 'GET',
+ "/networks/001/ports/1/attachment." + format)
+ print_response(res)
+ #de_attach virtual interface from the port
+ res = client.do_request(TENANT_ID, 'DELETE',
+ "/networks/001/ports/1/attachment." + format)
+ print_response(res)
+ #list existing interface of the port
+ res = client.do_request(TENANT_ID, 'GET',
+ "/networks/001/ports/1/attachment." + format)
+ print_response(res)
+
+
+#assuming network 001, ports 1 and portprofile 002 are created in the plug-in
+def test_assign_portprofile(format='xml'):
+ client = ExtClient(HOST, PORT, USE_SSL)
+ print "TEST attach resources to port"
+ content_type = "application/" + format
+ body = Serializer().serialize(test_port_assign_data, content_type)
+ print "body is " + body
+ res = client.do_request(TENANT_ID, 'PUT',
+ "/portprofiles/001/associate_portprofile."
+ + format, body=body)
+ print_response(res)
+ res = client.do_request(TENANT_ID, 'POST',
+ "/portprofiles/001/disassociate_portprofile."
+ + format, body=body)
+
+ print_response(res)
+
+
+def main():
+ create_cisco_portprofile('json')
- #create_cisco_network('json')
- #test_create_port('json')
- #create_cisco_portprofile('json')
- #test_assign_portprofile('json')
++ #test_attach_resource('json')
+
+ test_delete_portprofile('json')
+ test_credential('json')
+ test_qos('json')
+ ##test_action_ext('json')
+ test_get_host('json')
+ test_get_instance_port('json')
+
++ create_cisco_network('json')
++ test_create_port('json')
++ create_cisco_portprofile('json')
++ test_assign_portprofile('json')
+ pass
+
+
+# Standard boilerplate to call the main() function.
+if __name__ == '__main__':
+ main()
--- /dev/null
+"""
+# 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.
+#
+"""
++
++
+def get_view_builder(req):
++ """get view builder """
+ base_url = req.application_url
+ return ViewBuilder(base_url)
+
+
+class ViewBuilder(object):
+ """
+ ViewBuilder for Credential,
+ derived from quantum.views.networks
+ """
+ def __init__(self, base_url):
+ """
+ :param base_url: url of the root wsgi application
+ """
+ self.base_url = base_url
+
+ def build(self, credential_data, is_detail=False):
+ """Generic method used to generate a credential entity."""
+ print "credential-DATA:%s" % credential_data
+ if is_detail:
+ credential = self._build_detail(credential_data)
+ else:
+ credential = self._build_simple(credential_data)
+ return credential
+
+ def _build_simple(self, credential_data):
+ """Return a simple model of a server."""
+ return dict(credential=dict(id=credential_data['credential_id']))
+
+ def _build_detail(self, credential_data):
+ """Return a simple model of a server."""
+
+ return dict(credential=dict(id=credential_data['credential_id'],
+ name=credential_data['user_name'],
+ password=credential_data['password']))
--- /dev/null
- def wrap_exception(f):
+"""
+# 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
+
+
- return f(*args, **kw)
- except Exception, e:
- if not isinstance(e, Error):
++def wrap_exception(afunc):
++ """Wrap Exception"""
+ def _wrap(*args, **kw):
++ """Internal Wrap Exception func"""
+ try:
- raise Error(str(e))
++ 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))
- _wrap.func_name = f.func_name
++ raise Error(str(exp))
+ raise
++ _wrap.func_name = afunc.func_name
+ return _wrap
--- /dev/null
- import webob.exc
+"""
+# 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 webob.dec
- #print ("*********TEST2")
+
+from quantum.api import api_common as common
+from quantum.common import wsgi
+
+
+class Fault(webob.exc.HTTPException):
+ """Error codes for API faults"""
+
+ _fault_names = {
+ 400: "malformedRequest",
+ 401: "unauthorized",
+ 420: "networkNotFound",
+ 421: "PortprofileInUse",
+ 430: "portNotFound",
+ 431: "requestedStateInvalid",
+ 432: "portInUse",
+ 440: "alreadyAttached",
+ 450: "PortprofileNotFound",
+ 451: "CredentialNotFound",
+ 452: "QoSNotFound",
+ 453: "NovatenantNotFound",
+ 470: "serviceUnavailable",
+ 471: "pluginFault"}
+
+ def __init__(self, exception):
+ """Create a Fault for the given webob.exc.exception."""
+ self.wrapped_exc = exception
+
+ @webob.dec.wsgify(RequestClass=wsgi.Request)
+ def __call__(self, req):
+ """Generate a WSGI response based on the exception passed to ctor."""
- #print ("*********TEST1")
+ # 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}}
+ # '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.content_type = content_type
+ return self.wrapped_exc
+
+
+class PortprofileNotFound(webob.exc.HTTPClientError):
+ """
+ subclass of :class:`~HTTPClientError`
+
+ This indicates that the server did not find the Portprofile specified
+ in the HTTP request
+
+ code: 450, title: Portprofile not Found
+ """
+ code = 450
+ title = 'Portprofile Not Found'
+ explanation = ('Unable to find a Portprofile with'
+ + ' the specified identifier.')
+
+
+class PortNotFound(webob.exc.HTTPClientError):
+ """
+ subclass of :class:`~HTTPClientError`
+
+ This indicates that the server did not find the port specified
+ in the HTTP request for a given network
+
+ code: 430, title: Port not Found
+ """
+ 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`
+
+ This indicates that the server did not find the Credential specified
+ in the HTTP request
+
+ code: 460, title: Credential not Found
+ """
+ code = 451
+ title = 'Credential Not Found'
+ explanation = ('Unable to find a Credential with'
+ + ' the specified identifier.')
+
+
+class QosNotFound(webob.exc.HTTPClientError):
+ """
+ subclass of :class:`~HTTPClientError`
+
+ This indicates that the server did not find the QoS specified
+ in the HTTP request
+
+ code: 480, title: QoS not Found
+ """
+ code = 452
+ title = 'QoS Not Found'
+ explanation = ('Unable to find a QoS with'
+ + ' the specified identifier.')
+
+
+class NovatenantNotFound(webob.exc.HTTPClientError):
+ """
+ subclass of :class:`~HTTPClientError`
+
+ This indicates that the server did not find the Novatenant specified
+ in the HTTP request
+
+ code: 480, title: Nova tenant not Found
+ """
+ code = 453
+ title = 'Nova tenant Not Found'
+ explanation = ('Unable to find a Novatenant with'
+ + ' the specified identifier.')
+
+
+class RequestedStateInvalid(webob.exc.HTTPClientError):
+ """
+ subclass of :class:`~HTTPClientError`
+
+ This indicates that the server could not update the port state to
+ to the request value
+
+ code: 431, title: Requested State Invalid
+ """
+ code = 431
+ title = 'Requested State Invalid'
+ explanation = ('Unable to update port state with specified value.')
--- /dev/null
- return dict(host_desc=host_data['host_desc'])
+"""
+# 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.
+#
+"""
++
++
+def get_view_builder(req):
++ """get view builder """
+ base_url = req.application_url
+ return ViewBuilder(base_url)
+
+
+class ViewBuilder(object):
+ """
+ ViewBuilder for novatenant,
+ derived from quantum.views.networks
+ """
+ def __init__(self, base_url):
+ """
+ :param base_url: url of the root wsgi application
+ """
+ self.base_url = base_url
+
+ def build_host(self, host_data):
+ """Return host description."""
++ return dict(host_list=host_data['host_list'])
+
+ def build_vif(self, vif_data):
+ """Return VIF description."""
+ return dict(vif_desc=vif_data['vif_desc'])
--- /dev/null
+"""
+# 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.
+#
+"""
++
++
+def get_view_builder(req):
++ """get view builder"""
+ base_url = req.application_url
+ return ViewBuilder(base_url)
+
+
+class ViewBuilder(object):
+ """
+ ViewBuilder for Portprofile,
+ derived from quantum.views.networks
+ """
+ def __init__(self, base_url):
+ """
+ :param base_url: url of the root wsgi application
+ """
+ self.base_url = base_url
+
+ def build(self, portprofile_data, is_detail=False):
+ """Generic method used to generate a portprofile entity."""
+ print "portprofile_DATA:%s" % portprofile_data
+ if is_detail:
+ portprofile = self._build_detail(portprofile_data)
+ else:
+ portprofile = self._build_simple(portprofile_data)
+ return portprofile
+
+ def _build_simple(self, portprofile_data):
+ """Return a simple model of a portprofile"""
+ return dict(portprofile=dict(id=portprofile_data['profile_id']))
+
+ def _build_detail(self, portprofile_data):
+ """Return a detailed info of a portprofile."""
+ if (portprofile_data['assignment'] == None):
+ return dict(portprofile=dict(id=portprofile_data['profile_id'],
+ name=portprofile_data['profile_name'],
+ qos_name=portprofile_data['qos_name']))
+ else:
+ return dict(portprofile=dict(id=portprofile_data['profile_id'],
+ name=portprofile_data['profile_name'],
+ qos_name=portprofile_data['qos_name'],
+ assignment=portprofile_data['assignment']))
--- /dev/null
- print "qos_DATA:%s" % qos_data
+"""
+# 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.
+#
+"""
++
++
+def get_view_builder(req):
++ """get view builder"""
+ base_url = req.application_url
+ return ViewBuilder(base_url)
+
+
+class ViewBuilder(object):
+ """
+ ViewBuilder for QoS,
+ derived from quantum.views.networks
+ """
+ def __init__(self, base_url):
+ """
+ :param base_url: url of the root wsgi application
+ """
+ self.base_url = base_url
+
+ def build(self, qos_data, is_detail=False):
+ """Generic method used to generate a QoS entity."""
-
+ if is_detail:
+ qos = self._build_detail(qos_data)
+ else:
+ qos = self._build_simple(qos_data)
+ return qos
+
+ def _build_simple(self, qos_data):
+ """Return a simple model of a server."""
+ return dict(qos=dict(id=qos_data['qos_id']))
+
+ def _build_detail(self, qos_data):
+ """Return a simple model of a server."""
+ return dict(qos=dict(id=qos_data['qos_id'],
+ name=qos_data['qos_name'],
+ description=qos_data['qos_desc']))
--- /dev/null
- from quantum.common import wsgi
+"""
+# 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
+
+from webob import exc
+from extensions import _credential_view as credential_view
+from extensions import _exceptions as exception
+from extensions import _faults as faults
+
+from quantum.api import api_common as common
-
+from quantum.common import extensions
+from quantum.manager import QuantumManager
+
+LOG = logging.getLogger('quantum.api.credentials')
+
+
+class Credential(object):
-
- def get_name(self):
++ """extension class Credential"""
+ def __init__(self):
+ pass
- def get_alias(self):
++
++ @classmethod
++ def get_name(cls):
++ """ Returns Ext Resource Name """
+ return "Cisco Credential"
+
- def get_description(self):
++ @classmethod
++ def get_alias(cls):
++ """ Returns Ext Resource Alias """
+ return "Cisco Credential"
+
- def get_namespace(self):
- return ""
++ @classmethod
++ def get_description(cls):
++ """ Returns Ext Resource Description """
+ return "Credential include username and password"
+
- def get_updated(self):
++ @classmethod
++ def get_namespace(cls):
++ """ Returns Ext Resource Namespace """
++ return "http://docs.ciscocloud.com/api/ext/credential/v1.0"
+
- def get_resources(self):
++ @classmethod
++ def get_updated(cls):
++ """ Returns Ext Resource Name """
+ return "2011-07-25T13:25:27-06:00"
+
- super(CredentialController, self).__init__(plugin)
++ @classmethod
++ def get_resources(cls):
++ """ 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)]
+
+
+class CredentialController(common.QuantumController):
+ """ credential API controller
+ based on QuantumController """
+
+ _credential_ops_param_list = [{
+ 'param-name': 'credential_name',
+ 'required': True}, {
+ 'param-name': 'user_name',
+ 'required': True}, {
+ 'param-name': 'password',
+ 'required': True}]
+
+ _serialization_metadata = {
+ "application/xml": {
+ "attributes": {
+ "credential": ["id", "name"],
+ },
+ },
+ }
+
+ def __init__(self, plugin):
+ self._resource_name = 'credential'
- except exception.CredentialNotFound as e:
- return faults.Fault(faults.CredentialNotFound(e))
-
- #return faults.Fault(e)
++ self._plugin = plugin
++ #super(CredentialController, self).__init__(plugin)
+
+ def index(self, request, tenant_id):
+ """ Returns a list of credential ids """
+ #TODO: this should be for a given tenant!!!
+ return self._items(request, tenant_id, is_detail=False)
+
+ def _items(self, request, tenant_id, is_detail):
+ """ Returns a list of credentials. """
+ credentials = self._plugin.get_all_credentials(tenant_id)
+ builder = credential_view.get_view_builder(request)
+ result = [builder.build(credential, is_detail)['credential']
+ for credential in credentials]
+ return dict(credentials=result)
+
++ # pylint: disable-msg=E1101,W0613
+ def show(self, request, tenant_id, id):
+ """ Returns credential details for the given credential id """
+ try:
+ credential = self._plugin.get_credential_details(
+ tenant_id, id)
+ builder = credential_view.get_view_builder(request)
+ #build response with details
+ result = builder.build(credential, True)
+ return dict(credentials=result)
- except exc.HTTPError as e:
- return faults.Fault(e)
++ except exception.CredentialNotFound as exp:
++ return faults.Fault(faults.CredentialNotFound(exp))
+
+ 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,
+ self._credential_ops_param_list)
- except exc.HTTPError as e:
- return faults.Fault(e)
++ except exc.HTTPError as exp:
++ return faults.Fault(exp)
+ credential = self._plugin.\
+ create_credential(tenant_id,
+ req_params['credential_name'],
+ req_params['user_name'],
+ req_params['password'])
+ builder = credential_view.get_view_builder(request)
+ result = builder.build(credential)
+ return dict(credentials=result)
+
+ def update(self, request, tenant_id, id):
+ """ Updates the name for the credential with the given id """
+ try:
+ req_params = \
+ self._parse_request_params(request,
+ self._credential_ops_param_list)
- except exception.CredentialNotFound as e:
- return faults.Fault(faults.CredentialNotFound(e))
++ except exc.HTTPError as exp:
++ return faults.Fault(exp)
+ try:
+ credential = self._plugin.\
+ rename_credential(tenant_id,
+ id, req_params['credential_name'])
+
+ builder = credential_view.get_view_builder(request)
+ result = builder.build(credential, True)
+ return dict(credentials=result)
- except exception.CredentialNotFound as e:
- return faults.Fault(faults.CredentialNotFound(e))
++ except exception.CredentialNotFound as exp:
++ return faults.Fault(faults.CredentialNotFound(exp))
+
+ def delete(self, request, tenant_id, id):
+ """ Destroys the credential with the given id """
+ try:
+ self._plugin.delete_credential(tenant_id, id)
+ return exc.HTTPAccepted()
++ except exception.CredentialNotFound as exp:
++ return faults.Fault(faults.CredentialNotFound(exp))
+
--- /dev/null
- from quantum.common import wsgi
+"""
+# 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.
+#
+"""
+from webob import exc
+
+from extensions import _novatenant_view as novatenant_view
+from extensions import _exceptions as exception
+from extensions import _faults as faults
+
+from quantum.api import api_common as common
-
+from quantum.common import extensions
+from quantum.manager import QuantumManager
+
+
+class Novatenant(object):
- def get_name(self):
++ """extension class Novatenant"""
+ def __init__(self):
+ pass
+
-
- def get_alias(self):
++ @classmethod
++ def get_name(cls):
++ """ Returns Ext Resource Name """
+ return "Cisco Nova Tenant"
-
- def get_description(self):
++
++ @classmethod
++ def get_alias(cls):
++ """ Returns Ext Resource Name """
+ return "Cisco Nova Tenant"
-
- def get_namespace(self):
- return ""
-
- def get_updated(self):
++
++ @classmethod
++ def get_description(cls):
++ """ Returns Ext Resource Name """
+ return "novatenant resource is used by nova side to invoke quantum api"
-
- def get_resources(self):
++
++ @classmethod
++ def get_namespace(cls):
++ """ Returns Ext Resource Name """
++ return "http://docs.ciscocloud.com/api/ext/novatenant/v1.0"
++
++ @classmethod
++ def get_updated(cls):
++ """ Returns Ext Resource Name """
+ return "2011-08-09T13:25:27-06:00"
- super(NovatenantsController, self).__init__(plugin)
++
++ @classmethod
++ def get_resources(cls):
++ """ Returns Ext Resource Name """
+ parent_resource = dict(member_name="tenant",
+ collection_name="extensions/csco/tenants")
+ member_actions = {'get_host': "PUT",
+ 'get_instance_port': "PUT"}
+ controller = NovatenantsController(QuantumManager.get_plugin())
+ return [extensions.ResourceExtension('novatenants', controller,
+ parent=parent_resource,
+ member_actions=member_actions)]
+
+
+class NovatenantsController(common.QuantumController):
+ """ Novatenant API controller
+ based on QuantumController """
+
+ _Novatenant_ops_param_list = [{
+ 'param-name': 'novatenant_name',
+ 'required': True}]
+
+ _get_host_ops_param_list = [{
+ 'param-name': 'instance_id',
+ 'required': True}, {
+ 'param-name': 'instance_desc',
+ 'required': True}]
+
+ _serialization_metadata = {
+ "application/xml": {
+ "attributes": {
+ "novatenant": ["id", "name"],
+ },
+ },
+ }
+
+ def __init__(self, plugin):
+ self._resource_name = 'novatenant'
- except exc.HTTPError as e:
- return faults.Fault(e)
++ 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"
+
++ # pylint: disable-msg=E1101,W0613
+ def show(self, request, tenant_id, id):
+ """ Returns novatenant details for the given novatenant id """
+ return "novatenant is a dummy resource"
+
+ def create(self, request, tenant_id):
+ """ Creates a new novatenant for a given tenant """
+ return "novatenant is a dummy resource"
+
+ def update(self, request, tenant_id, id):
+ """ Updates the name for the novatenant with the given id """
+ return "novatenant is a dummy resource"
+
+ def delete(self, request, tenant_id, id):
+ """ Destroys the Novatenant with the given id """
+ return "novatenant is a dummy resource"
+
+ #added for cisco's extension
+ def get_host(self, request, tenant_id, id):
+ content_type = request.best_match_content_type()
+ print "Content type:%s" % content_type
+
+ try:
+ req_params = \
+ self._parse_request_params(request,
+ self._get_host_ops_param_list)
- except exception.NovatenantNotFound as e:
- return faults.Fault(faults.NovatenantNotFound(e))
- except exception.PortNotFound as e:
- return faults.Fault(faults.PortNotFound(e))
++ except exc.HTTPError as exp:
++ return faults.Fault(exp)
+ instance_id = req_params['instance_id']
+
+ instance_desc = req_params['instance_desc']
+ try:
+ host = self._plugin.get_host(tenant_id, instance_id, instance_desc)
+ builder = novatenant_view.get_view_builder(request)
+ result = builder.build_host(host)
+ return result
+ #return exc.HTTPAccepted()
- #added for Cisco extension
++ except exception.NovatenantNotFound as exp:
++ return faults.Fault(faults.NovatenantNotFound(exp))
++ except exception.PortNotFound as exp:
++ return faults.Fault(faults.PortNotFound(exp))
+
- except exc.HTTPError as e:
- return faults.Fault(e)
+ def get_instance_port(self, request, tenant_id, id):
+ content_type = request.best_match_content_type()
+ print "Content type:%s" % content_type
+
+ try:
+ req_params = \
+ self._parse_request_params(request,
+ self._get_host_ops_param_list)
- return exc.HTTPAccepted()
- except exception.NovatenantNotFound as e:
- return faults.Fault(faults.NovatenantNotFound(e))
- except exception.PortNotFound as e:
- return faults.Fault(faults.PortNotFound(e))
++ except exc.HTTPError as exp:
++ return faults.Fault(exp)
+ instance_id = req_params['instance_id']
+
+ instance_desc = req_params['instance_desc']
+ try:
+ vif = self._plugin. \
+ get_instance_port(tenant_id, instance_id, instance_desc)
+ builder = novatenant_view.get_view_builder(request)
+ result = builder.build_vif(vif)
+ return result
+
++ except exception.NovatenantNotFound as exp:
++ return faults.Fault(faults.NovatenantNotFound(exp))
++ except exception.PortNotFound as exp:
++ return faults.Fault(faults.PortNotFound(exp))
--- /dev/null
- from quantum.common import wsgi
+"""
+# 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.
+#
+"""
+
+from webob import exc
+
+from extensions import _pprofiles as pprofiles_view
+from extensions import _exceptions as exception
+from extensions import _faults as faults
+
+from quantum.api import api_common as common
-
+from quantum.common import extensions
+from quantum.manager import QuantumManager
+
+
+class Portprofile(object):
-
- def get_name(self):
++ """extension class Portprofile"""
+ def __init__(self):
+ pass
-
- def get_alias(self):
++
++ @classmethod
++ def get_name(cls):
+ """ Returns Ext Resource Name """
+ return "Cisco Port Profile"
-
- def get_description(self):
++
++ @classmethod
++ def get_alias(cls):
+ """ Returns Ext Resource alias """
+ return "Cisco Port Profile"
-
- def get_namespace(self):
++
++ @classmethod
++ def get_description(cls):
+ """ Returns Ext Resource Description """
+ return "Portprofile include QoS information"
- return ""
-
- def get_updated(self):
++
++ @classmethod
++ def get_namespace(cls):
+ """ Returns Ext Resource Namespace """
-
- def get_resources(self):
++ return "http://docs.ciscocloud.com/api/ext/portprofile/v1.0"
++
++ @classmethod
++ def get_updated(cls):
+ """ Returns Ext Resource Updateed time """
+ return "2011-07-23T13:25:27-06:00"
-
++
++ @classmethod
++ def get_resources(cls):
+ """ Returns all defined resources """
+ parent_resource = dict(member_name="tenant",
+ collection_name="extensions/csco/tenants")
+ member_actions = {'associate_portprofile': "PUT",
+ 'disassociate_portprofile': "POST"}
+ controller = PortprofilesController(QuantumManager.get_plugin())
+ return [extensions.ResourceExtension('portprofiles', controller,
+ parent=parent_resource,
+ member_actions=member_actions)]
+
- _portprofile_ops_param_list = [{
++
+class PortprofilesController(common.QuantumController):
+ """ portprofile API controller
+ based on QuantumController """
++
++ def __init__(self, plugin):
++ self._resource_name = 'portprofile'
++ self._plugin = plugin
++ #super(PortprofilesController, self).__init__(plugin)
+
- _assignprofile_ops_param_list = [{
++ self._portprofile_ops_param_list = [{
+ 'param-name': 'portprofile_name',
+ 'required': True}, {
+ 'param-name': 'qos_name',
+ 'required': True}, {
+ 'param-name': 'assignment',
+ 'required': False}]
+
- _serialization_metadata = {
++ self._assignprofile_ops_param_list = [{
+ 'param-name': 'network-id',
+ 'required': True}, {
+ 'param-name': 'port-id',
+ 'required': True}]
+
-
- def __init__(self, plugin):
- self._resource_name = 'portprofile'
- self._plugin = plugin
- super(PortprofilesController, self).__init__(plugin)
-
++ self._serialization_metadata = {
+ "application/xml": {
+ "attributes": {
+ "portprofile": ["id", "name"],
+ },
+ },
+ }
- #TODO: this should be for a given tenant!!!
++
+ def index(self, request, tenant_id):
+ """ Returns a list of portprofile ids """
- except exception.PortprofileNotFound as e:
- return faults.Fault(faults.PortprofileNotFound(e))
- #return faults.Fault(e)
+ return self._items(request, tenant_id, is_detail=False)
+
+ def _items(self, request, tenant_id, is_detail):
+ """ Returns a list of portprofiles. """
+ portprofiles = self._plugin.get_all_portprofiles(tenant_id)
+ builder = pprofiles_view.get_view_builder(request)
+ result = [builder.build(portprofile, is_detail)['portprofile']
+ for portprofile in portprofiles]
+ return dict(portprofiles=result)
+
++ # pylint: disable-msg=E1101
+ def show(self, request, tenant_id, id):
+ """ Returns portprofile details for the given portprofile id """
+ try:
+ portprofile = self._plugin.get_portprofile_details(
+ tenant_id, id)
+ builder = pprofiles_view.get_view_builder(request)
+ #build response with details
+ result = builder.build(portprofile, True)
+ return dict(portprofiles=result)
- except exc.HTTPError as e:
- return faults.Fault(e)
++ 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 """
+ #look for portprofile name in request
+ try:
+ req_params = \
+ self._parse_request_params(request,
+ self._portprofile_ops_param_list)
- except exc.HTTPError as e:
- return faults.Fault(e)
++ except exc.HTTPError as exp:
++ return faults.Fault(exp)
+ portprofile = self._plugin.\
+ create_portprofile(tenant_id,
+ req_params['portprofile_name'],
+ req_params['qos_name'])
+ builder = pprofiles_view.get_view_builder(request)
+ result = builder.build(portprofile)
+ return dict(portprofiles=result)
+
+ def update(self, request, tenant_id, id):
+ """ Updates the name for the portprofile with the given id """
+ try:
+ req_params = \
+ self._parse_request_params(request,
+ self._portprofile_ops_param_list)
- except exception.PortprofileNotFound as e:
- return faults.Fault(faults.PortprofileNotFound(e))
++ except exc.HTTPError as exp:
++ return faults.Fault(exp)
+ try:
+ portprofile = self._plugin.\
+ rename_portprofile(tenant_id,
+ id, req_params['portprofile_name'])
+
+ builder = pprofiles_view.get_view_builder(request)
+ result = builder.build(portprofile, True)
+ return dict(portprofiles=result)
- except exception.PortprofileNotFound as e:
- return faults.Fault(faults.PortprofileNotFound(e))
++ except exception.PortprofileNotFound as exp:
++ return faults.Fault(faults.PortprofileNotFound(exp))
+
+ def delete(self, request, tenant_id, id):
+ """ Destroys the portprofile with the given id """
+ try:
+ self._plugin.delete_portprofile(tenant_id, id)
+ return exc.HTTPAccepted()
- #added for cisco's extension
++ except exception.PortprofileNotFound as exp:
++ return faults.Fault(faults.PortprofileNotFound(exp))
+
- except exc.HTTPError as e:
- return faults.Fault(e)
+ def associate_portprofile(self, request, tenant_id, id):
+ """ associate a portprofile to the port """
+ content_type = request.best_match_content_type()
+ print "Content type:%s" % content_type
+
+ try:
+ req_params = \
+ self._parse_request_params(request,
+ self._assignprofile_ops_param_list)
- except exception.PortprofileNotFound as e:
- return faults.Fault(faults.PortprofileNotFound(e))
- except exception.PortNotFound as e:
- return faults.Fault(faults.PortNotFound(e))
++ 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,
+ net_id, port_id,
+ id)
+ return exc.HTTPAccepted()
- #added for Cisco extension
++ except exception.PortprofileNotFound as exp:
++ return faults.Fault(faults.PortprofileNotFound(exp))
++ except exception.PortNotFound as exp:
++ return faults.Fault(faults.PortNotFound(exp))
+
- except exc.HTTPError as e:
- return faults.Fault(e)
+ def disassociate_portprofile(self, request, tenant_id, id):
+ """ Disassociate a portprofile from a port """
+ content_type = request.best_match_content_type()
+ print "Content type:%s" % content_type
+
+ try:
+ req_params = \
+ self._parse_request_params(request,
+ self._assignprofile_ops_param_list)
- except exception.PortprofileNotFound as e:
- return faults.Fault(faults.PortprofileNotFound(e))
- except exception.PortNotFound as e:
- return faults.Fault(faults.PortNotFound(e))
++ 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. \
+ disassociate_portprofile(tenant_id,
+ net_id, port_id, id)
+ return exc.HTTPAccepted()
++ except exception.PortprofileNotFound as exp:
++ return faults.Fault(faults.PortprofileNotFound(exp))
++ except exception.PortNotFound as exp:
++ return faults.Fault(faults.PortNotFound(exp))
--- /dev/null
- from quantum.common import wsgi
+"""
+# 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
+
+from webob import exc
+from extensions import _qos_view as qos_view
+from extensions import _exceptions as exception
+from extensions import _faults as faults
+
+from quantum.api import api_common as common
-
+from quantum.common import extensions
+from quantum.manager import QuantumManager
+
+LOG = logging.getLogger('quantum.api.qoss')
+
+
+class Qos(object):
-
- def get_name(self):
++ """Qos extension file"""
+ def __init__(self):
+ pass
- def get_alias(self):
++
++ @classmethod
++ def get_name(cls):
++ """ Returns Ext Resource Name """
+ return "Cisco qos"
+
- def get_description(self):
++ @classmethod
++ def get_alias(cls):
++ """ Returns Ext Resource Alias """
+ return "Cisco qos"
+
- def get_namespace(self):
- return ""
-
- def get_updated(self):
++ @classmethod
++ def get_description(cls):
++ """ Returns Ext Resource Description """
+ return "qos include username and password"
+
- def get_resources(self):
++ @classmethod
++ def get_namespace(cls):
++ """ Returns Ext Resource Namespace """
++ return "http://docs.ciscocloud.com/api/ext/qos/v1.0"
++
++ @classmethod
++ def get_updated(cls):
++ """ Returns Ext Resource update """
+ return "2011-07-25T13:25:27-06:00"
+
- super(QosController, self).__init__(plugin)
++ @classmethod
++ def get_resources(cls):
++ """ Returns Ext Resources """
+ parent_resource = dict(member_name="tenant",
+ collection_name="extensions/csco/tenants")
+
+ controller = QosController(QuantumManager.get_plugin())
+ return [extensions.ResourceExtension('qoss', controller,
+ parent=parent_resource)]
+
+
+class QosController(common.QuantumController):
+ """ qos API controller
+ based on QuantumController """
+
+ _qos_ops_param_list = [{
+ 'param-name': 'qos_name',
+ 'required': True}, {
+ 'param-name': 'qos_desc',
+ 'required': True}]
+ _serialization_metadata = {
+ "application/xml": {
+ "attributes": {
+ "qos": ["id", "name"],
+ },
+ },
+ }
+
+ def __init__(self, plugin):
+ self._resource_name = 'qos'
- #TODO: this should be for a given tenant!!!
++ self._plugin = plugin
++ #super(QosController, self).__init__(plugin)
+
+ def index(self, request, tenant_id):
+ """ Returns a list of qos ids """
- except exception.QosNotFound as e:
- return faults.Fault(faults.QosNotFound(e))
-
- #return faults.Fault(e)
+ return self._items(request, tenant_id, is_detail=False)
+
+ def _items(self, request, tenant_id, is_detail):
+ """ Returns a list of qoss. """
+ qoss = self._plugin.get_all_qoss(tenant_id)
+ builder = qos_view.get_view_builder(request)
+ result = [builder.build(qos, is_detail)['qos']
+ for qos in qoss]
+ return dict(qoss=result)
+
++ # pylint: disable-msg=E1101
+ def show(self, request, tenant_id, id):
+ """ Returns qos details for the given qos id """
+ try:
+ qos = self._plugin.get_qos_details(
+ tenant_id, id)
+ builder = qos_view.get_view_builder(request)
+ #build response with details
+ result = builder.build(qos, True)
+ return dict(qoss=result)
- except exc.HTTPError as e:
- return faults.Fault(e)
++ except exception.QosNotFound as exp:
++ return faults.Fault(faults.QosNotFound(exp))
+
+ def create(self, request, tenant_id):
+ """ Creates a new qos for a given tenant """
+ #look for qos name in request
+ try:
+ req_params = \
+ self._parse_request_params(request,
+ self._qos_ops_param_list)
- except exc.HTTPError as e:
- return faults.Fault(e)
++ except exc.HTTPError as exp:
++ return faults.Fault(exp)
+ qos = self._plugin.\
+ create_qos(tenant_id,
+ req_params['qos_name'],
+ req_params['qos_desc'])
+ builder = qos_view.get_view_builder(request)
+ result = builder.build(qos)
+ return dict(qoss=result)
+
+ def update(self, request, tenant_id, id):
+ """ Updates the name for the qos with the given id """
+ try:
+ req_params = \
+ self._parse_request_params(request,
+ self._qos_ops_param_list)
- except exception.QosNotFound as e:
- return faults.Fault(faults.QosNotFound(e))
++ except exc.HTTPError as exp:
++ return faults.Fault(exp)
+ try:
+ qos = self._plugin.\
+ rename_qos(tenant_id,
+ id, req_params['qos_name'])
+
+ builder = qos_view.get_view_builder(request)
+ result = builder.build(qos, True)
+ return dict(qoss=result)
- except exception.QosNotFound as e:
- return faults.Fault(faults.QosNotFound(e))
++ except exception.QosNotFound as exp:
++ return faults.Fault(faults.QosNotFound(exp))
+
+ def delete(self, request, tenant_id, id):
+ """ Destroys the qos with the given id """
+ try:
+ self._plugin.delete_qos(tenant_id, id)
+ return exc.HTTPAccepted()
++ except exception.QosNotFound as exp:
++ return faults.Fault(faults.QosNotFound(exp))
--- /dev/null
- _host = {'host_desc': {
+from quantum.common import exceptions as exc
+from extensions import _exceptions as extexc
+
+
+class CiscoPaloPlugin2(object):
+ """
+ This plugin has internal data structure
+ derived from quantum fakeplugin
+ """
+
+ #static data for networks and ports
+ _port_dict_1 = {
+ 1: {'port-id': 1,
+ 'port-state': 'DOWN',
+ 'attachment': None,
+ 'portprofile': None},
+ 2: {'port-id': 2,
+ 'port-state': 'UP',
+ 'attachment': None,
+ 'portprofile': None}}
+ _port_dict_2 = {
+ 1: {'port-id': 1,
+ 'port-state': 'UP',
+ 'attachment': 'SomeFormOfVIFID',
+ 'portprofile': '001'},
+ 2: {'port-id': 2,
+ 'port-state': 'DOWN',
+ 'attachment': None,
+ 'portprofile': '001'}}
+ _networks = {'001':
+ {
+ 'net-id': '001',
+ 'net-name': 'pippotest',
+ 'net-ports': _port_dict_1},
+ '002':
+ {
+ 'net-id': '002',
+ 'net-name': 'cicciotest',
+ 'net-ports': _port_dict_2}}
+ _portprofiles = {'001':
+ {
+ 'profile_id': '001',
+ 'profile_name': 'pprofiletest',
+ 'assignment': ['1', '2'],
+ 'qos_name': '001'},
+ '002':
+ {
+ 'profile_id': '002',
+ 'profile_name': 'cicciotest',
+ 'qos_name': '002',
+ 'assignment': None}}
+
+ _credentials = {'001':
+ {
+ 'credential_id': '001',
+ 'credential_name': 'cred1',
+ 'user_name': 'ying',
+ 'password': 'yingTest'},
+ '002':
+ {
+ 'credential_id': '002',
+ 'credential_name': 'cred2',
+ 'user_name': 'admin',
+ 'password': 'adminTest'}}
+ _qoss = {'001':
+ {
+ 'qos_id': '001',
+ 'qos_name': 'silver',
+ 'qos_desc': {'pps':170, 'TTL':20}},
+ '002':
+ {
+ 'qos_id': '002',
+ 'qos_name': 'gold',
+ 'qos_desc': {'pps':340, 'TTL':10}}}
+
++ _host = {'host_list': {
+ "host_key1": "host_value1",
+ "host_key2": "host_value2"}}
+ _vif = {'vif_desc': {
+ "vif_key1": "vif_value1",
+ "vif_key2": "vif_value2"}
+ }
+
+
+ supported_extension_aliases = ["Cisco Credential", "Cisco Port Profile", "Cisco qos", "Cisco Nova Tenant"]
+
+
+ """
+ def supports_extension(self, extension):
+ #return extension.get_alias() == "Cisco Port Profile"
+ return extension.get_alias() == "Cisco Credential"
+ """
+ def __init__(self):
+ CiscoPaloPlugin2._net_counter = \
+ len(CiscoPaloPlugin2._networks)
+
+ CiscoPaloPlugin2._profile_counter = \
+ len(CiscoPaloPlugin2._portprofiles)
+
+ CiscoPaloPlugin2._credential_counter = \
+ len(CiscoPaloPlugin2._credentials)
+
+ CiscoPaloPlugin2._qos_counter = \
+ len(CiscoPaloPlugin2._qoss)
+ def _get_network(self, tenant_id, network_id):
+
+ network = CiscoPaloPlugin2._networks.get(network_id)
+ if not network:
+ raise exc.NetworkNotFound(net_id=network_id)
+ return network
+
+
+
+ def _get_credential(self, tenant_id, credential_id):
+ credential = CiscoPaloPlugin2._credentials.get(credential_id)
+ if not credential:
+ raise extexc.CredentialNotFound(credential_id=credential_id)
+ return credential
+
+ def _get_qos(self, tenant_id, qos_id):
+ qos = CiscoPaloPlugin2._qoss.get(qos_id)
+ if not qos:
+ raise extexc.QosNotFound(qos_id=qos_id)
+ return qos
+
+ def _get_port(self, tenant_id, network_id, port_id):
+ net = self._get_network(tenant_id, network_id)
+ port = net['net-ports'].get(int(port_id))
+ if not port:
+ raise exc.PortNotFound(net_id=network_id, port_id=port_id)
+ return port
+
+ def _validate_port_state(self, port_state):
+ if port_state.upper() not in ('UP', 'DOWN'):
+ raise exc.StateInvalid(port_state=port_state)
+ return True
+
+ def _validate_attachment(self, tenant_id, network_id, port_id,
+ remote_interface_id):
+ network = self._get_network(tenant_id, network_id)
+ for port in network['net-ports'].values():
+ if port['attachment'] == remote_interface_id:
+ raise exc.AlreadyAttached(net_id=network_id,
+ port_id=port_id,
+ att_id=port['attachment'],
+ att_port_id=port['port-id'])
+
+ def get_all_networks(self, tenant_id):
+ """
+ Returns a dictionary containing all
+ <network_uuid, network_name> for
+ the specified tenant.
+ """
+ print("get_all_networks() called\n")
+ return CiscoPaloPlugin2._networks.values()
+
+ def get_network_details(self, tenant_id, net_id):
+ """
+ retrieved a list of all the remote vifs that
+ are attached to the network
+ """
+ print("get_network_details() called\n")
+ return self._get_network(tenant_id, net_id)
+
+ def create_network(self, tenant_id, net_name):
+ """
+ Creates a new Virtual Network, and assigns it
+ a symbolic name.
+ """
+ print("create_network() called\n")
+ CiscoPaloPlugin2._net_counter += 1
+ new_net_id = ("0" * (3 - len(str(CiscoPaloPlugin2._net_counter)))) + \
+ str(CiscoPaloPlugin2._net_counter)
+ print new_net_id
+ new_net_dict = {'net-id': new_net_id,
+ 'net-name': net_name,
+ 'net-ports': {}}
+ CiscoPaloPlugin2._networks[new_net_id] = new_net_dict
+ # return network_id of the created network
+ return new_net_dict
+
+ def delete_network(self, tenant_id, net_id):
+ """
+ Deletes the network with the specified network identifier
+ belonging to the specified tenant.
+ """
+ print("delete_network() called\n")
+ net = CiscoPaloPlugin2._networks.get(net_id)
+ # Verify that no attachments are plugged into the network
+ if net:
+ if net['net-ports']:
+ for port in net['net-ports'].values():
+ if port['attachment']:
+ raise exc.NetworkInUse(net_id=net_id)
+ CiscoPaloPlugin2._networks.pop(net_id)
+ return net
+ # Network not found
+ raise exc.NetworkNotFound(net_id=net_id)
+
+ def rename_network(self, tenant_id, net_id, new_name):
+ """
+ Updates the symbolic name belonging to a particular
+ Virtual Network.
+ """
+ print("rename_network() called\n")
+ net = self._get_network(tenant_id, net_id)
+ net['net-name'] = new_name
+ return net
+
+ def _get_portprofile(self, tenant_id, portprofile_id):
+ portprofile = CiscoPaloPlugin2._portprofiles.get(portprofile_id)
+ if not portprofile:
+ raise extexc.PortprofileNotFound(portprofile_id=portprofile_id)
+ return portprofile
+
+ def get_all_portprofiles(self, tenant_id):
+ """
+ Returns a dictionary containing all
+ <portprofile_uuid, portprofile_name> for
+ the specified tenant.
+ """
+ print("get_all_portprofiles() called\n")
+ return CiscoPaloPlugin2._portprofiles.values()
+
+ def get_portprofile_details(self, tenant_id, profile_id):
+ """
+ retrieved a list of all the remote vifs that
+ are attached to the portprofile
+ """
+ print("get_portprofile_details() called\n")
+ return self._get_portprofile(tenant_id, profile_id)
+
+ def create_portprofile(self, tenant_id, profile_name, vlan_id):
+ """
+ Creates a new Virtual portprofile, and assigns it
+ a symbolic name.
+ """
+ print("create_portprofile() called\n")
+ CiscoPaloPlugin2._profile_counter += 1
+ new_profile_id = ("0" * \
+ (3 - \
+ len(str(CiscoPaloPlugin2._profile_counter)))) + \
+ str(CiscoPaloPlugin2._profile_counter)
+ print new_profile_id
+ new_profile_dict = {'profile_id': new_profile_id,
+ 'profile_name': profile_name,
+ 'qos_name': vlan_id,
+ 'assignment': None}
+ CiscoPaloPlugin2._portprofiles[new_profile_id] = new_profile_dict
+ # return portprofile_id of the created portprofile
+ return new_profile_dict
+
+ def delete_portprofile(self, tenant_id, profile_id):
+ """
+ Deletes the portprofile with the specified portprofile identifier
+ belonging to the specified tenant.
+ """
+ print("delete_portprofile() called\n")
+ profile = CiscoPaloPlugin2._portprofiles.get(profile_id)
+ # Verify that no attachments are plugged into the portprofile
+ if profile:
+ CiscoPaloPlugin2._portprofiles.pop(profile_id)
+ return profile
+ # portprofile not found
+ raise extexc.PortprofileNotFound(profile_id=profile_id)
+
+ def rename_portprofile(self, tenant_id, profile_id, new_name):
+ """
+ Updates the symbolic name belonging to a particular
+ Virtual portprofile.
+ """
+ print("rename_portprofile() called\n")
+ profile = self._get_portprofile(tenant_id, profile_id)
+ profile['profile_name'] = new_name
+ return profile
+
+
+
+ def associate_portprofile(self, tenant_id, net_id, port_id, pprofile_id):
+ """
+ Assign portprofile to the specified port on the
+ specified Virtual Network.
+ """
+ print("assign_portprofile() called\n")
+ print("net_id " + net_id)
+ # Validate attachment
+ #self._validate_attachment(tenant_id, net_id, port_id,
+ # remote_interface_id)
+ #TODO: modify the exception
+ port = self._get_port(tenant_id, net_id, port_id)
+ if (not port['portprofile'] == None):
+ raise exc.PortInUse(net_id=net_id, port_id=port_id,
+ att_id=port['portprofile'])
+ port['portprofile'] = pprofile_id
+
+ def disassociate_portprofile(self, tenant_id, net_id, port_id, portprofile_id):
+ """
+ De-assign a portprofile from the specified port on the
+ specified Virtual Network.
+ """
+ print("deassign_portprofile() called\n")
+ #print("*******net_id is "+net_id)
+ port = self._get_port(tenant_id, net_id, port_id)
+
+ port['portprofile'] = None
+ #TODO:
+ #modify assignment[portprofile_id] to remove this port
+
+ #TODO: add new data structure to
+ #hold all the assignment for a specific portprofile
+ def get_portprofile_assignment(self, tenant_id, net_id, port_id):
+ print("get portprofile assignment called\n")
+ port = self._get_port(tenant_id, net_id, port_id)
+ ppid = port['portprofile']
+ if (ppid == None):
+ print("***no portprofile attached")
+ return "no portprofile attached"
+ else:
+ print("***attached portprofile id is " + ppid)
+ return ("attached portprofile " + ppid)
+
+
+ def get_all_credentials(self, tenant_id):
+ """
+ Returns a dictionary containing all
+ <credential_id, credential_name> for
+ the specified tenant.
+ """
+ print("get_all_credentials() called\n")
+ return CiscoPaloPlugin2._credentials.values()
+
+ def get_credential_details(self, tenant_id, credential_id):
+ """
+ retrieved a list of all the remote vifs that
+ are attached to the credential
+ """
+ print("get_credential_details() called\n")
+ return self._get_credential(tenant_id, credential_id)
+
+ def create_credential(self, tenant_id, credential_name, user_name, password):
+ """
+ Creates a new Virtual credential, and assigns it
+ a symbolic name.
+ """
+ print("create_credential() called\n")
+ CiscoPaloPlugin2._credential_counter += 1
+ new_credential_id = ("0" * \
+ (3 - \
+ len(str(CiscoPaloPlugin2._credential_counter)))) + \
+ str(CiscoPaloPlugin2._credential_counter)
+ print new_credential_id
+ new_credential_dict = {'credential_id': new_credential_id,
+ 'credential_name': credential_name,
+ 'user_name': user_name,
+ 'password': password}
+ CiscoPaloPlugin2._credentials[new_credential_id] = new_credential_dict
+ # return credential_id of the created credential
+ return new_credential_dict
+
+ def delete_credential(self, tenant_id, credential_id):
+ """
+ Deletes the credential with the specified credential identifier
+ belonging to the specified tenant.
+ """
+ print("delete_credential() called\n")
+ credential = CiscoPaloPlugin2._credentials.get(credential_id)
+
+ if credential:
+ CiscoPaloPlugin2._credentials.pop(credential_id)
+ return credential
+ # credential not found
+ raise extexc.CredentialNotFound(credential_id=credential_id)
+
+ def rename_credential(self, tenant_id, credential_id, new_name):
+ """
+ Updates the symbolic name belonging to a particular
+ Virtual credential.
+ """
+ print("rename_credential() called\n")
+ credential = self._get_credential(tenant_id, credential_id)
+ credential['credential_name'] = new_name
+ return credential
+
+
+ def get_all_qoss(self, tenant_id):
+ """
+ Returns a dictionary containing all
+ <qos_id, qos_name> for
+ the specified tenant.
+ """
+ print("get_all_qoss() called\n")
+ return CiscoPaloPlugin2._qoss.values()
+
+ def get_qos_details(self, tenant_id, qos_id):
+ """
+ retrieved a list of all the remote vifs that
+ are attached to the qos
+ """
+ print("get_qos_details() called\n")
+ return self._get_qos(tenant_id, qos_id)
+
+ def create_qos(self, tenant_id, qos_name, qos_desc):
+ """
+ Creates a new Virtual qos, and assigns it
+ a symbolic name.
+ """
+ print("create_qos() called\n")
+ CiscoPaloPlugin2._qos_counter += 1
+ new_qos_id = ("0" * \
+ (3 - \
+ len(str(CiscoPaloPlugin2._qos_counter)))) + \
+ str(CiscoPaloPlugin2._qos_counter)
+ print new_qos_id
+ new_qos_dict = {'qos_id': new_qos_id,
+ 'qos_name': qos_name,
+ 'qos_desc': qos_desc}
+
+ print("************************")
+ print("test dictionary data")
+ print(qos_desc['TTL'])
+ print("************************")
+
+ CiscoPaloPlugin2._qoss[new_qos_id] = new_qos_dict
+ # return qos_id of the created qos
+ return new_qos_dict
+
+ def delete_qos(self, tenant_id, qos_id):
+ """
+ Deletes the qos with the specified qos identifier
+ belonging to the specified tenant.
+ """
+ print("delete_qos() called\n")
+ qos = CiscoPaloPlugin2._qoss.get(qos_id)
+ # Verify that no attachments are plugged into the qos
+ if qos:
+ CiscoPaloPlugin2._qoss.pop(qos_id)
+ return qos
+ # qos not found
+ raise extexc.QosNotFound(qos_id=qos_id)
+
+ def rename_qos(self, tenant_id, qos_id, new_name):
+ """
+ Updates the symbolic name belonging to a particular
+ Virtual qos.
+ """
+ print("rename_qos() called\n")
+ qos = self._get_qos(tenant_id, qos_id)
+ qos['qos_name'] = new_name
+ return qos
+
+
+
+
+ def get_all_ports(self, tenant_id, net_id):
+ """
+ Retrieves all port identifiers belonging to the
+ specified Virtual Network.
+ """
+ print("get_all_ports() called\n")
+ network = self._get_network(tenant_id, net_id)
+ ports_on_net = network['net-ports'].values()
+ return ports_on_net
+
+ def get_port_details(self, tenant_id, net_id, port_id):
+ """
+ This method allows the user to retrieve a remote interface
+ that is attached to this particular port.
+ """
+ print("get_port_details() called\n")
+ return self._get_port(tenant_id, net_id, port_id)
+
+ def create_port(self, tenant_id, net_id, port_state=None):
+ """
+ Creates a port on the specified Virtual Network.
+ """
+ print("create_port() called\n")
+ net = self._get_network(tenant_id, net_id)
+ # check port state
+ # TODO(salvatore-orlando): Validate port state in API?
+ self._validate_port_state(port_state)
+ ports = net['net-ports']
+ new_port_id = max(ports.keys()) + 1
+ new_port_dict = {'port-id': new_port_id,
+ 'port-state': port_state,
+ 'attachment': None,
+ 'portprofile': None}
+ ports[new_port_id] = new_port_dict
+ return new_port_dict
+
+ def update_port(self, tenant_id, net_id, port_id, port_state):
+ """
+ Updates the state of a port on the specified Virtual Network.
+ """
+ print("create_port() called\n")
+ port = self._get_port(tenant_id, net_id, port_id)
+ self._validate_port_state(port_state)
+ port['port-state'] = port_state
+ return port
+
+ def delete_port(self, tenant_id, net_id, port_id):
+ """
+ Deletes a port on a specified Virtual Network,
+ if the port contains a remote interface attachment,
+ the remote interface is first un-plugged and then the port
+ is deleted.
+ """
+ print("delete_port() called\n")
+ net = self._get_network(tenant_id, net_id)
+ port = self._get_port(tenant_id, net_id, port_id)
+ if port['attachment']:
+ raise exc.PortInUse(net_id=net_id, port_id=port_id,
+ att_id=port['attachment'])
+ try:
+ net['net-ports'].pop(int(port_id))
+ except KeyError:
+ raise exc.PortNotFound(net_id=net_id, port_id=port_id)
+
+ def get_interface_details(self, tenant_id, net_id, port_id):
+ print("get interface detail called\n")
+ port = self._get_port(tenant_id, net_id, port_id)
+ vid = port['attachment']
+ if (vid == None):
+ print("***no interface is attached")
+ return "no interface attached"
+ else:
+ print("***interface id is " + vid)
+ return ("attached interface " + vid)
+
+ def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id):
+ """
+ Attaches a remote interface to the specified port on the
+ specified Virtual Network.
+ """
+ print("plug_interface() called\n")
+ # Validate attachment
+ self._validate_attachment(tenant_id, net_id, port_id,
+ remote_interface_id)
+ port = self._get_port(tenant_id, net_id, port_id)
+ if port['attachment']:
+ raise exc.PortInUse(net_id=net_id, port_id=port_id,
+ att_id=port['attachment'])
+ port['attachment'] = remote_interface_id
+
+ def unplug_interface(self, tenant_id, net_id, port_id):
+ """
+ Detaches a remote interface from the specified port on the
+ specified Virtual Network.
+ """
+ print("unplug_interface() called\n")
+ port = self._get_port(tenant_id, net_id, port_id)
+ # TODO(salvatore-orlando):
+ # Should unplug on port without attachment raise an Error?
+ port['attachment'] = None
+
+ def get_host(self, tenant_id, instance_id, instance_desc):
+ print("associate an instance to a port....")
+ print("get key2: " + instance_desc['key2'])
+ return CiscoPaloPlugin2._host
+ def get_instance_port(self, tenant_id, instance_id, instance_desc):
+ print("get instance associated port....")
+ print("get key1: " + instance_desc['key1'])
+ return CiscoPaloPlugin2._vif
res_ext = extensions.ResourceExtension('tweedles',
self.ResourceExtensionController())
test_app = setup_extensions_test_app(SimpleExtensionManager(res_ext))
--
index_response = test_app.get("/tweedles")
self.assertEqual(200, index_response.status_int)
self.assertEqual("resource index", index_response.body)
--
++
show_response = test_app.get("/tweedles/25266")
self.assertEqual({'data': {'id': "25266"}}, show_response.json)
--
++
def test_resource_extension_with_custom_member_action(self):
controller = self.ResourceExtensionController()
member = {'custom_member_action': "GET"}