Merge "Remove Cisco Meta and N1KV monolithic plugins"

This commit is contained in:
Jenkins 2015-09-05 18:50:51 +00:00 committed by Gerrit Code Review
commit 64c596a6c1
36 changed files with 45 additions and 8799 deletions

View File

@ -1,107 +0,0 @@
[cisco]
# (StrOpt) A short prefix to prepend to the VLAN number when creating a
# VLAN interface. For example, if an interface is being created for
# VLAN 2001 it will be named 'q-2001' using the default prefix.
#
# vlan_name_prefix = q-
# Example: vlan_name_prefix = vnet-
# (StrOpt) A short prefix to prepend to the VLAN number when creating a
# provider VLAN interface. For example, if an interface is being created
# for provider VLAN 3003 it will be named 'p-3003' using the default prefix.
#
# provider_vlan_name_prefix = p-
# Example: provider_vlan_name_prefix = PV-
# (BoolOpt) A flag indicating whether Openstack networking should manage the
# creation and removal of VLAN interfaces for provider networks on the Nexus
# switches. If the flag is set to False then Openstack will not create or
# remove VLAN interfaces for provider networks, and the administrator needs
# to manage these interfaces manually or by external orchestration.
#
# provider_vlan_auto_create = True
# (BoolOpt) A flag indicating whether Openstack networking should manage
# the adding and removing of provider VLANs from trunk ports on the Nexus
# switches. If the flag is set to False then Openstack will not add or
# remove provider VLANs from trunk ports, and the administrator needs to
# manage these operations manually or by external orchestration.
#
# provider_vlan_auto_trunk = True
# (StrOpt) Period-separated module path to the model class to use for
# the Cisco neutron plugin.
#
# model_class = neutron.plugins.cisco.models.virt_phy_sw_v2.VirtualPhysicalSwitchModelV2
# (BoolOpt) A flag to enable Layer 3 support on the Nexus switches.
# Note: This feature is not supported on all models/versions of Cisco
# Nexus switches. To use this feature, all of the Nexus switches in the
# deployment must support it.
# nexus_l3_enable = False
# (BoolOpt) A flag to enable round robin scheduling of routers for SVI.
# svi_round_robin = False
# Cisco Nexus Switch configurations.
# Each switch to be managed by Openstack Neutron must be configured here.
#
# N1KV Format.
# [N1KV:<IP address of VSM>]
# username=<credential username>
# password=<credential password>
#
# Example:
# [N1KV:2.2.2.2]
# username=admin
# password=mySecretPassword
[cisco_n1k]
# (StrOpt) Specify the name of the integration bridge to which the VIFs are
# attached.
# Default value: br-int
# integration_bridge = br-int
# (StrOpt) Name of the policy profile to be associated with a port when no
# policy profile is specified during port creates.
# Default value: service_profile
# default_policy_profile = service_profile
# (StrOpt) Name of the policy profile to be associated with a port owned by
# network node (dhcp, router).
# Default value: dhcp_pp
# network_node_policy_profile = dhcp_pp
# (StrOpt) Name of the network profile to be associated with a network when no
# network profile is specified during network creates. Admin should pre-create
# a network profile with this name.
# Default value: default_network_profile
# default_network_profile = network_pool
# (IntOpt) Time in seconds for which the plugin polls the VSM for updates in
# policy profiles.
# Default value: 60
# poll_duration = 60
# (BoolOpt) Specify whether tenants are restricted from accessing all the
# policy profiles.
# Default value: False, indicating all tenants can access all policy profiles.
#
# restrict_policy_profiles = False
# (IntOpt) Number of threads to use to make HTTP requests to the VSM.
# Default value: 4
# http_pool_size = 4
# (IntOpt) Timeout duration in seconds for the http request
# Default value: 15
# http_timeout = 15
# (BoolOpt) Specify whether tenants are restricted from accessing network
# profiles belonging to other tenants.
# Default value: True, indicating other tenants cannot access network
# profiles belonging to a tenant.
#
# restrict_network_profiles = True

View File

@ -1,2 +1,2 @@
11926bcfe72d
34af2b5c5a59
4af11ca47297

View File

@ -0,0 +1,44 @@
# Copyright 2015 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
"""Drop cisco monolithic tables
Revision ID: 4af11ca47297
Revises: 11926bcfe72d
Create Date: 2015-08-13 08:01:19.709839
"""
# revision identifiers, used by Alembic.
revision = '4af11ca47297'
down_revision = '11926bcfe72d'
from alembic import op
def upgrade():
op.drop_table('cisco_n1kv_port_bindings')
op.drop_table('cisco_n1kv_network_bindings')
op.drop_table('cisco_n1kv_multi_segments')
op.drop_table('cisco_provider_networks')
op.drop_table('cisco_n1kv_trunk_segments')
op.drop_table('cisco_n1kv_vmnetworks')
op.drop_table('cisco_n1kv_profile_bindings')
op.drop_table('cisco_qos_policies')
op.drop_table('cisco_credentials')
op.drop_table('cisco_n1kv_vlan_allocations')
op.drop_table('cisco_n1kv_vxlan_allocations')
op.drop_table('cisco_network_profiles')
op.drop_table('cisco_policy_profiles')

View File

@ -51,8 +51,6 @@ from neutron.plugins.bigswitch.db import consistency_db # noqa
from neutron.plugins.bigswitch import routerrule_db # noqa
from neutron.plugins.brocade.db import models as brocade_models # noqa
from neutron.plugins.cisco.db.l3 import l3_models # noqa
from neutron.plugins.cisco.db import n1kv_models_v2 # noqa
from neutron.plugins.cisco.db import network_models_v2 # noqa
from neutron.plugins.ml2.drivers.brocade.db import ( # noqa
models as ml2_brocade_models)
from neutron.plugins.ml2.drivers import type_flat # noqa

View File

@ -1,7 +0,0 @@
Cisco Neutron Virtual Network Plugin
This plugin implements Neutron v2 APIs and helps configure
topologies consisting of virtual and physical switches.
For more details on use please refer to:
http://wiki.openstack.org/cisco-neutron

View File

@ -13,96 +13,7 @@
# under the License.
# Attachment attributes
INSTANCE_ID = 'instance_id'
TENANT_ID = 'tenant_id'
TENANT_NAME = 'tenant_name'
HOST_NAME = 'host_name'
# Network attributes
NET_ID = 'id'
NET_NAME = 'name'
NET_VLAN_ID = 'vlan_id'
NET_VLAN_NAME = 'vlan_name'
NET_PORTS = 'ports'
CREDENTIAL_ID = 'credential_id'
CREDENTIAL_NAME = 'credential_name'
CREDENTIAL_USERNAME = 'user_name'
CREDENTIAL_PASSWORD = 'password'
CREDENTIAL_TYPE = 'type'
MASKED_PASSWORD = '********'
USERNAME = 'username'
PASSWORD = 'password'
LOGGER_COMPONENT_NAME = "cisco_plugin"
VSWITCH_PLUGIN = 'vswitch_plugin'
DEVICE_IP = 'device_ip'
NETWORK_ADMIN = 'network_admin'
NETWORK = 'network'
PORT = 'port'
BASE_PLUGIN_REF = 'base_plugin_ref'
CONTEXT = 'context'
SUBNET = 'subnet'
#### N1Kv CONSTANTS
# Special vlan_id value in n1kv_vlan_allocations table indicating flat network
FLAT_VLAN_ID = -1
# Topic for tunnel notifications between the plugin and agent
TUNNEL = 'tunnel'
# Maximum VXLAN range configurable for one network profile.
MAX_VXLAN_RANGE = 1000000
# Values for network_type
NETWORK_TYPE_FLAT = 'flat'
NETWORK_TYPE_VLAN = 'vlan'
NETWORK_TYPE_VXLAN = 'vxlan'
NETWORK_TYPE_LOCAL = 'local'
NETWORK_TYPE_NONE = 'none'
NETWORK_TYPE_TRUNK = 'trunk'
NETWORK_TYPE_MULTI_SEGMENT = 'multi-segment'
# Values for network sub_type
NETWORK_TYPE_OVERLAY = 'overlay'
NETWORK_SUBTYPE_NATIVE_VXLAN = 'native_vxlan'
NETWORK_SUBTYPE_TRUNK_VLAN = NETWORK_TYPE_VLAN
NETWORK_SUBTYPE_TRUNK_VXLAN = NETWORK_TYPE_OVERLAY
# Prefix for VM Network name
VM_NETWORK_NAME_PREFIX = 'vmn_'
SET = 'set'
INSTANCE = 'instance'
PROPERTIES = 'properties'
NAME = 'name'
ID = 'id'
POLICY = 'policy'
TENANT_ID_NOT_SET = 'TENANT_ID_NOT_SET'
ENCAPSULATIONS = 'encapsulations'
STATE = 'state'
ONLINE = 'online'
MAPPINGS = 'mappings'
MAPPING = 'mapping'
SEGMENTS = 'segments'
SEGMENT = 'segment'
BRIDGE_DOMAIN_SUFFIX = '_bd'
LOGICAL_NETWORK_SUFFIX = '_log_net'
ENCAPSULATION_PROFILE_SUFFIX = '_profile'
UUID_LENGTH = 36
# N1KV vlan and vxlan segment range
N1KV_VLAN_RESERVED_MIN = 3968
N1KV_VLAN_RESERVED_MAX = 4047
N1KV_VXLAN_MIN = 4096
N1KV_VXLAN_MAX = 16000000
# Type and topic for Cisco cfg agent
# ==================================
@ -112,7 +23,3 @@ AGENT_TYPE_CFG = 'Cisco cfg agent'
CFG_AGENT = 'cisco_cfg_agent'
# Topic for routing service helper in Cisco configuration agent
CFG_AGENT_L3_ROUTING = 'cisco_cfg_agent_l3_routing'
# Values for network profile fields
ADD_TENANTS = 'add_tenants'
REMOVE_TENANTS = 'remove_tenants'

View File

@ -1,53 +0,0 @@
# Copyright 2012 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.
from neutron.plugins.cisco.common import cisco_constants as const
from neutron.plugins.cisco.common import cisco_exceptions as cexc
from neutron.plugins.cisco.common import config
from neutron.plugins.cisco.db import network_db_v2 as cdb
class Store(object):
"""Credential Store."""
@staticmethod
def initialize():
dev_dict = config.get_device_dictionary()
for key in dev_dict:
dev_id, dev_ip, dev_key = key
if dev_key == const.USERNAME:
try:
cdb.add_credential(
dev_ip,
dev_dict[dev_id, dev_ip, const.USERNAME],
dev_dict[dev_id, dev_ip, const.PASSWORD],
dev_id)
except cexc.CredentialAlreadyExists:
# We are quietly ignoring this, since it only happens
# if this class module is loaded more than once, in
# which case, the credentials are already populated
pass
@staticmethod
def get_username(cred_name):
"""Get the username."""
credential = cdb.get_credential_name(cred_name)
return credential[const.CREDENTIAL_USERNAME]
@staticmethod
def get_password(cred_name):
"""Get the password."""
credential = cdb.get_credential_name(cred_name)
return credential[const.CREDENTIAL_PASSWORD]

View File

@ -1,236 +0,0 @@
# 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.
"""Exceptions used by the Cisco plugin."""
from neutron.common import exceptions
class NetworkSegmentIDNotFound(exceptions.NeutronException):
"""Segmentation ID for network is not found."""
message = _("Segmentation ID for network %(net_id)s is not found.")
class NoMoreNics(exceptions.NeutronException):
"""No more dynamic NICs are available in the system."""
message = _("Unable to complete operation. No more dynamic NICs are "
"available in the system.")
class NetworkVlanBindingAlreadyExists(exceptions.NeutronException):
"""Binding cannot be created, since it already exists."""
message = _("NetworkVlanBinding for %(vlan_id)s and network "
"%(network_id)s already exists.")
class VlanIDNotFound(exceptions.NeutronException):
"""VLAN ID cannot be found."""
message = _("Vlan ID %(vlan_id)s not found.")
class VlanIDOutsidePool(exceptions.NeutronException):
"""VLAN ID cannot be allocated, since it is outside the configured pool."""
message = _("Unable to complete operation. VLAN ID exists outside of the "
"configured network segment range.")
class VlanIDNotAvailable(exceptions.NeutronException):
"""No VLAN ID available."""
message = _("No Vlan ID available.")
class QosNotFound(exceptions.NeutronException):
"""QoS level with this ID cannot be found."""
message = _("QoS level %(qos_id)s could not be found "
"for tenant %(tenant_id)s.")
class QosNameAlreadyExists(exceptions.NeutronException):
"""QoS Name already exists."""
message = _("QoS level with name %(qos_name)s already exists "
"for tenant %(tenant_id)s.")
class CredentialNotFound(exceptions.NeutronException):
"""Credential with this ID cannot be found."""
message = _("Credential %(credential_id)s could not be found.")
class CredentialNameNotFound(exceptions.NeutronException):
"""Credential Name could not be found."""
message = _("Credential %(credential_name)s could not be found.")
class CredentialAlreadyExists(exceptions.NeutronException):
"""Credential already exists."""
message = _("Credential %(credential_name)s already exists.")
class ProviderNetworkExists(exceptions.NeutronException):
"""Provider network already exists."""
message = _("Provider network %s already exists")
class NexusComputeHostNotConfigured(exceptions.NeutronException):
"""Connection to compute host is not configured."""
message = _("Connection to %(host)s is not configured.")
class NexusConnectFailed(exceptions.NeutronException):
"""Failed to connect to Nexus switch."""
message = _("Unable to connect to Nexus %(nexus_host)s. Reason: %(exc)s.")
class NexusConfigFailed(exceptions.NeutronException):
"""Failed to configure Nexus switch."""
message = _("Failed to configure Nexus: %(config)s. Reason: %(exc)s.")
class NexusPortBindingNotFound(exceptions.NeutronException):
"""NexusPort Binding is not present."""
message = _("Nexus Port Binding (%(filters)s) is not present.")
def __init__(self, **kwargs):
filters = ','.join('%s=%s' % i for i in kwargs.items())
super(NexusPortBindingNotFound, self).__init__(filters=filters)
class NoNexusSviSwitch(exceptions.NeutronException):
"""No usable nexus switch found."""
message = _("No usable Nexus switch found to create SVI interface.")
class PortVnicBindingAlreadyExists(exceptions.NeutronException):
"""PortVnic Binding already exists."""
message = _("PortVnic Binding %(port_id)s already exists.")
class PortVnicNotFound(exceptions.NeutronException):
"""PortVnic Binding is not present."""
message = _("PortVnic Binding %(port_id)s is not present.")
class SubnetNotSpecified(exceptions.NeutronException):
"""Subnet id not specified."""
message = _("No subnet_id specified for router gateway.")
class SubnetInterfacePresent(exceptions.NeutronException):
"""Subnet SVI interface already exists."""
message = _("Subnet %(subnet_id)s has an interface on %(router_id)s.")
class PortIdForNexusSvi(exceptions.NeutronException):
"""Port Id specified for Nexus SVI."""
message = _('Nexus hardware router gateway only uses Subnet Ids.')
class InvalidDetach(exceptions.NeutronException):
message = _("Unable to unplug the attachment %(att_id)s from port "
"%(port_id)s for network %(net_id)s. The attachment "
"%(att_id)s does not exist.")
class PolicyProfileAlreadyExists(exceptions.NeutronException):
"""Policy Profile cannot be created since it already exists."""
message = _("Policy Profile %(profile_id)s "
"already exists.")
class PolicyProfileIdNotFound(exceptions.NotFound):
"""Policy Profile with the given UUID cannot be found."""
message = _("Policy Profile %(profile_id)s could not be found.")
class PolicyProfileNameNotFound(exceptions.NotFound):
"""Policy Profile with the given name cannot be found."""
message = _("Policy Profile %(profile_name)s could not be found.")
class NetworkProfileAlreadyExists(exceptions.NeutronException):
"""Network Profile cannot be created since it already exists."""
message = _("Network Profile %(profile_id)s "
"already exists.")
class NetworkProfileNotFound(exceptions.NotFound):
"""Network Profile with the given UUID/name cannot be found."""
message = _("Network Profile %(profile)s could not be found.")
class NetworkProfileInUse(exceptions.InUse):
"""Network Profile with the given UUID is in use."""
message = _("One or more network segments belonging to network "
"profile %(profile)s is in use.")
class NoMoreNetworkSegments(exceptions.NoNetworkAvailable):
"""Network segments exhausted for the given network profile."""
message = _("No more segments available in network segment pool "
"%(network_profile_name)s.")
class VMNetworkNotFound(exceptions.NotFound):
"""VM Network with the given name cannot be found."""
message = _("VM Network %(name)s could not be found.")
class VxlanIDInUse(exceptions.InUse):
"""VXLAN ID is in use."""
message = _("Unable to create the network. "
"The VXLAN ID %(vxlan_id)s is in use.")
class VxlanIDNotFound(exceptions.NotFound):
"""VXLAN ID cannot be found."""
message = _("Vxlan ID %(vxlan_id)s not found.")
class VxlanIDOutsidePool(exceptions.NeutronException):
"""VXLAN ID cannot be allocated, as it is outside the configured pool."""
message = _("Unable to complete operation. VXLAN ID exists outside of the "
"configured network segment range.")
class VSMConnectionFailed(exceptions.ServiceUnavailable):
"""Connection to VSM failed."""
message = _("Connection to VSM failed: %(reason)s.")
class VSMError(exceptions.NeutronException):
"""Error has occurred on the VSM."""
message = _("Internal VSM Error: %(reason)s.")
class NetworkBindingNotFound(exceptions.NotFound):
"""Network Binding for network cannot be found."""
message = _("Network Binding for network %(network_id)s could "
"not be found.")
class PortBindingNotFound(exceptions.NotFound):
"""Port Binding for port cannot be found."""
message = _("Port Binding for port %(port_id)s could "
"not be found.")
class ProfileTenantBindingNotFound(exceptions.NotFound):
"""Profile to Tenant binding for given profile ID cannot be found."""
message = _("Profile-Tenant binding for profile %(profile_id)s could "
"not be found.")
class NoClusterFound(exceptions.NotFound):
"""No service cluster found to perform multi-segment bridging."""
message = _("No service cluster found to perform multi-segment bridging.")

View File

@ -1,134 +0,0 @@
# 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.
import webob.dec
from neutron import wsgi
class Fault(webob.exc.HTTPException):
"""Error codes for API faults."""
_fault_names = {
400: "malformedRequest",
401: "unauthorized",
451: "CredentialNotFound",
452: "QoSNotFound",
453: "NovatenantNotFound",
454: "MultiportNotFound",
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.
Response is generated 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, "neutronServiceFault")
fault_data = {
fault_name: {
'code': code,
'message': self.wrapped_exc.explanation}}
# 'code' is an attribute on the fault tag itself
content_type = req.best_match_content_type()
self.wrapped_exc.body = wsgi.Serializer().serialize(
fault_data, content_type)
self.wrapped_exc.content_type = content_type
return self.wrapped_exc
class PortNotFound(webob.exc.HTTPClientError):
"""PortNotFound exception.
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):
"""CredentialNotFound exception.
subclass of :class:`~HTTPClientError`
This indicates that the server did not find the Credential specified
in the HTTP request
code: 451, 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):
"""QosNotFound exception.
subclass of :class:`~HTTPClientError`
This indicates that the server did not find the QoS specified
in the HTTP request
code: 452, 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):
"""NovatenantNotFound exception.
subclass of :class:`~HTTPClientError`
This indicates that the server did not find the Novatenant specified
in the HTTP request
code: 453, 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):
"""RequestedStateInvalid exception.
subclass of :class:`~HTTPClientError`
This indicates that the server could not update the port state
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.')

View File

@ -1,138 +0,0 @@
# Copyright 2013 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
cisco_opts = [
cfg.StrOpt('vlan_name_prefix', default='q-',
help=_("VLAN Name prefix")),
cfg.StrOpt('provider_vlan_name_prefix', default='p-',
help=_("VLAN Name prefix for provider vlans")),
cfg.BoolOpt('provider_vlan_auto_create', default=True,
help=_('Provider VLANs are automatically created as needed '
'on the Nexus switch')),
cfg.BoolOpt('provider_vlan_auto_trunk', default=True,
help=_('Provider VLANs are automatically trunked as needed '
'on the ports of the Nexus switch')),
cfg.BoolOpt('nexus_l3_enable', default=False,
help=_("Enable L3 support on the Nexus switches")),
cfg.BoolOpt('svi_round_robin', default=False,
help=_("Distribute SVI interfaces over all switches")),
cfg.StrOpt('model_class',
default='neutron.plugins.cisco.models.virt_phy_sw_v2.'
'VirtualPhysicalSwitchModelV2',
help=_("Model Class")),
]
cisco_n1k_opts = [
cfg.StrOpt('integration_bridge', default='br-int',
help=_("N1K Integration Bridge")),
cfg.BoolOpt('enable_tunneling', default=True,
help=_("N1K Enable Tunneling")),
cfg.StrOpt('tunnel_bridge', default='br-tun',
help=_("N1K Tunnel Bridge")),
cfg.StrOpt('local_ip', default='10.0.0.3',
help=_("N1K Local IP")),
cfg.StrOpt('tenant_network_type', default='local',
help=_("N1K Tenant Network Type")),
cfg.StrOpt('bridge_mappings', default='',
help=_("N1K Bridge Mappings")),
cfg.StrOpt('vxlan_id_ranges', default='5000:10000',
help=_("N1K VXLAN ID Ranges")),
cfg.StrOpt('network_vlan_ranges', default='vlan:1:4095',
help=_("N1K Network VLAN Ranges")),
cfg.StrOpt('default_network_profile', default='default_network_profile',
help=_("N1K default network profile")),
cfg.StrOpt('default_policy_profile', default='service_profile',
help=_("N1K default policy profile")),
cfg.StrOpt('network_node_policy_profile', default='dhcp_pp',
help=_("N1K policy profile for network node")),
cfg.IntOpt('poll_duration', default=60,
help=_("N1K Policy profile polling duration in seconds")),
cfg.BoolOpt('restrict_policy_profiles', default=False,
help=_("Restrict the visibility of policy profiles to the "
"tenants")),
cfg.IntOpt('http_pool_size', default=4,
help=_("Number of threads to use to make HTTP requests")),
cfg.IntOpt('http_timeout', default=15,
help=_("N1K http timeout duration in seconds")),
cfg.BoolOpt('restrict_network_profiles', default=True,
help=_("Restrict tenants from accessing network profiles "
"belonging to some other tenant")),
]
cfg.CONF.register_opts(cisco_opts, "CISCO")
cfg.CONF.register_opts(cisco_n1k_opts, "CISCO_N1K")
# shortcuts
CONF = cfg.CONF
CISCO = cfg.CONF.CISCO
CISCO_N1K = cfg.CONF.CISCO_N1K
#
# device_dictionary - Contains all external device configuration.
#
# When populated the device dictionary format is:
# {('<device ID>', '<device ipaddr>', '<keyword>'): '<value>', ...}
#
# Example:
# {('NEXUS_SWITCH', '1.1.1.1', 'username'): 'admin',
# ('NEXUS_SWITCH', '1.1.1.1', 'password'): 'mySecretPassword',
# ('NEXUS_SWITCH', '1.1.1.1', 'compute1'): '1/1', ...}
#
device_dictionary = {}
#
# first_device_ip - IP address of first switch discovered in config
#
# Used for SVI placement when round-robin placement is disabled
#
first_device_ip = None
class CiscoConfigOptions(object):
"""Cisco Configuration Options Class."""
def __init__(self):
self._create_device_dictionary()
def _create_device_dictionary(self):
"""
Create the device dictionary from the cisco_plugins.ini
device supported sections. Ex. NEXUS_SWITCH, N1KV.
"""
global first_device_ip
multi_parser = cfg.MultiConfigParser()
read_ok = multi_parser.read(CONF.config_file)
if len(read_ok) != len(CONF.config_file):
raise cfg.Error(_("Some config files were not parsed properly"))
first_device_ip = None
for parsed_file in multi_parser.parsed:
for parsed_item in parsed_file.keys():
dev_id, sep, dev_ip = parsed_item.partition(':')
if dev_id.lower() == 'n1kv':
for dev_key, value in parsed_file[parsed_item].items():
if dev_ip and not first_device_ip:
first_device_ip = dev_ip
device_dictionary[dev_id, dev_ip, dev_key] = value[0]
def get_device_dictionary():
return device_dictionary

File diff suppressed because it is too large Load Diff

View File

@ -1,185 +0,0 @@
# Copyright 2013 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
import sqlalchemy as sa
from sqlalchemy import sql
from neutron.db import model_base
from neutron.db import models_v2
from neutron.plugins.cisco.common import cisco_constants
LOG = logging.getLogger(__name__)
class N1kvVlanAllocation(model_base.BASEV2):
"""Represents allocation state of vlan_id on physical network."""
__tablename__ = 'cisco_n1kv_vlan_allocations'
physical_network = sa.Column(sa.String(64),
nullable=False,
primary_key=True)
vlan_id = sa.Column(sa.Integer, nullable=False, primary_key=True,
autoincrement=False)
allocated = sa.Column(sa.Boolean, nullable=False, default=False,
server_default=sql.false())
network_profile_id = sa.Column(sa.String(36),
sa.ForeignKey('cisco_network_profiles.id',
ondelete="CASCADE"),
nullable=False)
class N1kvVxlanAllocation(model_base.BASEV2):
"""Represents allocation state of vxlan_id."""
__tablename__ = 'cisco_n1kv_vxlan_allocations'
vxlan_id = sa.Column(sa.Integer, nullable=False, primary_key=True,
autoincrement=False)
allocated = sa.Column(sa.Boolean, nullable=False, default=False,
server_default=sql.false())
network_profile_id = sa.Column(sa.String(36),
sa.ForeignKey('cisco_network_profiles.id',
ondelete="CASCADE"),
nullable=False)
class N1kvPortBinding(model_base.BASEV2):
"""Represents binding of ports to policy profile."""
__tablename__ = 'cisco_n1kv_port_bindings'
port_id = sa.Column(sa.String(36),
sa.ForeignKey('ports.id', ondelete="CASCADE"),
primary_key=True)
profile_id = sa.Column(sa.String(36),
sa.ForeignKey('cisco_policy_profiles.id'))
class N1kvNetworkBinding(model_base.BASEV2):
"""Represents binding of virtual network to physical realization."""
__tablename__ = 'cisco_n1kv_network_bindings'
network_id = sa.Column(sa.String(36),
sa.ForeignKey('networks.id', ondelete="CASCADE"),
primary_key=True)
network_type = sa.Column(sa.String(32), nullable=False)
physical_network = sa.Column(sa.String(64))
segmentation_id = sa.Column(sa.Integer)
multicast_ip = sa.Column(sa.String(32))
profile_id = sa.Column(sa.String(36),
sa.ForeignKey('cisco_network_profiles.id'))
class N1kVmNetwork(model_base.BASEV2):
"""Represents VM Network information."""
__tablename__ = 'cisco_n1kv_vmnetworks'
name = sa.Column(sa.String(80), primary_key=True)
profile_id = sa.Column(sa.String(36),
sa.ForeignKey('cisco_policy_profiles.id'))
network_id = sa.Column(sa.String(36))
port_count = sa.Column(sa.Integer)
class NetworkProfile(model_base.BASEV2, models_v2.HasId):
"""
Nexus1000V Network Profiles
segment_type - VLAN, OVERLAY, TRUNK, MULTI_SEGMENT
sub_type - TRUNK_VLAN, TRUNK_VXLAN, native_vxlan, enhanced_vxlan
segment_range - '<integer>-<integer>'
multicast_ip_index - <integer>
multicast_ip_range - '<ip>-<ip>'
physical_network - Name for the physical network
"""
__tablename__ = 'cisco_network_profiles'
name = sa.Column(sa.String(255))
segment_type = sa.Column(sa.Enum(cisco_constants.NETWORK_TYPE_VLAN,
cisco_constants.NETWORK_TYPE_OVERLAY,
cisco_constants.NETWORK_TYPE_TRUNK,
cisco_constants.
NETWORK_TYPE_MULTI_SEGMENT,
name='segment_type'),
nullable=False)
sub_type = sa.Column(sa.String(255))
segment_range = sa.Column(sa.String(255))
multicast_ip_index = sa.Column(sa.Integer, default=0,
server_default='0')
multicast_ip_range = sa.Column(sa.String(255))
physical_network = sa.Column(sa.String(255))
class PolicyProfile(model_base.BASEV2):
"""
Nexus1000V Network Profiles
Both 'id' and 'name' are coming from Nexus1000V switch
"""
__tablename__ = 'cisco_policy_profiles'
id = sa.Column(sa.String(36), primary_key=True)
name = sa.Column(sa.String(255))
class ProfileBinding(model_base.BASEV2):
"""
Represents a binding of Network Profile
or Policy Profile to tenant_id
"""
__tablename__ = 'cisco_n1kv_profile_bindings'
profile_type = sa.Column(sa.Enum(cisco_constants.NETWORK,
cisco_constants.POLICY,
name='profile_type'))
tenant_id = sa.Column(sa.String(36),
primary_key=True,
default=cisco_constants.TENANT_ID_NOT_SET,
server_default=cisco_constants.TENANT_ID_NOT_SET)
profile_id = sa.Column(sa.String(36), primary_key=True)
class N1kvTrunkSegmentBinding(model_base.BASEV2):
"""Represents binding of segments in trunk networks."""
__tablename__ = 'cisco_n1kv_trunk_segments'
trunk_segment_id = sa.Column(sa.String(36),
sa.ForeignKey('networks.id',
ondelete="CASCADE"),
primary_key=True)
segment_id = sa.Column(sa.String(36), nullable=False, primary_key=True)
dot1qtag = sa.Column(sa.String(36), nullable=False, primary_key=True)
class N1kvMultiSegmentNetworkBinding(model_base.BASEV2):
"""Represents binding of segments in multi-segment networks."""
__tablename__ = 'cisco_n1kv_multi_segments'
multi_segment_id = sa.Column(sa.String(36),
sa.ForeignKey('networks.id',
ondelete="CASCADE"),
primary_key=True)
segment1_id = sa.Column(sa.String(36), nullable=False, primary_key=True)
segment2_id = sa.Column(sa.String(36), nullable=False, primary_key=True)
encap_profile_name = sa.Column(sa.String(36))

View File

@ -1,280 +0,0 @@
# Copyright 2012, Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
from oslo_utils import uuidutils
from sqlalchemy.orm import exc
from neutron.db import api as db
from neutron.plugins.cisco.common import cisco_constants as const
from neutron.plugins.cisco.common import cisco_exceptions as c_exc
from neutron.plugins.cisco.db import network_models_v2
LOG = logging.getLogger(__name__)
def get_all_qoss(tenant_id):
"""Lists all the qos to tenant associations."""
LOG.debug("get_all_qoss() called")
session = db.get_session()
return (session.query(network_models_v2.QoS).
filter_by(tenant_id=tenant_id).all())
def get_qos(tenant_id, qos_id):
"""Lists the qos given a tenant_id and qos_id."""
LOG.debug("get_qos() called")
session = db.get_session()
try:
return (session.query(network_models_v2.QoS).
filter_by(tenant_id=tenant_id).
filter_by(qos_id=qos_id).one())
except exc.NoResultFound:
raise c_exc.QosNotFound(qos_id=qos_id,
tenant_id=tenant_id)
def add_qos(tenant_id, qos_name, qos_desc):
"""Adds a qos to tenant association."""
LOG.debug("add_qos() called")
session = db.get_session()
try:
qos = (session.query(network_models_v2.QoS).
filter_by(tenant_id=tenant_id).
filter_by(qos_name=qos_name).one())
raise c_exc.QosNameAlreadyExists(qos_name=qos_name,
tenant_id=tenant_id)
except exc.NoResultFound:
qos = network_models_v2.QoS(qos_id=uuidutils.generate_uuid(),
tenant_id=tenant_id,
qos_name=qos_name,
qos_desc=qos_desc)
session.add(qos)
session.flush()
return qos
def remove_qos(tenant_id, qos_id):
"""Removes a qos to tenant association."""
session = db.get_session()
try:
qos = (session.query(network_models_v2.QoS).
filter_by(tenant_id=tenant_id).
filter_by(qos_id=qos_id).one())
session.delete(qos)
session.flush()
return qos
except exc.NoResultFound:
pass
def update_qos(tenant_id, qos_id, new_qos_name=None):
"""Updates a qos to tenant association."""
session = db.get_session()
try:
qos = (session.query(network_models_v2.QoS).
filter_by(tenant_id=tenant_id).
filter_by(qos_id=qos_id).one())
if new_qos_name:
qos["qos_name"] = new_qos_name
session.merge(qos)
session.flush()
return qos
except exc.NoResultFound:
raise c_exc.QosNotFound(qos_id=qos_id,
tenant_id=tenant_id)
def get_all_credentials():
"""Lists all the creds for a tenant."""
session = db.get_session()
return (session.query(network_models_v2.Credential).all())
def get_credential(credential_id):
"""Lists the creds for given a cred_id."""
session = db.get_session()
try:
return (session.query(network_models_v2.Credential).
filter_by(credential_id=credential_id).one())
except exc.NoResultFound:
raise c_exc.CredentialNotFound(credential_id=credential_id)
def get_credential_name(credential_name):
"""Lists the creds for given a cred_name."""
session = db.get_session()
try:
return (session.query(network_models_v2.Credential).
filter_by(credential_name=credential_name).one())
except exc.NoResultFound:
raise c_exc.CredentialNameNotFound(credential_name=credential_name)
def add_credential(credential_name, user_name, password, type):
"""Create a credential."""
session = db.get_session()
try:
cred = (session.query(network_models_v2.Credential).
filter_by(credential_name=credential_name).one())
raise c_exc.CredentialAlreadyExists(credential_name=credential_name)
except exc.NoResultFound:
cred = network_models_v2.Credential(
credential_id=uuidutils.generate_uuid(),
credential_name=credential_name,
user_name=user_name,
password=password,
type=type)
session.add(cred)
session.flush()
return cred
def remove_credential(credential_id):
"""Removes a credential."""
session = db.get_session()
try:
cred = (session.query(network_models_v2.Credential).
filter_by(credential_id=credential_id).one())
session.delete(cred)
session.flush()
return cred
except exc.NoResultFound:
pass
def update_credential(credential_id,
new_user_name=None, new_password=None):
"""Updates a credential for a tenant."""
session = db.get_session()
try:
cred = (session.query(network_models_v2.Credential).
filter_by(credential_id=credential_id).one())
if new_user_name:
cred["user_name"] = new_user_name
if new_password:
cred["password"] = new_password
session.merge(cred)
session.flush()
return cred
except exc.NoResultFound:
raise c_exc.CredentialNotFound(credential_id=credential_id)
def get_all_n1kv_credentials():
session = db.get_session()
return (session.query(network_models_v2.Credential).
filter_by(type='n1kv'))
def delete_all_n1kv_credentials():
session = db.get_session()
session.query(network_models_v2.Credential).filter_by(type='n1kv').delete()
def add_provider_network(network_id, network_type, segmentation_id):
"""Add a network to the provider network table."""
session = db.get_session()
if session.query(network_models_v2.ProviderNetwork).filter_by(
network_id=network_id).first():
raise c_exc.ProviderNetworkExists(network_id)
pnet = network_models_v2.ProviderNetwork(network_id=network_id,
network_type=network_type,
segmentation_id=segmentation_id)
session.add(pnet)
session.flush()
def remove_provider_network(network_id):
"""Remove network_id from the provider network table.
:param network_id: Any network id. If it is not in the table, do nothing.
:return: network_id if it was in the table and successfully removed.
"""
session = db.get_session()
pnet = (session.query(network_models_v2.ProviderNetwork).
filter_by(network_id=network_id).first())
if pnet:
session.delete(pnet)
session.flush()
return network_id
def is_provider_network(network_id):
"""Return True if network_id is in the provider network table."""
session = db.get_session()
if session.query(network_models_v2.ProviderNetwork).filter_by(
network_id=network_id).first():
return True
def is_provider_vlan(vlan_id):
"""Check for a for a vlan provider network with the specified vland_id.
Returns True if the provider network table contains a vlan network
with the specified vlan_id.
"""
session = db.get_session()
if (session.query(network_models_v2.ProviderNetwork).
filter_by(network_type=const.NETWORK_TYPE_VLAN,
segmentation_id=vlan_id).first()):
return True
class Credential_db_mixin(object):
"""Mixin class for Cisco Credentials as a resource."""
def _make_credential_dict(self, credential, fields=None):
res = {'credential_id': credential['credential_id'],
'credential_name': credential['credential_name'],
'user_name': credential['user_name'],
'password': credential['password'],
'type': credential['type']}
return self._fields(res, fields)
def create_credential(self, context, credential):
"""Create a credential."""
c = credential['credential']
cred = add_credential(c['credential_name'],
c['user_name'],
c['password'],
c['type'])
return self._make_credential_dict(cred)
def get_credentials(self, context, filters=None, fields=None):
"""Retrieve a list of credentials."""
return self._get_collection(context,
network_models_v2.Credential,
self._make_credential_dict,
filters=filters,
fields=fields)
def get_credential(self, context, id, fields=None):
"""Retireve the requested credential based on its id."""
credential = get_credential(id)
return self._make_credential_dict(credential, fields)
def update_credential(self, context, id, credential):
"""Update a credential based on its id."""
c = credential['credential']
cred = update_credential(id,
c['user_name'],
c['password'])
return self._make_credential_dict(cred)
def delete_credential(self, context, id):
"""Delete a credential based on its id."""
return remove_credential(id)

View File

@ -1,52 +0,0 @@
# Copyright 2012, Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import sqlalchemy as sa
from neutron.db import model_base
class QoS(model_base.BASEV2):
"""Represents QoS policies for a tenant."""
__tablename__ = 'cisco_qos_policies'
qos_id = sa.Column(sa.String(255))
tenant_id = sa.Column(sa.String(255), primary_key=True)
qos_name = sa.Column(sa.String(255), primary_key=True)
qos_desc = sa.Column(sa.String(255))
class Credential(model_base.BASEV2):
"""Represents credentials for a tenant to control Cisco switches."""
__tablename__ = 'cisco_credentials'
credential_id = sa.Column(sa.String(255))
credential_name = sa.Column(sa.String(255), primary_key=True)
user_name = sa.Column(sa.String(255))
password = sa.Column(sa.String(255))
type = sa.Column(sa.String(255))
class ProviderNetwork(model_base.BASEV2):
"""Represents networks that were created as provider networks."""
__tablename__ = 'cisco_provider_networks'
network_id = sa.Column(sa.String(36),
sa.ForeignKey('networks.id', ondelete="CASCADE"),
primary_key=True)
network_type = sa.Column(sa.String(255), nullable=False)
segmentation_id = sa.Column(sa.Integer, nullable=False)

View File

@ -1,47 +0,0 @@
# 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.
def get_view_builder(req):
base_url = req.application_url
return ViewBuilder(base_url)
class ViewBuilder(object):
"""ViewBuilder for Credential, derived from neutron.views.networks."""
def __init__(self, base_url):
"""Initialize builder.
: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."""
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 description of credential."""
return dict(credential=dict(id=credential_data['credential_id']))
def _build_detail(self, credential_data):
"""Return a detailed description of credential."""
return dict(credential=dict(id=credential_data['credential_id'],
name=credential_data['user_name'],
password=credential_data['password']))

View File

@ -1,47 +0,0 @@
# 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.
def get_view_builder(req):
base_url = req.application_url
return ViewBuilder(base_url)
class ViewBuilder(object):
"""ViewBuilder for QoS, derived from neutron.views.networks."""
def __init__(self, base_url):
"""Initialize builder.
: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 description of qos."""
return dict(qos=dict(id=qos_data['qos_id']))
def _build_detail(self, qos_data):
"""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

@ -1,74 +0,0 @@
# Copyright 2013 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.
from neutron.api import extensions
from neutron.api.v2 import attributes
from neutron.api.v2 import base
from neutron import manager
# Attribute Map
RESOURCE_ATTRIBUTE_MAP = {
'credentials': {
'credential_id': {'allow_post': False, 'allow_put': False,
'validate': {'type:regex': attributes.UUID_PATTERN},
'is_visible': True},
'credential_name': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': ''},
'tenant_id': {'allow_post': True, 'allow_put': False,
'is_visible': False, 'default': ''},
'type': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': ''},
'user_name': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': ''},
'password': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': ''},
},
}
class Credential(extensions.ExtensionDescriptor):
@classmethod
def get_name(cls):
"""Returns Extended Resource Name."""
return "Cisco Credential"
@classmethod
def get_alias(cls):
"""Returns Extended Resource Alias."""
return "credential"
@classmethod
def get_description(cls):
"""Returns Extended Resource Description."""
return "Credential include username and password"
@classmethod
def get_updated(cls):
"""Returns Extended Resource Update Time."""
return "2011-07-25T13:25:27-06:00"
@classmethod
def get_resources(cls):
"""Returns Extended Resources."""
resource_name = "credential"
collection_name = resource_name + "s"
plugin = manager.NeutronManager.get_plugin()
params = RESOURCE_ATTRIBUTE_MAP.get(collection_name, dict())
controller = base.create_resource(collection_name,
resource_name,
plugin, params)
return [extensions.ResourceExtension(collection_name,
controller)]

View File

@ -1,95 +0,0 @@
# Copyright 2013 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.api import extensions
from neutron.api.v2 import attributes
PROFILE_ID = 'n1kv:profile_id'
MULTICAST_IP = 'n1kv:multicast_ip'
SEGMENT_ADD = 'n1kv:segment_add'
SEGMENT_DEL = 'n1kv:segment_del'
MEMBER_SEGMENTS = 'n1kv:member_segments'
EXTENDED_ATTRIBUTES_2_0 = {
'networks': {
PROFILE_ID: {'allow_post': True, 'allow_put': False,
'validate': {'type:regex': attributes.UUID_PATTERN},
'default': attributes.ATTR_NOT_SPECIFIED,
'is_visible': True},
MULTICAST_IP: {'allow_post': True, 'allow_put': True,
'default': attributes.ATTR_NOT_SPECIFIED,
'is_visible': True},
SEGMENT_ADD: {'allow_post': True, 'allow_put': True,
'default': attributes.ATTR_NOT_SPECIFIED,
'is_visible': True},
SEGMENT_DEL: {'allow_post': True, 'allow_put': True,
'default': attributes.ATTR_NOT_SPECIFIED,
'is_visible': True},
MEMBER_SEGMENTS: {'allow_post': True, 'allow_put': True,
'default': attributes.ATTR_NOT_SPECIFIED,
'is_visible': True},
},
'ports': {
PROFILE_ID: {'allow_post': True, 'allow_put': False,
'validate': {'type:regex': attributes.UUID_PATTERN},
'default': attributes.ATTR_NOT_SPECIFIED,
'is_visible': True}
}
}
class N1kv(extensions.ExtensionDescriptor):
"""Extension class supporting N1kv profiles.
This class is used by neutron's extension framework to make
metadata about the n1kv profile extension available to
clients. No new resources are defined by this extension. Instead,
the existing network resource's request and response messages are
extended with attributes in the n1kv profile namespace.
To create a network based on n1kv profile using the CLI with admin rights:
(shell) net-create --tenant_id <tenant-id> <net-name> \
--n1kv:profile_id <id>
(shell) port-create --tenant_id <tenant-id> <net-name> \
--n1kv:profile_id <id>
With admin rights, network dictionaries returned from CLI commands
will also include n1kv profile attributes.
"""
@classmethod
def get_name(cls):
return "n1kv"
@classmethod
def get_alias(cls):
return "n1kv"
@classmethod
def get_description(cls):
return "Expose network profile"
@classmethod
def get_updated(cls):
return "2012-11-15T10:00:00-00:00"
def get_extended_resources(self, version):
if version == "2.0":
return EXTENDED_ATTRIBUTES_2_0
else:
return {}

View File

@ -1,97 +0,0 @@
# Copyright 2013 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.api import extensions
from neutron.api.v2 import attributes
from neutron.api.v2 import base
from neutron import manager
# Attribute Map
RESOURCE_ATTRIBUTE_MAP = {
'network_profiles': {
'id': {'allow_post': False, 'allow_put': False,
'validate': {'type:regex': attributes.UUID_PATTERN},
'is_visible': True},
'name': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': ''},
'segment_type': {'allow_post': True, 'allow_put': False,
'is_visible': True, 'default': ''},
'sub_type': {'allow_post': True, 'allow_put': False,
'is_visible': True,
'default': attributes.ATTR_NOT_SPECIFIED},
'segment_range': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': ''},
'multicast_ip_range': {'allow_post': True, 'allow_put': True,
'is_visible': True,
'default': attributes.ATTR_NOT_SPECIFIED},
'multicast_ip_index': {'allow_post': False, 'allow_put': False,
'is_visible': False, 'default': '0'},
'physical_network': {'allow_post': True, 'allow_put': False,
'is_visible': True, 'default': ''},
'tenant_id': {'allow_post': True, 'allow_put': False,
'is_visible': False, 'default': ''},
'add_tenants': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': None,
'convert_to': attributes.convert_none_to_empty_list},
'remove_tenants': {
'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': None,
'convert_to': attributes.convert_none_to_empty_list,
},
},
'network_profile_bindings': {
'profile_id': {'allow_post': False, 'allow_put': False,
'validate': {'type:regex': attributes.UUID_PATTERN},
'is_visible': True},
'tenant_id': {'allow_post': True, 'allow_put': False,
'is_visible': True},
},
}
class Network_profile(extensions.ExtensionDescriptor):
@classmethod
def get_name(cls):
return "Cisco N1kv Network Profiles"
@classmethod
def get_alias(cls):
return 'network_profile'
@classmethod
def get_description(cls):
return ("Profile includes the type of profile for N1kv")
@classmethod
def get_updated(cls):
return "2012-07-20T10:00:00-00:00"
@classmethod
def get_resources(cls):
"""Returns Extended Resources."""
exts = []
plugin = manager.NeutronManager.get_plugin()
for resource_name in ['network_profile', 'network_profile_binding']:
collection_name = resource_name + "s"
controller = base.create_resource(
collection_name,
resource_name,
plugin,
RESOURCE_ATTRIBUTE_MAP.get(collection_name))
ex = extensions.ResourceExtension(collection_name,
controller)
exts.append(ex)
return exts

View File

@ -1,76 +0,0 @@
# Copyright 2013 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.api import extensions
from neutron.api.v2 import attributes
from neutron.api.v2 import base
from neutron import manager
# Attribute Map
RESOURCE_ATTRIBUTE_MAP = {
'policy_profiles': {
'id': {'allow_post': False, 'allow_put': False,
'validate': {'type:regex': attributes.UUID_PATTERN},
'is_visible': True},
'name': {'allow_post': False, 'allow_put': False,
'is_visible': True, 'default': ''},
'add_tenant': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': None},
'remove_tenant': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': None},
},
'policy_profile_bindings': {
'profile_id': {'allow_post': False, 'allow_put': False,
'validate': {'type:regex': attributes.UUID_PATTERN},
'is_visible': True},
'tenant_id': {'allow_post': True, 'allow_put': False,
'is_visible': True},
},
}
class Policy_profile(extensions.ExtensionDescriptor):
@classmethod
def get_name(cls):
return "Cisco Nexus1000V Policy Profiles"
@classmethod
def get_alias(cls):
return 'policy_profile'
@classmethod
def get_description(cls):
return "Profile includes the type of profile for N1kv"
@classmethod
def get_updated(cls):
return "2012-07-20T10:00:00-00:00"
@classmethod
def get_resources(cls):
"""Returns Extended Resources."""
exts = []
plugin = manager.NeutronManager.get_plugin()
for resource_name in ['policy_profile', 'policy_profile_binding']:
collection_name = resource_name + "s"
controller = base.create_resource(
collection_name,
resource_name,
plugin,
RESOURCE_ATTRIBUTE_MAP.get(collection_name))
ex = extensions.ResourceExtension(collection_name,
controller)
exts.append(ex)
return exts

View File

@ -1,146 +0,0 @@
# 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.
from webob import exc
from neutron.api import api_common as common
from neutron.api import extensions
from neutron import manager
from neutron.plugins.cisco.common import cisco_exceptions as exception
from neutron.plugins.cisco.common import cisco_faults as faults
from neutron.plugins.cisco.extensions import _qos_view as qos_view
from neutron import wsgi
class Qos(extensions.ExtensionDescriptor):
"""Qos extension file."""
@classmethod
def get_name(cls):
"""Returns Ext Resource Name."""
return "Cisco qos"
@classmethod
def get_alias(cls):
"""Returns Ext Resource Alias."""
return "Cisco qos"
@classmethod
def get_description(cls):
"""Returns Ext Resource Description."""
return "qos includes qos_name and qos_desc"
@classmethod
def get_updated(cls):
"""Returns Ext Resource update."""
return "2011-07-25T13:25:27-06:00"
@classmethod
def get_resources(cls):
"""Returns Ext Resources."""
parent_resource = dict(member_name="tenant",
collection_name="extensions/csco/tenants")
controller = QosController(manager.NeutronManager.get_plugin())
return [extensions.ResourceExtension('qoss', controller,
parent=parent_resource)]
class QosController(common.NeutronController, wsgi.Controller):
"""qos API controller based on NeutronController."""
_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'
self._plugin = plugin
def index(self, request, tenant_id):
"""Returns a list of qos ids."""
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=no-member
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 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:
body = self._deserialize(request.body, request.get_content_type())
req_body = self._prepare_request_body(body,
self._qos_ops_param_list)
req_params = req_body[self._resource_name]
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:
body = self._deserialize(request.body, request.get_content_type())
req_body = self._prepare_request_body(body,
self._qos_ops_param_list)
req_params = req_body[self._resource_name]
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 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.HTTPOk()
except exception.QosNotFound as exp:
return faults.Fault(faults.QosNotFound(exp))

View File

@ -1,171 +0,0 @@
# Copyright 2012 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.
import abc
import inspect
import six
@six.add_metaclass(abc.ABCMeta)
class L2DevicePluginBase(object):
"""Base class for a device-specific plugin.
An example of a device-specific plugin is a Nexus switch plugin.
The network model relies on device-category-specific plugins to perform
the configuration on each device.
"""
@abc.abstractmethod
def create_network(self, tenant_id, net_name, net_id, vlan_name, vlan_id,
**kwargs):
"""Create network.
:returns:
:raises:
"""
pass
@abc.abstractmethod
def delete_network(self, tenant_id, net_id, **kwargs):
"""Delete network.
:returns:
:raises:
"""
pass
@abc.abstractmethod
def update_network(self, tenant_id, net_id, name, **kwargs):
"""Update network.
:returns:
:raises:
"""
pass
@abc.abstractmethod
def create_port(self, tenant_id, net_id, port_state, port_id, **kwargs):
"""Create port.
:returns:
:raises:
"""
pass
@abc.abstractmethod
def delete_port(self, tenant_id, net_id, port_id, **kwargs):
"""Delete port.
:returns:
:raises:
"""
pass
@abc.abstractmethod
def update_port(self, tenant_id, net_id, port_id, **kwargs):
"""Update port.
:returns:
:raises:
"""
pass
@abc.abstractmethod
def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id,
**kwargs):
"""Plug interface.
:returns:
:raises:
"""
pass
@abc.abstractmethod
def unplug_interface(self, tenant_id, net_id, port_id, **kwargs):
"""Unplug interface.
:returns:
:raises:
"""
pass
def create_subnet(self, tenant_id, net_id, ip_version,
subnet_cidr, **kwargs):
"""Create subnet.
:returns:
:raises:
"""
pass
def get_subnets(self, tenant_id, net_id, **kwargs):
"""Get subnets.
:returns:
:raises:
"""
pass
def get_subnet(self, tenant_id, net_id, subnet_id, **kwargs):
"""Get subnet.
:returns:
:raises:
"""
pass
def update_subnet(self, tenant_id, net_id, subnet_id, **kwargs):
"""Update subnet.
:returns:
:raises:
"""
pass
def delete_subnet(self, tenant_id, net_id, subnet_id, **kwargs):
"""Delete subnet.
:returns:
:raises:
"""
pass
@classmethod
def __subclasshook__(cls, klass):
"""Check plugin class.
The __subclasshook__ method is a class method
that will be called every time a class is tested
using issubclass(klass, Plugin).
In that case, it will check that every method
marked with the abstractmethod decorator is
provided by the plugin class.
"""
if cls is L2DevicePluginBase:
for method in cls.__abstractmethods__:
method_ok = False
for base in klass.__mro__:
if method in base.__dict__:
fn_obj = base.__dict__[method]
if inspect.isfunction(fn_obj):
abstract_fn_obj = cls.__dict__[method]
arg_count = fn_obj.__code__.co_argcount
expected_arg_count = \
abstract_fn_obj.__code__.co_argcount
method_ok = arg_count == expected_arg_count
if method_ok:
continue
return NotImplemented
return True
return NotImplemented

View File

@ -1,320 +0,0 @@
# Copyright 2012 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.
import inspect
from oslo_log import log as logging
from oslo_utils import excutils
from oslo_utils import importutils
from neutron.api.v2 import attributes
from neutron.extensions import portbindings
from neutron.extensions import providernet as provider
from neutron.i18n import _LE, _LI
from neutron import neutron_plugin_base_v2
from neutron.plugins.cisco.common import cisco_constants as const
from neutron.plugins.cisco.common import cisco_credentials_v2 as cred
from neutron.plugins.cisco.common import config as conf
from neutron.plugins.cisco.db import network_db_v2 as cdb
LOG = logging.getLogger(__name__)
class VirtualPhysicalSwitchModelV2(neutron_plugin_base_v2.NeutronPluginBaseV2):
"""Virtual Physical Switch Model.
This implementation works with n1kv sub-plugin for the
following topology:
One or more servers to a n1kv switch.
"""
__native_bulk_support = True
supported_extension_aliases = ["provider", "binding"]
_methods_to_delegate = ['create_network_bulk',
'get_network', 'get_networks',
'create_port_bulk',
'get_port', 'get_ports',
'create_subnet', 'create_subnet_bulk',
'delete_subnet', 'update_subnet',
'get_subnet', 'get_subnets',
'create_or_update_agent', 'report_state']
def __init__(self):
"""Initialize the segmentation manager.
Checks which device plugins are configured, and load the inventories
those device plugins for which the inventory is configured.
"""
conf.CiscoConfigOptions()
self._plugins = {}
self._plugins['vswitch_plugin'] = importutils.import_object(
'neutron.plugins.cisco.n1kv.n1kv_neutron_plugin.'
'N1kvNeutronPluginV2')
if ((const.VSWITCH_PLUGIN in self._plugins) and
hasattr(self._plugins[const.VSWITCH_PLUGIN],
"supported_extension_aliases")):
self.supported_extension_aliases.extend(
self._plugins[const.VSWITCH_PLUGIN].
supported_extension_aliases)
# Initialize credential store after database initialization
cred.Store.initialize()
LOG.debug("%(module)s.%(name)s init done",
{'module': __name__,
'name': self.__class__.__name__})
def __getattribute__(self, name):
"""Delegate calls to sub-plugin.
This delegates the calls to the methods implemented by the
sub-plugin. Note: Currently, bulking is handled by the caller
(PluginV2), and this model class expects to receive only non-bulking
calls. If, however, a bulking call is made, this will method will
delegate the call to the sub-plugin.
"""
super_getattribute = super(VirtualPhysicalSwitchModelV2,
self).__getattribute__
methods = super_getattribute('_methods_to_delegate')
if name in methods:
plugin = super_getattribute('_plugins')[const.VSWITCH_PLUGIN]
return getattr(plugin, name)
try:
return super_getattribute(name)
except AttributeError:
plugin = super_getattribute('_plugins')[const.VSWITCH_PLUGIN]
return getattr(plugin, name)
def _func_name(self, offset=0):
"""Get the name of the calling function."""
frame_record = inspect.stack()[1 + offset]
func_name = frame_record[3]
return func_name
def _invoke_plugin_per_device(self, plugin_key, function_name,
args, **kwargs):
"""Invoke plugin per device.
Invokes a device plugin's relevant functions (based on the
plugin implementation) for completing this operation.
"""
if plugin_key not in self._plugins:
LOG.info(_LI("No %s Plugin loaded"), plugin_key)
LOG.info(_LI("%(plugin_key)s: %(function_name)s with args "
"%(args)s ignored"),
{'plugin_key': plugin_key,
'function_name': function_name,
'args': args})
else:
func = getattr(self._plugins[plugin_key], function_name)
return func(*args, **kwargs)
def _get_provider_vlan_id(self, network):
if (all(attributes.is_attr_set(network.get(attr))
for attr in (provider.NETWORK_TYPE,
provider.PHYSICAL_NETWORK,
provider.SEGMENTATION_ID))
and
network[provider.NETWORK_TYPE] == const.NETWORK_TYPE_VLAN):
return network[provider.SEGMENTATION_ID]
def create_network(self, context, network):
"""Create network.
Perform this operation in the context of the configured device
plugins.
"""
LOG.debug("create_network() called")
provider_vlan_id = self._get_provider_vlan_id(network[const.NETWORK])
args = [context, network]
switch_output = self._invoke_plugin_per_device(const.VSWITCH_PLUGIN,
self._func_name(),
args)
# The vswitch plugin did all the verification. If it's a provider
# vlan network, save it for the sub-plugin to use later.
if provider_vlan_id:
network_id = switch_output[const.NET_ID]
cdb.add_provider_network(network_id,
const.NETWORK_TYPE_VLAN,
provider_vlan_id)
LOG.debug("Provider network added to DB: %(network_id)s, "
"%(vlan_id)s",
{'network_id': network_id, 'vlan_id': provider_vlan_id})
return switch_output
def update_network(self, context, id, network):
"""Update network.
Perform this operation in the context of the configured device
plugins.
"""
LOG.debug("update_network() called")
# We can only support updating of provider attributes if all the
# configured sub-plugins support it. Currently we have no method
# in place for checking whether a sub-plugin supports it,
# so assume not.
provider._raise_if_updates_provider_attributes(network['network'])
args = [context, id, network]
return self._invoke_plugin_per_device(const.VSWITCH_PLUGIN,
self._func_name(),
args)
def delete_network(self, context, id):
"""Delete network.
Perform this operation in the context of the configured device
plugins.
"""
args = [context, id]
switch_output = self._invoke_plugin_per_device(const.VSWITCH_PLUGIN,
self._func_name(),
args)
if cdb.remove_provider_network(id):
LOG.debug("Provider network removed from DB: %s", id)
return switch_output
def get_network(self, context, id, fields=None):
"""Get network. This method is delegated to the vswitch plugin.
This method is included here to satisfy abstract method requirements.
"""
pass # pragma no cover
def get_networks(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None, page_reverse=False):
"""Get networks. This method is delegated to the vswitch plugin.
This method is included here to satisfy abstract method requirements.
"""
pass # pragma no cover
def _check_valid_port_device_owner(self, port):
"""Check the port for valid device_owner.
Don't call the sub-plugin for router and dhcp
port owners.
"""
return port['device_owner'].startswith('compute')
def _get_port_host_id_from_bindings(self, port):
"""Get host_id from portbindings."""
host_id = None
if (portbindings.HOST_ID in port and
attributes.is_attr_set(port[portbindings.HOST_ID])):
host_id = port[portbindings.HOST_ID]
return host_id
def create_port(self, context, port):
"""Create port.
Perform this operation in the context of the configured device
plugins.
"""
LOG.debug("create_port() called")
args = [context, port]
return self._invoke_plugin_per_device(const.VSWITCH_PLUGIN,
self._func_name(),
args)
def get_port(self, context, id, fields=None):
"""Get port. This method is delegated to the vswitch plugin.
This method is included here to satisfy abstract method requirements.
"""
pass # pragma no cover
def get_ports(self, context, filters=None, fields=None):
"""Get ports. This method is delegated to the vswitch plugin.
This method is included here to satisfy abstract method requirements.
"""
pass # pragma no cover
def update_port(self, context, id, port):
"""Update port.
Perform this operation in the context of the configured device
plugins.
"""
LOG.debug("update_port() called")
args = [context, id, port]
return self._invoke_plugin_per_device(const.VSWITCH_PLUGIN,
self._func_name(),
args)
def delete_port(self, context, id, l3_port_check=True):
"""Delete port.
Perform this operation in the context of the configured device
plugins.
"""
LOG.debug("delete_port() called")
port = self.get_port(context, id)
try:
args = [context, id]
switch_output = self._invoke_plugin_per_device(
const.VSWITCH_PLUGIN, self._func_name(),
args, l3_port_check=l3_port_check)
except Exception as e:
with excutils.save_and_reraise_exception():
LOG.error(_LE("Unable to delete port '%(pname)s' on switch. "
"Exception: %(exp)s"), {'pname': port['name'],
'exp': e})
return switch_output
def create_subnet(self, context, subnet):
"""Create subnet. This method is delegated to the vswitch plugin.
This method is included here to satisfy abstract method requirements.
"""
pass # pragma no cover
def update_subnet(self, context, id, subnet):
"""Update subnet. This method is delegated to the vswitch plugin.
This method is included here to satisfy abstract method requirements.
"""
pass # pragma no cover
def get_subnet(self, context, id, fields=None):
"""Get subnet. This method is delegated to the vswitch plugin.
This method is included here to satisfy abstract method requirements.
"""
pass # pragma no cover
def delete_subnet(self, context, id, kwargs):
"""Delete subnet. This method is delegated to the vswitch plugin.
This method is included here to satisfy abstract method requirements.
"""
pass # pragma no cover
def get_subnets(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None, page_reverse=False):
"""Get subnets. This method is delegated to the vswitch plugin.
This method is included here to satisfy abstract method requirements.
"""
pass # pragma no cover

View File

@ -1,558 +0,0 @@
# Copyright 2013 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import base64
import eventlet
import netaddr
from oslo_log import log as logging
from oslo_serialization import jsonutils
import requests
import six
from neutron.common import exceptions as n_exc
from neutron.extensions import providernet
from neutron.plugins.cisco.common import cisco_constants as c_const
from neutron.plugins.cisco.common import cisco_credentials_v2 as c_cred
from neutron.plugins.cisco.common import cisco_exceptions as c_exc
from neutron.plugins.cisco.common import config as c_conf
from neutron.plugins.cisco.db import network_db_v2
from neutron.plugins.cisco.extensions import n1kv
LOG = logging.getLogger(__name__)
def safe_b64_encode(s):
if six.PY3:
method = base64.encodebytes
else:
method = base64.encodestring
if isinstance(s, six.text_type):
s = s.encode('utf-8')
encoded_string = method(s).rstrip()
if six.PY3:
return encoded_string.decode('utf-8')
else:
return encoded_string
class Client(object):
"""
Client for the Cisco Nexus1000V Neutron Plugin.
This client implements functions to communicate with
Cisco Nexus1000V VSM.
For every Neutron objects, Cisco Nexus1000V Neutron Plugin
creates a corresponding object in the controller (Cisco
Nexus1000V VSM).
CONCEPTS:
Following are few concepts used in Nexus1000V VSM:
port-profiles:
Policy profiles correspond to port profiles on Nexus1000V VSM.
Port profiles are the primary mechanism by which network policy is
defined and applied to switch interfaces in a Nexus 1000V system.
network-segment:
Each network-segment represents a broadcast domain.
network-segment-pool:
A network-segment-pool contains one or more network-segments.
logical-network:
A logical-network contains one or more network-segment-pools.
bridge-domain:
A bridge-domain is created when the network-segment is of type VXLAN.
Each VXLAN <--> VLAN combination can be thought of as a bridge domain.
ip-pool:
Each ip-pool represents a subnet on the Nexus1000V VSM.
vm-network:
vm-network refers to a network-segment and policy-profile.
It maintains a list of ports that uses the network-segment and
policy-profile this vm-network refers to.
events:
Events correspond to commands that are logged on Nexus1000V VSM.
Events are used to poll for a certain resource on Nexus1000V VSM.
Event type of port_profile: Return all updates/create/deletes
of port profiles from the VSM.
Event type of port_profile_update: Return only updates regarding
policy-profiles.
Event type of port_profile_delete: Return only deleted policy profiles.
WORK FLOW:
For every network profile a corresponding logical-network and
a network-segment-pool, under this logical-network, will be created.
For every network created from a given network profile, a
network-segment will be added to the network-segment-pool corresponding
to that network profile.
A port is created on a network and associated with a policy-profile.
Hence for every unique combination of a network and a policy-profile, a
unique vm-network will be created and a reference to the port will be
added. If the same combination of network and policy-profile is used by
another port, the references to that port will be added to the same
vm-network.
"""
# Define paths for the URI where the client connects for HTTP requests.
port_profiles_path = "/virtual-port-profile"
network_segment_path = "/network-segment/%s"
network_segment_pool_path = "/network-segment-pool/%s"
ip_pool_path = "/ip-pool-template/%s"
ports_path = "/kvm/vm-network/%s/ports"
port_path = "/kvm/vm-network/%s/ports/%s"
vm_networks_path = "/kvm/vm-network"
vm_network_path = "/kvm/vm-network/%s"
bridge_domains_path = "/kvm/bridge-domain"
bridge_domain_path = "/kvm/bridge-domain/%s"
logical_network_path = "/logical-network/%s"
events_path = "/kvm/events"
clusters_path = "/cluster"
encap_profiles_path = "/encapsulation-profile"
encap_profile_path = "/encapsulation-profile/%s"
pool = eventlet.GreenPool(c_conf.CISCO_N1K.http_pool_size)
def __init__(self, **kwargs):
"""Initialize a new client for the plugin."""
self.format = 'json'
self.hosts = self._get_vsm_hosts()
self.action_prefix = 'http://%s/api/n1k' % self.hosts[0]
self.timeout = c_conf.CISCO_N1K.http_timeout
def list_port_profiles(self):
"""
Fetch all policy profiles from the VSM.
:returns: JSON string
"""
return self._get(self.port_profiles_path)
def create_bridge_domain(self, network, overlay_subtype):
"""
Create a bridge domain on VSM.
:param network: network dict
:param overlay_subtype: string representing subtype of overlay network
"""
body = {'name': network['id'] + c_const.BRIDGE_DOMAIN_SUFFIX,
'segmentId': network[providernet.SEGMENTATION_ID],
'subType': overlay_subtype,
'tenantId': network['tenant_id']}
if overlay_subtype == c_const.NETWORK_SUBTYPE_NATIVE_VXLAN:
body['groupIp'] = network[n1kv.MULTICAST_IP]
return self._post(self.bridge_domains_path,
body=body)
def delete_bridge_domain(self, name):
"""
Delete a bridge domain on VSM.
:param name: name of the bridge domain to be deleted
"""
return self._delete(self.bridge_domain_path % name)
def create_network_segment(self, network, network_profile):
"""
Create a network segment on the VSM.
:param network: network dict
:param network_profile: network profile dict
"""
body = {'publishName': network['id'],
'description': network['name'],
'id': network['id'],
'tenantId': network['tenant_id'],
'networkSegmentPool': network_profile['id'], }
if network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_VLAN:
body['vlan'] = network[providernet.SEGMENTATION_ID]
elif network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_OVERLAY:
body['bridgeDomain'] = (network['id'] +
c_const.BRIDGE_DOMAIN_SUFFIX)
if network_profile['segment_type'] == c_const.NETWORK_TYPE_TRUNK:
body['mode'] = c_const.NETWORK_TYPE_TRUNK
body['segmentType'] = network_profile['sub_type']
if network_profile['sub_type'] == c_const.NETWORK_TYPE_VLAN:
body['addSegments'] = network['add_segment_list']
body['delSegments'] = network['del_segment_list']
else:
body['encapProfile'] = (network['id'] +
c_const.ENCAPSULATION_PROFILE_SUFFIX)
else:
body['mode'] = 'access'
body['segmentType'] = network_profile['segment_type']
return self._post(self.network_segment_path % network['id'],
body=body)
def update_network_segment(self, network_segment_id, body):
"""
Update a network segment on the VSM.
Network segment on VSM can be updated to associate it with an ip-pool
or update its description and segment id.
:param network_segment_id: UUID representing the network segment
:param body: dict of arguments to be updated
"""
return self._post(self.network_segment_path % network_segment_id,
body=body)
def delete_network_segment(self, network_segment_id):
"""
Delete a network segment on the VSM.
:param network_segment_id: UUID representing the network segment
"""
return self._delete(self.network_segment_path % network_segment_id)
def create_logical_network(self, network_profile, tenant_id):
"""
Create a logical network on the VSM.
:param network_profile: network profile dict
:param tenant_id: UUID representing the tenant
"""
LOG.debug("Logical network")
body = {'description': network_profile['name'],
'tenantId': tenant_id}
logical_network_name = (network_profile['id'] +
c_const.LOGICAL_NETWORK_SUFFIX)
return self._post(self.logical_network_path % logical_network_name,
body=body)
def delete_logical_network(self, logical_network_name):
"""
Delete a logical network on VSM.
:param logical_network_name: string representing name of the logical
network
"""
return self._delete(
self.logical_network_path % logical_network_name)
def create_network_segment_pool(self, network_profile, tenant_id):
"""
Create a network segment pool on the VSM.
:param network_profile: network profile dict
:param tenant_id: UUID representing the tenant
"""
LOG.debug("network_segment_pool")
logical_network_name = (network_profile['id'] +
c_const.LOGICAL_NETWORK_SUFFIX)
body = {'name': network_profile['name'],
'description': network_profile['name'],
'id': network_profile['id'],
'logicalNetwork': logical_network_name,
'tenantId': tenant_id}
if network_profile['segment_type'] == c_const.NETWORK_TYPE_OVERLAY:
body['subType'] = network_profile['sub_type']
return self._post(
self.network_segment_pool_path % network_profile['id'],
body=body)
def update_network_segment_pool(self, network_profile):
"""
Update a network segment pool on the VSM.
:param network_profile: network profile dict
"""
body = {'name': network_profile['name'],
'description': network_profile['name']}
return self._post(self.network_segment_pool_path %
network_profile['id'], body=body)
def delete_network_segment_pool(self, network_segment_pool_id):
"""
Delete a network segment pool on the VSM.
:param network_segment_pool_id: UUID representing the network
segment pool
"""
return self._delete(self.network_segment_pool_path %
network_segment_pool_id)
def create_ip_pool(self, subnet):
"""
Create an ip-pool on the VSM.
:param subnet: subnet dict
"""
if subnet['cidr']:
try:
ip = netaddr.IPNetwork(subnet['cidr'])
netmask = str(ip.netmask)
network_address = str(ip.network)
except (ValueError, netaddr.AddrFormatError):
msg = _("Invalid input for CIDR")
raise n_exc.InvalidInput(error_message=msg)
else:
netmask = network_address = ""
if subnet['allocation_pools']:
address_range_start = subnet['allocation_pools'][0]['start']
address_range_end = subnet['allocation_pools'][0]['end']
else:
address_range_start = None
address_range_end = None
body = {'addressRangeStart': address_range_start,
'addressRangeEnd': address_range_end,
'ipAddressSubnet': netmask,
'description': subnet['name'],
'gateway': subnet['gateway_ip'],
'dhcp': subnet['enable_dhcp'],
'dnsServersList': subnet['dns_nameservers'],
'networkAddress': network_address,
'netSegmentName': subnet['network_id'],
'id': subnet['id'],
'tenantId': subnet['tenant_id']}
return self._post(self.ip_pool_path % subnet['id'],
body=body)
def update_ip_pool(self, subnet):
"""
Update an ip-pool on the VSM.
:param subnet: subnet dictionary
"""
body = {'description': subnet['name'],
'dhcp': subnet['enable_dhcp'],
'dnsServersList': subnet['dns_nameservers']}
return self._post(self.ip_pool_path % subnet['id'],
body=body)
def delete_ip_pool(self, subnet_id):
"""
Delete an ip-pool on the VSM.
:param subnet_id: UUID representing the subnet
"""
return self._delete(self.ip_pool_path % subnet_id)
def create_vm_network(self,
port,
vm_network_name,
policy_profile):
"""
Create a VM network on the VSM.
:param port: port dict
:param vm_network_name: name of the VM network
:param policy_profile: policy profile dict
"""
body = {'name': vm_network_name,
'networkSegmentId': port['network_id'],
'networkSegment': port['network_id'],
'portProfile': policy_profile['name'],
'portProfileId': policy_profile['id'],
'tenantId': port['tenant_id'],
'portId': port['id'],
'macAddress': port['mac_address'],
}
if port.get('fixed_ips'):
body['ipAddress'] = port['fixed_ips'][0]['ip_address']
body['subnetId'] = port['fixed_ips'][0]['subnet_id']
return self._post(self.vm_networks_path,
body=body)
def delete_vm_network(self, vm_network_name):
"""
Delete a VM network on the VSM.
:param vm_network_name: name of the VM network
"""
return self._delete(self.vm_network_path % vm_network_name)
def create_n1kv_port(self, port, vm_network_name):
"""
Create a port on the VSM.
:param port: port dict
:param vm_network_name: name of the VM network which imports this port
"""
body = {'id': port['id'],
'macAddress': port['mac_address']}
if port.get('fixed_ips'):
body['ipAddress'] = port['fixed_ips'][0]['ip_address']
body['subnetId'] = port['fixed_ips'][0]['subnet_id']
return self._post(self.ports_path % vm_network_name,
body=body)
def update_n1kv_port(self, vm_network_name, port_id, body):
"""
Update a port on the VSM.
Update the mac address associated with the port
:param vm_network_name: name of the VM network which imports this port
:param port_id: UUID of the port
:param body: dict of the arguments to be updated
"""
return self._post(self.port_path % (vm_network_name, port_id),
body=body)
def delete_n1kv_port(self, vm_network_name, port_id):
"""
Delete a port on the VSM.
:param vm_network_name: name of the VM network which imports this port
:param port_id: UUID of the port
"""
return self._delete(self.port_path % (vm_network_name, port_id))
def _do_request(self, method, action, body=None,
headers=None):
"""
Perform the HTTP request.
The response is in either JSON format or plain text. A GET method will
invoke a JSON response while a PUT/POST/DELETE returns message from the
VSM in plain text format.
Exception is raised when VSM replies with an INTERNAL SERVER ERROR HTTP
status code (500) i.e. an error has occurred on the VSM or SERVICE
UNAVAILABLE (503) i.e. VSM is not reachable.
:param method: type of the HTTP request. POST, GET, PUT or DELETE
:param action: path to which the client makes request
:param body: dict for arguments which are sent as part of the request
:param headers: header for the HTTP request
:returns: JSON or plain text in HTTP response
"""
action = self.action_prefix + action
if not headers and self.hosts:
headers = self._get_auth_header(self.hosts[0])
headers['Content-Type'] = self._set_content_type('json')
headers['Accept'] = self._set_content_type('json')
if body:
body = jsonutils.dumps(body, indent=2)
LOG.debug("req: %s", body)
try:
resp = self.pool.spawn(requests.request,
method,
url=action,
data=body,
headers=headers,
timeout=self.timeout).wait()
except Exception as e:
raise c_exc.VSMConnectionFailed(reason=e)
LOG.debug("status_code %s", resp.status_code)
if resp.status_code == requests.codes.OK:
if 'application/json' in resp.headers['content-type']:
try:
return resp.json()
except ValueError:
return {}
elif 'text/plain' in resp.headers['content-type']:
LOG.debug("VSM: %s", resp.text)
else:
raise c_exc.VSMError(reason=resp.text)
def _set_content_type(self, format=None):
"""
Set the mime-type to either 'xml' or 'json'.
:param format: format to be set.
:return: mime-type string
"""
if not format:
format = self.format
return "application/%s" % format
def _delete(self, action, body=None, headers=None):
return self._do_request("DELETE", action, body=body,
headers=headers)
def _get(self, action, body=None, headers=None):
return self._do_request("GET", action, body=body,
headers=headers)
def _post(self, action, body=None, headers=None):
return self._do_request("POST", action, body=body,
headers=headers)
def _put(self, action, body=None, headers=None):
return self._do_request("PUT", action, body=body,
headers=headers)
def _get_vsm_hosts(self):
"""
Retrieve a list of VSM ip addresses.
:return: list of host ip addresses
"""
return [cr[c_const.CREDENTIAL_NAME] for cr in
network_db_v2.get_all_n1kv_credentials()]
def _get_auth_header(self, host_ip):
"""
Retrieve header with auth info for the VSM.
:param host_ip: IP address of the VSM
:return: authorization header dict
"""
username = c_cred.Store.get_username(host_ip)
password = c_cred.Store.get_password(host_ip)
auth = safe_b64_encode("%s:%s" % (username, password))
header = {"Authorization": "Basic %s" % auth}
return header
def get_clusters(self):
"""Fetches a list of all vxlan gateway clusters."""
return self._get(self.clusters_path)
def create_encapsulation_profile(self, encap):
"""
Create an encapsulation profile on VSM.
:param encap: encapsulation dict
"""
body = {'name': encap['name'],
'addMappings': encap['add_segment_list'],
'delMappings': encap['del_segment_list']}
return self._post(self.encap_profiles_path,
body=body)
def update_encapsulation_profile(self, context, profile_name, body):
"""
Adds a vlan to bridge-domain mapping to an encapsulation profile.
:param profile_name: Name of the encapsulation profile
:param body: mapping dictionary
"""
return self._post(self.encap_profile_path
% profile_name, body=body)
def delete_encapsulation_profile(self, name):
"""
Delete an encapsulation profile on VSM.
:param name: name of the encapsulation profile to be deleted
"""
return self._delete(self.encap_profile_path % name)

File diff suppressed because it is too large Load Diff

View File

@ -1,171 +0,0 @@
# Copyright 2012 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.
from oslo_log import log as logging
from oslo_utils import importutils
import webob.exc as wexc
from neutron.api import extensions as neutron_extensions
from neutron.api.v2 import base
from neutron.db import db_base_plugin_v2
from neutron.plugins.cisco.common import cisco_exceptions as cexc
from neutron.plugins.cisco.common import config
from neutron.plugins.cisco.db import network_db_v2 as cdb
from neutron.plugins.cisco import extensions
LOG = logging.getLogger(__name__)
class PluginV2(db_base_plugin_v2.NeutronDbPluginV2):
"""Meta-Plugin with v2 API support for multiple sub-plugins."""
_supported_extension_aliases = ["credential", "Cisco qos"]
_methods_to_delegate = ['create_network',
'delete_network', 'update_network', 'get_network',
'get_networks',
'create_port', 'delete_port',
'update_port', 'get_port', 'get_ports',
'create_subnet',
'delete_subnet', 'update_subnet',
'get_subnet', 'get_subnets', ]
CISCO_FAULT_MAP = {
cexc.CredentialAlreadyExists: wexc.HTTPBadRequest,
cexc.CredentialNameNotFound: wexc.HTTPNotFound,
cexc.CredentialNotFound: wexc.HTTPNotFound,
cexc.NetworkSegmentIDNotFound: wexc.HTTPNotFound,
cexc.NetworkVlanBindingAlreadyExists: wexc.HTTPBadRequest,
cexc.NexusComputeHostNotConfigured: wexc.HTTPNotFound,
cexc.NexusConfigFailed: wexc.HTTPBadRequest,
cexc.NexusConnectFailed: wexc.HTTPServiceUnavailable,
cexc.NexusPortBindingNotFound: wexc.HTTPNotFound,
cexc.NoMoreNics: wexc.HTTPBadRequest,
cexc.PortIdForNexusSvi: wexc.HTTPBadRequest,
cexc.PortVnicBindingAlreadyExists: wexc.HTTPBadRequest,
cexc.PortVnicNotFound: wexc.HTTPNotFound,
cexc.QosNameAlreadyExists: wexc.HTTPBadRequest,
cexc.QosNotFound: wexc.HTTPNotFound,
cexc.SubnetNotSpecified: wexc.HTTPBadRequest,
cexc.VlanIDNotAvailable: wexc.HTTPNotFound,
cexc.VlanIDNotFound: wexc.HTTPNotFound,
}
@property
def supported_extension_aliases(self):
if not hasattr(self, '_aliases'):
aliases = self._supported_extension_aliases[:]
if hasattr(self._model, "supported_extension_aliases"):
aliases.extend(self._model.supported_extension_aliases)
self._aliases = aliases
return self._aliases
def __init__(self):
"""Load the model class."""
self._model_name = config.CISCO.model_class
self._model = importutils.import_object(self._model_name)
native_bulk_attr_name = ("_%s__native_bulk_support"
% self._model.__class__.__name__)
self.__native_bulk_support = getattr(self._model,
native_bulk_attr_name, False)
neutron_extensions.append_api_extensions_path(extensions.__path__)
# Extend the fault map
self._extend_fault_map()
LOG.debug("Plugin initialization complete")
def __getattribute__(self, name):
"""Delegate core API calls to the model class.
Core API calls are delegated directly to the configured model class.
Note: Bulking calls will be handled by this class, and turned into
non-bulking calls to be considered for delegation.
"""
methods = object.__getattribute__(self, "_methods_to_delegate")
if name in methods:
return getattr(object.__getattribute__(self, "_model"),
name)
else:
return object.__getattribute__(self, name)
def __getattr__(self, name):
"""Delegate calls to the extensions.
This delegates the calls to the extensions explicitly implemented by
the model.
"""
if hasattr(self._model, name):
return getattr(self._model, name)
else:
# Must make sure we re-raise the error that led us here, since
# otherwise getattr() and even hasattr() doesn't work correctly.
raise AttributeError(
_("'%(model)s' object has no attribute '%(name)s'") %
{'model': self._model_name, 'name': name})
def _extend_fault_map(self):
"""Extend the Neutron Fault Map for Cisco exceptions.
Map exceptions which are specific to the Cisco Plugin
to standard HTTP exceptions.
"""
base.FAULT_MAP.update(self.CISCO_FAULT_MAP)
#
# Extension API implementation
#
def get_all_qoss(self, tenant_id):
"""Get all QoS levels."""
LOG.debug("get_all_qoss() called")
qoslist = cdb.get_all_qoss(tenant_id)
return qoslist
def get_qos_details(self, tenant_id, qos_id):
"""Get QoS Details."""
LOG.debug("get_qos_details() called")
return cdb.get_qos(tenant_id, qos_id)
def create_qos(self, tenant_id, qos_name, qos_desc):
"""Create a QoS level."""
LOG.debug("create_qos() called")
qos = cdb.add_qos(tenant_id, qos_name, str(qos_desc))
return qos
def delete_qos(self, tenant_id, qos_id):
"""Delete a QoS level."""
LOG.debug("delete_qos() called")
return cdb.remove_qos(tenant_id, qos_id)
def rename_qos(self, tenant_id, qos_id, new_name):
"""Rename QoS level."""
LOG.debug("rename_qos() called")
return cdb.update_qos(tenant_id, qos_id, new_name)
def get_all_credentials(self):
"""Get all credentials."""
LOG.debug("get_all_credentials() called")
credential_list = cdb.get_all_credentials()
return credential_list
def get_credential_details(self, credential_id):
"""Get a particular credential."""
LOG.debug("get_credential_details() called")
return cdb.get_credential(credential_id)
def rename_credential(self, credential_id, new_name, new_password):
"""Rename the particular credential resource."""
LOG.debug("rename_credential() called")
return cdb.update_credential(credential_id, new_name,
new_password=new_password)

View File

@ -1,126 +0,0 @@
# Copyright 2014 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.plugins.cisco.common import cisco_exceptions as c_exc
from neutron.plugins.cisco.n1kv import n1kv_client
_resource_metadata = {'port': ['id', 'macAddress', 'ipAddress', 'subnetId'],
'vmnetwork': ['name', 'networkSegmentId',
'networkSegment', 'portProfile',
'portProfileId', 'tenantId',
'portId', 'macAddress',
'ipAddress', 'subnetId'],
'subnet': ['addressRangeStart', 'addressRangeEnd',
'ipAddressSubnet', 'description', 'gateway',
'dhcp', 'dnsServersList', 'networkAddress',
'netSegmentName', 'id', 'tenantId']}
class TestClient(n1kv_client.Client):
def __init__(self, **kwargs):
self.broken = False
self.inject_params = False
self.total_profiles = 2
super(TestClient, self).__init__()
def _get_total_profiles(self):
return self.total_profiles
def _do_request(self, method, action, body=None, headers=None):
if self.broken:
raise c_exc.VSMError(reason='VSM:Internal Server Error')
if self.inject_params and body:
body['invalidKey'] = 'catchMeIfYouCan'
if method == 'POST':
return _validate_resource(action, body)
elif method == 'GET':
if 'virtual-port-profile' in action:
return _policy_profile_generator(
self._get_total_profiles())
else:
raise c_exc.VSMError(reason='VSM:Internal Server Error')
class TestClientInvalidRequest(TestClient):
def __init__(self, **kwargs):
super(TestClientInvalidRequest, self).__init__()
self.inject_params = True
class TestClientInvalidResponse(TestClient):
def __init__(self, **kwargs):
super(TestClientInvalidResponse, self).__init__()
self.broken = True
def _validate_resource(action, body=None):
if body:
body_set = set(body.keys())
else:
return
if 'vm-network' in action and 'port' not in action:
vmnetwork_set = set(_resource_metadata['vmnetwork'])
if body_set - vmnetwork_set:
raise c_exc.VSMError(reason='Invalid Request')
elif 'port' in action:
port_set = set(_resource_metadata['port'])
if body_set - port_set:
raise c_exc.VSMError(reason='Invalid Request')
elif 'subnet' in action:
subnet_set = set(_resource_metadata['subnet'])
if body_set - subnet_set:
raise c_exc.VSMError(reason='Invalid Request')
else:
return
def _policy_profile_generator(total_profiles):
"""
Generate policy profile response and return a dictionary.
:param total_profiles: integer representing total number of profiles to
return
"""
profiles = {}
for num in range(1, total_profiles + 1):
name = "pp-%s" % num
profile_id = "00000000-0000-0000-0000-00000000000%s" % num
profiles[name] = {"properties": {"name": name, "id": profile_id}}
return profiles
def _policy_profile_generator_xml(total_profiles):
"""
Generate policy profile response in XML format.
:param total_profiles: integer representing total number of profiles to
return
"""
xml = ["""<?xml version="1.0" encoding="utf-8"?>
<set name="virtual_port_profile_set">"""]
template = (
'<instance name="%(num)d"'
' url="/api/n1k/virtual-port-profile/%(num)s">'
'<properties>'
'<id>00000000-0000-0000-0000-00000000000%(num)s</id>'
'<name>pp-%(num)s</name>'
'</properties>'
'</instance>'
)
xml.extend(template % {'num': n} for n in range(1, total_profiles + 1))
xml.append("</set>")
return ''.join(xml)

View File

@ -1,881 +0,0 @@
# Copyright 2013 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from six import moves
from sqlalchemy.orm import exc as s_exc
from testtools import matchers
from neutron.common import exceptions as n_exc
from neutron import context
from neutron.db import api as db
from neutron.db import common_db_mixin
from neutron.plugins.cisco.common import cisco_constants as c_const
from neutron.plugins.cisco.common import cisco_exceptions as c_exc
from neutron.plugins.cisco.db import n1kv_db_v2
from neutron.plugins.cisco.db import n1kv_models_v2
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
from neutron.tests.unit import testlib_api
PHYS_NET = 'physnet1'
PHYS_NET_2 = 'physnet2'
VLAN_MIN = 10
VLAN_MAX = 19
VXLAN_MIN = 5000
VXLAN_MAX = 5009
SEGMENT_RANGE = '200-220'
SEGMENT_RANGE_MIN_OVERLAP = '210-230'
SEGMENT_RANGE_MAX_OVERLAP = '190-209'
SEGMENT_RANGE_OVERLAP = '190-230'
TEST_NETWORK_ID = 'abcdefghijklmnopqrstuvwxyz'
TEST_NETWORK_ID2 = 'abcdefghijklmnopqrstuvwxy2'
TEST_NETWORK_ID3 = 'abcdefghijklmnopqrstuvwxy3'
TEST_NETWORK_PROFILE = {'name': 'test_profile',
'segment_type': c_const.NETWORK_TYPE_VLAN,
'physical_network': 'physnet1',
'segment_range': '10-19'}
TEST_NETWORK_PROFILE_2 = {'name': 'test_profile_2',
'segment_type': c_const.NETWORK_TYPE_VLAN,
'physical_network': 'physnet1',
'segment_range': SEGMENT_RANGE}
TEST_NETWORK_PROFILE_VXLAN = {'name': 'test_profile',
'segment_type': c_const.NETWORK_TYPE_OVERLAY,
'sub_type': c_const.NETWORK_SUBTYPE_NATIVE_VXLAN,
'segment_range': '5000-5009',
'multicast_ip_range': '239.0.0.70-239.0.0.80'}
TEST_POLICY_PROFILE = {'id': '4a417990-76fb-11e2-bcfd-0800200c9a66',
'name': 'test_policy_profile'}
TEST_NETWORK_PROFILE_MULTI_SEGMENT = {'name': 'test_profile',
'segment_type':
c_const.NETWORK_TYPE_MULTI_SEGMENT}
TEST_NETWORK_PROFILE_VLAN_TRUNK = {'name': 'test_profile',
'segment_type': c_const.NETWORK_TYPE_TRUNK,
'sub_type': c_const.NETWORK_TYPE_VLAN}
TEST_NETWORK_PROFILE_VXLAN_TRUNK = {'name': 'test_profile',
'segment_type': c_const.NETWORK_TYPE_TRUNK,
'sub_type': c_const.NETWORK_TYPE_OVERLAY}
def _create_test_network_profile_if_not_there(session,
profile=TEST_NETWORK_PROFILE):
try:
_profile = session.query(n1kv_models_v2.NetworkProfile).filter_by(
name=profile['name']).one()
except s_exc.NoResultFound:
_profile = n1kv_db_v2.create_network_profile(session, profile)
return _profile
def _create_test_policy_profile_if_not_there(session,
profile=TEST_POLICY_PROFILE):
try:
_profile = session.query(n1kv_models_v2.PolicyProfile).filter_by(
name=profile['name']).one()
except s_exc.NoResultFound:
_profile = n1kv_db_v2.create_policy_profile(profile)
return _profile
class VlanAllocationsTest(testlib_api.SqlTestCase):
def setUp(self):
super(VlanAllocationsTest, self).setUp()
self.session = db.get_session()
self.net_p = _create_test_network_profile_if_not_there(self.session)
n1kv_db_v2.sync_vlan_allocations(self.session, self.net_p)
def test_sync_vlan_allocations_outside_segment_range(self):
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
self.session,
PHYS_NET,
VLAN_MIN - 1)
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
self.session,
PHYS_NET,
VLAN_MAX + 1)
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
self.session,
PHYS_NET_2,
VLAN_MIN + 20)
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
self.session,
PHYS_NET_2,
VLAN_MIN + 20)
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
self.session,
PHYS_NET_2,
VLAN_MAX + 20)
def test_sync_vlan_allocations_unallocated_vlans(self):
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET,
VLAN_MIN).allocated)
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET,
VLAN_MIN + 1).
allocated)
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET,
VLAN_MAX - 1).
allocated)
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET,
VLAN_MAX).allocated)
def test_vlan_pool(self):
vlan_ids = set()
for x in moves.range(VLAN_MIN, VLAN_MAX + 1):
(physical_network, seg_type,
vlan_id, m_ip) = n1kv_db_v2.reserve_vlan(self.session, self.net_p)
self.assertEqual(physical_network, PHYS_NET)
self.assertThat(vlan_id, matchers.GreaterThan(VLAN_MIN - 1))
self.assertThat(vlan_id, matchers.LessThan(VLAN_MAX + 1))
vlan_ids.add(vlan_id)
self.assertRaises(n_exc.NoNetworkAvailable,
n1kv_db_v2.reserve_vlan,
self.session,
self.net_p)
n1kv_db_v2.release_vlan(self.session, PHYS_NET, vlan_ids.pop())
physical_network, seg_type, vlan_id, m_ip = (n1kv_db_v2.reserve_vlan(
self.session, self.net_p))
self.assertEqual(physical_network, PHYS_NET)
self.assertThat(vlan_id, matchers.GreaterThan(VLAN_MIN - 1))
self.assertThat(vlan_id, matchers.LessThan(VLAN_MAX + 1))
vlan_ids.add(vlan_id)
for vlan_id in vlan_ids:
n1kv_db_v2.release_vlan(self.session, PHYS_NET, vlan_id)
def test_specific_vlan_inside_pool(self):
vlan_id = VLAN_MIN + 5
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET,
vlan_id).allocated)
n1kv_db_v2.reserve_specific_vlan(self.session, PHYS_NET, vlan_id)
self.assertTrue(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET,
vlan_id).allocated)
self.assertRaises(n_exc.VlanIdInUse,
n1kv_db_v2.reserve_specific_vlan,
self.session,
PHYS_NET,
vlan_id)
n1kv_db_v2.release_vlan(self.session, PHYS_NET, vlan_id)
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET,
vlan_id).allocated)
def test_specific_vlan_outside_pool(self):
vlan_id = VLAN_MAX + 5
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
self.session,
PHYS_NET,
vlan_id)
self.assertRaises(c_exc.VlanIDOutsidePool,
n1kv_db_v2.reserve_specific_vlan,
self.session,
PHYS_NET,
vlan_id)
class VxlanAllocationsTest(testlib_api.SqlTestCase,
n1kv_db_v2.NetworkProfile_db_mixin):
def setUp(self):
super(VxlanAllocationsTest, self).setUp()
self.session = db.get_session()
self.net_p = _create_test_network_profile_if_not_there(
self.session, TEST_NETWORK_PROFILE_VXLAN)
n1kv_db_v2.sync_vxlan_allocations(self.session, self.net_p)
def test_sync_vxlan_allocations_outside_segment_range(self):
self.assertRaises(c_exc.VxlanIDNotFound,
n1kv_db_v2.get_vxlan_allocation,
self.session,
VXLAN_MIN - 1)
self.assertRaises(c_exc.VxlanIDNotFound,
n1kv_db_v2.get_vxlan_allocation,
self.session,
VXLAN_MAX + 1)
def test_sync_vxlan_allocations_unallocated_vxlans(self):
self.assertFalse(n1kv_db_v2.get_vxlan_allocation(self.session,
VXLAN_MIN).allocated)
self.assertFalse(n1kv_db_v2.get_vxlan_allocation(self.session,
VXLAN_MIN + 1).
allocated)
self.assertFalse(n1kv_db_v2.get_vxlan_allocation(self.session,
VXLAN_MAX - 1).
allocated)
self.assertFalse(n1kv_db_v2.get_vxlan_allocation(self.session,
VXLAN_MAX).allocated)
def test_vxlan_pool(self):
vxlan_ids = set()
for x in moves.range(VXLAN_MIN, VXLAN_MAX + 1):
vxlan = n1kv_db_v2.reserve_vxlan(self.session, self.net_p)
vxlan_id = vxlan[2]
self.assertThat(vxlan_id, matchers.GreaterThan(VXLAN_MIN - 1))
self.assertThat(vxlan_id, matchers.LessThan(VXLAN_MAX + 1))
vxlan_ids.add(vxlan_id)
self.assertRaises(n_exc.NoNetworkAvailable,
n1kv_db_v2.reserve_vxlan,
self.session,
self.net_p)
n1kv_db_v2.release_vxlan(self.session, vxlan_ids.pop())
vxlan = n1kv_db_v2.reserve_vxlan(self.session, self.net_p)
vxlan_id = vxlan[2]
self.assertThat(vxlan_id, matchers.GreaterThan(VXLAN_MIN - 1))
self.assertThat(vxlan_id, matchers.LessThan(VXLAN_MAX + 1))
vxlan_ids.add(vxlan_id)
for vxlan_id in vxlan_ids:
n1kv_db_v2.release_vxlan(self.session, vxlan_id)
n1kv_db_v2.delete_network_profile(self.session, self.net_p.id)
def test_specific_vxlan_inside_pool(self):
vxlan_id = VXLAN_MIN + 5
self.assertFalse(n1kv_db_v2.get_vxlan_allocation(self.session,
vxlan_id).allocated)
n1kv_db_v2.reserve_specific_vxlan(self.session, vxlan_id)
self.assertTrue(n1kv_db_v2.get_vxlan_allocation(self.session,
vxlan_id).allocated)
self.assertRaises(c_exc.VxlanIDInUse,
n1kv_db_v2.reserve_specific_vxlan,
self.session,
vxlan_id)
n1kv_db_v2.release_vxlan(self.session, vxlan_id)
self.assertFalse(n1kv_db_v2.get_vxlan_allocation(self.session,
vxlan_id).allocated)
def test_specific_vxlan_outside_pool(self):
vxlan_id = VXLAN_MAX + 5
self.assertRaises(c_exc.VxlanIDNotFound,
n1kv_db_v2.get_vxlan_allocation,
self.session,
vxlan_id)
self.assertRaises(c_exc.VxlanIDOutsidePool,
n1kv_db_v2.reserve_specific_vxlan,
self.session,
vxlan_id)
class NetworkBindingsTest(test_plugin.NeutronDbPluginV2TestCase):
def setUp(self):
super(NetworkBindingsTest, self).setUp()
self.session = db.get_session()
def test_add_network_binding(self):
with self.network() as network:
TEST_NETWORK_ID = network['network']['id']
self.assertRaises(c_exc.NetworkBindingNotFound,
n1kv_db_v2.get_network_binding,
self.session,
TEST_NETWORK_ID)
p = _create_test_network_profile_if_not_there(self.session)
n1kv_db_v2.add_network_binding(
self.session, TEST_NETWORK_ID, c_const.NETWORK_TYPE_VLAN,
PHYS_NET, 1234, '0.0.0.0', p.id, None)
binding = n1kv_db_v2.get_network_binding(
self.session, TEST_NETWORK_ID)
self.assertIsNotNone(binding)
self.assertEqual(binding.network_id, TEST_NETWORK_ID)
self.assertEqual(binding.network_type, c_const.NETWORK_TYPE_VLAN)
self.assertEqual(binding.physical_network, PHYS_NET)
self.assertEqual(binding.segmentation_id, 1234)
def test_create_multi_segment_network(self):
with self.network() as network:
TEST_NETWORK_ID = network['network']['id']
self.assertRaises(c_exc.NetworkBindingNotFound,
n1kv_db_v2.get_network_binding,
self.session,
TEST_NETWORK_ID)
p = _create_test_network_profile_if_not_there(
self.session,
TEST_NETWORK_PROFILE_MULTI_SEGMENT)
n1kv_db_v2.add_network_binding(
self.session, TEST_NETWORK_ID,
c_const.NETWORK_TYPE_MULTI_SEGMENT,
None, 0, '0.0.0.0', p.id, None)
binding = n1kv_db_v2.get_network_binding(
self.session, TEST_NETWORK_ID)
self.assertIsNotNone(binding)
self.assertEqual(binding.network_id, TEST_NETWORK_ID)
self.assertEqual(binding.network_type,
c_const.NETWORK_TYPE_MULTI_SEGMENT)
self.assertIsNone(binding.physical_network)
self.assertEqual(binding.segmentation_id, 0)
def test_add_multi_segment_binding(self):
with self.network() as network:
TEST_NETWORK_ID = network['network']['id']
self.assertRaises(c_exc.NetworkBindingNotFound,
n1kv_db_v2.get_network_binding,
self.session,
TEST_NETWORK_ID)
p = _create_test_network_profile_if_not_there(
self.session,
TEST_NETWORK_PROFILE_MULTI_SEGMENT)
n1kv_db_v2.add_network_binding(
self.session, TEST_NETWORK_ID,
c_const.NETWORK_TYPE_MULTI_SEGMENT,
None, 0, '0.0.0.0', p.id,
[(TEST_NETWORK_ID2, TEST_NETWORK_ID3)])
binding = n1kv_db_v2.get_network_binding(
self.session, TEST_NETWORK_ID)
self.assertIsNotNone(binding)
self.assertEqual(binding.network_id, TEST_NETWORK_ID)
self.assertEqual(binding.network_type,
c_const.NETWORK_TYPE_MULTI_SEGMENT)
self.assertIsNone(binding.physical_network)
self.assertEqual(binding.segmentation_id, 0)
ms_binding = (n1kv_db_v2.get_multi_segment_network_binding(
self.session, TEST_NETWORK_ID,
(TEST_NETWORK_ID2, TEST_NETWORK_ID3)))
self.assertIsNotNone(ms_binding)
self.assertEqual(ms_binding.multi_segment_id, TEST_NETWORK_ID)
self.assertEqual(ms_binding.segment1_id, TEST_NETWORK_ID2)
self.assertEqual(ms_binding.segment2_id, TEST_NETWORK_ID3)
ms_members = (n1kv_db_v2.get_multi_segment_members(
self.session, TEST_NETWORK_ID))
self.assertEqual(ms_members,
[(TEST_NETWORK_ID2, TEST_NETWORK_ID3)])
self.assertTrue(n1kv_db_v2.is_multi_segment_member(
self.session, TEST_NETWORK_ID2))
self.assertTrue(n1kv_db_v2.is_multi_segment_member(
self.session, TEST_NETWORK_ID3))
n1kv_db_v2.del_multi_segment_binding(
self.session, TEST_NETWORK_ID,
[(TEST_NETWORK_ID2, TEST_NETWORK_ID3)])
ms_members = (n1kv_db_v2.get_multi_segment_members(
self.session, TEST_NETWORK_ID))
self.assertEqual(ms_members, [])
def test_create_vlan_trunk_network(self):
with self.network() as network:
TEST_NETWORK_ID = network['network']['id']
self.assertRaises(c_exc.NetworkBindingNotFound,
n1kv_db_v2.get_network_binding,
self.session,
TEST_NETWORK_ID)
p = _create_test_network_profile_if_not_there(
self.session,
TEST_NETWORK_PROFILE_VLAN_TRUNK)
n1kv_db_v2.add_network_binding(
self.session, TEST_NETWORK_ID, c_const.NETWORK_TYPE_TRUNK,
None, 0, '0.0.0.0', p.id, None)
binding = n1kv_db_v2.get_network_binding(
self.session, TEST_NETWORK_ID)
self.assertIsNotNone(binding)
self.assertEqual(binding.network_id, TEST_NETWORK_ID)
self.assertEqual(binding.network_type, c_const.NETWORK_TYPE_TRUNK)
self.assertIsNone(binding.physical_network)
self.assertEqual(binding.segmentation_id, 0)
def test_create_vxlan_trunk_network(self):
with self.network() as network:
TEST_NETWORK_ID = network['network']['id']
self.assertRaises(c_exc.NetworkBindingNotFound,
n1kv_db_v2.get_network_binding,
self.session,
TEST_NETWORK_ID)
p = _create_test_network_profile_if_not_there(
self.session,
TEST_NETWORK_PROFILE_VXLAN_TRUNK)
n1kv_db_v2.add_network_binding(
self.session, TEST_NETWORK_ID, c_const.NETWORK_TYPE_TRUNK,
None, 0, '0.0.0.0', p.id, None)
binding = n1kv_db_v2.get_network_binding(
self.session, TEST_NETWORK_ID)
self.assertIsNotNone(binding)
self.assertEqual(binding.network_id, TEST_NETWORK_ID)
self.assertEqual(binding.network_type, c_const.NETWORK_TYPE_TRUNK)
self.assertIsNone(binding.physical_network)
self.assertEqual(binding.segmentation_id, 0)
def test_add_vlan_trunk_binding(self):
with self.network() as network1:
with self.network() as network2:
TEST_NETWORK_ID = network1['network']['id']
self.assertRaises(c_exc.NetworkBindingNotFound,
n1kv_db_v2.get_network_binding,
self.session,
TEST_NETWORK_ID)
TEST_NETWORK_ID2 = network2['network']['id']
self.assertRaises(c_exc.NetworkBindingNotFound,
n1kv_db_v2.get_network_binding,
self.session,
TEST_NETWORK_ID2)
p_v = _create_test_network_profile_if_not_there(self.session)
n1kv_db_v2.add_network_binding(
self.session, TEST_NETWORK_ID2, c_const.NETWORK_TYPE_VLAN,
PHYS_NET, 1234, '0.0.0.0', p_v.id, None)
p = _create_test_network_profile_if_not_there(
self.session,
TEST_NETWORK_PROFILE_VLAN_TRUNK)
n1kv_db_v2.add_network_binding(
self.session, TEST_NETWORK_ID, c_const.NETWORK_TYPE_TRUNK,
None, 0, '0.0.0.0', p.id, [(TEST_NETWORK_ID2, 0)])
binding = n1kv_db_v2.get_network_binding(
self.session, TEST_NETWORK_ID)
self.assertIsNotNone(binding)
self.assertEqual(binding.network_id, TEST_NETWORK_ID)
self.assertEqual(binding.network_type,
c_const.NETWORK_TYPE_TRUNK)
self.assertEqual(binding.physical_network, PHYS_NET)
self.assertEqual(binding.segmentation_id, 0)
t_binding = (n1kv_db_v2.get_trunk_network_binding(
self.session, TEST_NETWORK_ID,
(TEST_NETWORK_ID2, 0)))
self.assertIsNotNone(t_binding)
self.assertEqual(t_binding.trunk_segment_id, TEST_NETWORK_ID)
self.assertEqual(t_binding.segment_id, TEST_NETWORK_ID2)
self.assertEqual(t_binding.dot1qtag, '0')
t_members = (n1kv_db_v2.get_trunk_members(
self.session, TEST_NETWORK_ID))
self.assertEqual(t_members,
[(TEST_NETWORK_ID2, '0')])
self.assertTrue(n1kv_db_v2.is_trunk_member(
self.session, TEST_NETWORK_ID2))
n1kv_db_v2.del_trunk_segment_binding(
self.session, TEST_NETWORK_ID,
[(TEST_NETWORK_ID2, '0')])
t_members = (n1kv_db_v2.get_multi_segment_members(
self.session, TEST_NETWORK_ID))
self.assertEqual(t_members, [])
def test_add_vxlan_trunk_binding(self):
with self.network() as network1:
with self.network() as network2:
TEST_NETWORK_ID = network1['network']['id']
self.assertRaises(c_exc.NetworkBindingNotFound,
n1kv_db_v2.get_network_binding,
self.session,
TEST_NETWORK_ID)
TEST_NETWORK_ID2 = network2['network']['id']
self.assertRaises(c_exc.NetworkBindingNotFound,
n1kv_db_v2.get_network_binding,
self.session,
TEST_NETWORK_ID2)
p_v = _create_test_network_profile_if_not_there(
self.session, TEST_NETWORK_PROFILE_VXLAN_TRUNK)
n1kv_db_v2.add_network_binding(
self.session, TEST_NETWORK_ID2,
c_const.NETWORK_TYPE_OVERLAY,
None, 5100, '224.10.10.10', p_v.id, None)
p = _create_test_network_profile_if_not_there(
self.session,
TEST_NETWORK_PROFILE_VXLAN_TRUNK)
n1kv_db_v2.add_network_binding(
self.session, TEST_NETWORK_ID, c_const.NETWORK_TYPE_TRUNK,
None, 0, '0.0.0.0', p.id,
[(TEST_NETWORK_ID2, 5)])
binding = n1kv_db_v2.get_network_binding(
self.session, TEST_NETWORK_ID)
self.assertIsNotNone(binding)
self.assertEqual(binding.network_id, TEST_NETWORK_ID)
self.assertEqual(binding.network_type,
c_const.NETWORK_TYPE_TRUNK)
self.assertIsNone(binding.physical_network)
self.assertEqual(binding.segmentation_id, 0)
t_binding = (n1kv_db_v2.get_trunk_network_binding(
self.session, TEST_NETWORK_ID,
(TEST_NETWORK_ID2, '5')))
self.assertIsNotNone(t_binding)
self.assertEqual(t_binding.trunk_segment_id, TEST_NETWORK_ID)
self.assertEqual(t_binding.segment_id, TEST_NETWORK_ID2)
self.assertEqual(t_binding.dot1qtag, '5')
t_members = (n1kv_db_v2.get_trunk_members(
self.session, TEST_NETWORK_ID))
self.assertEqual(t_members,
[(TEST_NETWORK_ID2, '5')])
self.assertTrue(n1kv_db_v2.is_trunk_member(
self.session, TEST_NETWORK_ID2))
n1kv_db_v2.del_trunk_segment_binding(
self.session, TEST_NETWORK_ID,
[(TEST_NETWORK_ID2, '5')])
t_members = (n1kv_db_v2.get_multi_segment_members(
self.session, TEST_NETWORK_ID))
self.assertEqual(t_members, [])
class NetworkProfileTests(testlib_api.SqlTestCase,
n1kv_db_v2.NetworkProfile_db_mixin):
def setUp(self):
super(NetworkProfileTests, self).setUp()
self.session = db.get_session()
def test_create_network_profile(self):
_db_profile = n1kv_db_v2.create_network_profile(self.session,
TEST_NETWORK_PROFILE)
self.assertIsNotNone(_db_profile)
db_profile = (self.session.query(n1kv_models_v2.NetworkProfile).
filter_by(name=TEST_NETWORK_PROFILE['name']).one())
self.assertIsNotNone(db_profile)
self.assertEqual(_db_profile.id, db_profile.id)
self.assertEqual(_db_profile.name, db_profile.name)
self.assertEqual(_db_profile.segment_type, db_profile.segment_type)
self.assertEqual(_db_profile.segment_range, db_profile.segment_range)
self.assertEqual(_db_profile.multicast_ip_index,
db_profile.multicast_ip_index)
self.assertEqual(_db_profile.multicast_ip_range,
db_profile.multicast_ip_range)
n1kv_db_v2.delete_network_profile(self.session, _db_profile.id)
def test_create_multi_segment_network_profile(self):
_db_profile = (n1kv_db_v2.create_network_profile(
self.session, TEST_NETWORK_PROFILE_MULTI_SEGMENT))
self.assertIsNotNone(_db_profile)
db_profile = (
self.session.query(
n1kv_models_v2.NetworkProfile).filter_by(
name=TEST_NETWORK_PROFILE_MULTI_SEGMENT['name'])
.one())
self.assertIsNotNone(db_profile)
self.assertEqual(_db_profile.id, db_profile.id)
self.assertEqual(_db_profile.name, db_profile.name)
self.assertEqual(_db_profile.segment_type, db_profile.segment_type)
self.assertEqual(_db_profile.segment_range, db_profile.segment_range)
self.assertEqual(_db_profile.multicast_ip_index,
db_profile.multicast_ip_index)
self.assertEqual(_db_profile.multicast_ip_range,
db_profile.multicast_ip_range)
n1kv_db_v2.delete_network_profile(self.session, _db_profile.id)
def test_create_vlan_trunk_network_profile(self):
_db_profile = (n1kv_db_v2.create_network_profile(
self.session, TEST_NETWORK_PROFILE_VLAN_TRUNK))
self.assertIsNotNone(_db_profile)
db_profile = (self.session.query(n1kv_models_v2.NetworkProfile).
filter_by(name=TEST_NETWORK_PROFILE_VLAN_TRUNK['name']).
one())
self.assertIsNotNone(db_profile)
self.assertEqual(_db_profile.id, db_profile.id)
self.assertEqual(_db_profile.name, db_profile.name)
self.assertEqual(_db_profile.segment_type, db_profile.segment_type)
self.assertEqual(_db_profile.segment_range, db_profile.segment_range)
self.assertEqual(_db_profile.multicast_ip_index,
db_profile.multicast_ip_index)
self.assertEqual(_db_profile.multicast_ip_range,
db_profile.multicast_ip_range)
self.assertEqual(_db_profile.sub_type, db_profile.sub_type)
n1kv_db_v2.delete_network_profile(self.session, _db_profile.id)
def test_create_vxlan_trunk_network_profile(self):
_db_profile = (n1kv_db_v2.create_network_profile(
self.session, TEST_NETWORK_PROFILE_VXLAN_TRUNK))
self.assertIsNotNone(_db_profile)
db_profile = (self.session.query(n1kv_models_v2.NetworkProfile).
filter_by(name=TEST_NETWORK_PROFILE_VXLAN_TRUNK['name']).
one())
self.assertIsNotNone(db_profile)
self.assertEqual(_db_profile.id, db_profile.id)
self.assertEqual(_db_profile.name, db_profile.name)
self.assertEqual(_db_profile.segment_type, db_profile.segment_type)
self.assertEqual(_db_profile.segment_range, db_profile.segment_range)
self.assertEqual(_db_profile.multicast_ip_index,
db_profile.multicast_ip_index)
self.assertEqual(_db_profile.multicast_ip_range,
db_profile.multicast_ip_range)
self.assertEqual(_db_profile.sub_type, db_profile.sub_type)
n1kv_db_v2.delete_network_profile(self.session, _db_profile.id)
def test_create_network_profile_overlap(self):
_db_profile = n1kv_db_v2.create_network_profile(self.session,
TEST_NETWORK_PROFILE_2)
ctx = context.get_admin_context()
TEST_NETWORK_PROFILE_2['name'] = 'net-profile-min-overlap'
TEST_NETWORK_PROFILE_2['segment_range'] = SEGMENT_RANGE_MIN_OVERLAP
test_net_profile = {'network_profile': TEST_NETWORK_PROFILE_2}
self.assertRaises(n_exc.InvalidInput,
self.create_network_profile,
ctx,
test_net_profile)
TEST_NETWORK_PROFILE_2['name'] = 'net-profile-max-overlap'
TEST_NETWORK_PROFILE_2['segment_range'] = SEGMENT_RANGE_MAX_OVERLAP
test_net_profile = {'network_profile': TEST_NETWORK_PROFILE_2}
self.assertRaises(n_exc.InvalidInput,
self.create_network_profile,
ctx,
test_net_profile)
TEST_NETWORK_PROFILE_2['name'] = 'net-profile-overlap'
TEST_NETWORK_PROFILE_2['segment_range'] = SEGMENT_RANGE_OVERLAP
test_net_profile = {'network_profile': TEST_NETWORK_PROFILE_2}
self.assertRaises(n_exc.InvalidInput,
self.create_network_profile,
ctx,
test_net_profile)
n1kv_db_v2.delete_network_profile(self.session, _db_profile.id)
def test_delete_network_profile(self):
try:
profile = (self.session.query(n1kv_models_v2.NetworkProfile).
filter_by(name=TEST_NETWORK_PROFILE['name']).one())
except s_exc.NoResultFound:
profile = n1kv_db_v2.create_network_profile(self.session,
TEST_NETWORK_PROFILE)
n1kv_db_v2.delete_network_profile(self.session, profile.id)
try:
self.session.query(n1kv_models_v2.NetworkProfile).filter_by(
name=TEST_NETWORK_PROFILE['name']).one()
except s_exc.NoResultFound:
pass
else:
self.fail("Network Profile (%s) was not deleted" %
TEST_NETWORK_PROFILE['name'])
def test_update_network_profile(self):
TEST_PROFILE_1 = {'name': 'test_profile_1'}
profile = _create_test_network_profile_if_not_there(self.session)
updated_profile = n1kv_db_v2.update_network_profile(self.session,
profile.id,
TEST_PROFILE_1)
self.assertEqual(updated_profile.name, TEST_PROFILE_1['name'])
n1kv_db_v2.delete_network_profile(self.session, profile.id)
def test_get_network_profile(self):
profile = n1kv_db_v2.create_network_profile(self.session,
TEST_NETWORK_PROFILE)
got_profile = n1kv_db_v2.get_network_profile(self.session, profile.id)
self.assertEqual(profile.id, got_profile.id)
self.assertEqual(profile.name, got_profile.name)
n1kv_db_v2.delete_network_profile(self.session, profile.id)
def test_get_network_profiles(self):
test_profiles = [{'name': 'test_profile1',
'segment_type': c_const.NETWORK_TYPE_VLAN,
'physical_network': 'phys1',
'segment_range': '200-210'},
{'name': 'test_profile2',
'segment_type': c_const.NETWORK_TYPE_VLAN,
'physical_network': 'phys1',
'segment_range': '211-220'},
{'name': 'test_profile3',
'segment_type': c_const.NETWORK_TYPE_VLAN,
'physical_network': 'phys1',
'segment_range': '221-230'},
{'name': 'test_profile4',
'segment_type': c_const.NETWORK_TYPE_VLAN,
'physical_network': 'phys1',
'segment_range': '231-240'},
{'name': 'test_profile5',
'segment_type': c_const.NETWORK_TYPE_VLAN,
'physical_network': 'phys1',
'segment_range': '241-250'},
{'name': 'test_profile6',
'segment_type': c_const.NETWORK_TYPE_VLAN,
'physical_network': 'phys1',
'segment_range': '251-260'},
{'name': 'test_profile7',
'segment_type': c_const.NETWORK_TYPE_VLAN,
'physical_network': 'phys1',
'segment_range': '261-270'}]
[n1kv_db_v2.create_network_profile(self.session, p)
for p in test_profiles]
# TODO(abhraut): Fix this test to work with real tenant_td
profiles = n1kv_db_v2._get_network_profiles(db_session=self.session)
self.assertEqual(len(test_profiles), len(list(profiles)))
class PolicyProfileTests(testlib_api.SqlTestCase):
def setUp(self):
super(PolicyProfileTests, self).setUp()
self.session = db.get_session()
def test_create_policy_profile(self):
_db_profile = n1kv_db_v2.create_policy_profile(TEST_POLICY_PROFILE)
self.assertIsNotNone(_db_profile)
db_profile = (self.session.query(n1kv_models_v2.PolicyProfile).
filter_by(name=TEST_POLICY_PROFILE['name']).one)()
self.assertIsNotNone(db_profile)
self.assertTrue(_db_profile.id == db_profile.id)
self.assertTrue(_db_profile.name == db_profile.name)
def test_delete_policy_profile(self):
profile = _create_test_policy_profile_if_not_there(self.session)
n1kv_db_v2.delete_policy_profile(profile.id)
try:
self.session.query(n1kv_models_v2.PolicyProfile).filter_by(
name=TEST_POLICY_PROFILE['name']).one()
except s_exc.NoResultFound:
pass
else:
self.fail("Policy Profile (%s) was not deleted" %
TEST_POLICY_PROFILE['name'])
def test_update_policy_profile(self):
TEST_PROFILE_1 = {'name': 'test_profile_1'}
profile = _create_test_policy_profile_if_not_there(self.session)
updated_profile = n1kv_db_v2.update_policy_profile(self.session,
profile.id,
TEST_PROFILE_1)
self.assertEqual(updated_profile.name, TEST_PROFILE_1['name'])
def test_get_policy_profile(self):
profile = _create_test_policy_profile_if_not_there(self.session)
got_profile = n1kv_db_v2.get_policy_profile(self.session, profile.id)
self.assertEqual(profile.id, got_profile.id)
self.assertEqual(profile.name, got_profile.name)
class ProfileBindingTests(testlib_api.SqlTestCase,
n1kv_db_v2.NetworkProfile_db_mixin,
common_db_mixin.CommonDbMixin):
def setUp(self):
super(ProfileBindingTests, self).setUp()
self.session = db.get_session()
def _create_test_binding_if_not_there(self, tenant_id, profile_id,
profile_type):
try:
_binding = (self.session.query(n1kv_models_v2.ProfileBinding).
filter_by(profile_type=profile_type,
tenant_id=tenant_id,
profile_id=profile_id).one())
except s_exc.NoResultFound:
_binding = n1kv_db_v2.create_profile_binding(self.session,
tenant_id,
profile_id,
profile_type)
return _binding
def test_create_profile_binding(self):
test_tenant_id = "d434dd90-76ec-11e2-bcfd-0800200c9a66"
test_profile_id = "dd7b9741-76ec-11e2-bcfd-0800200c9a66"
test_profile_type = "network"
n1kv_db_v2.create_profile_binding(self.session,
test_tenant_id,
test_profile_id,
test_profile_type)
try:
self.session.query(n1kv_models_v2.ProfileBinding).filter_by(
profile_type=test_profile_type,
tenant_id=test_tenant_id,
profile_id=test_profile_id).one()
except s_exc.MultipleResultsFound:
self.fail("Bindings must be unique")
except s_exc.NoResultFound:
self.fail("Could not create Profile Binding")
def test_update_profile_binding(self):
test_tenant_id = "d434dd90-76ec-11e2-bcfd-0800200c9a66"
test_profile_id = "dd7b9741-76ec-11e2-bcfd-0800200c9a66"
test_profile_type = "network"
n1kv_db_v2.create_profile_binding(self.session,
test_tenant_id,
test_profile_id,
test_profile_type)
new_tenants = ['d434dd90-76ec-11e2-bcfd-0800200c9a67',
'd434dd90-76ec-11e2-bcfd-0800200c9a68',
'd434dd90-76ec-11e2-bcfd-0800200c9a69']
n1kv_db_v2.update_profile_binding(self.session,
test_profile_id,
new_tenants,
test_profile_type)
result = self.session.query(n1kv_models_v2.ProfileBinding).filter_by(
profile_type=test_profile_type,
profile_id=test_profile_id).all()
self.assertEqual(3, len(result))
def test_get_profile_binding(self):
test_tenant_id = "d434dd90-76ec-11e2-bcfd-0800200c9a66"
test_profile_id = "dd7b9741-76ec-11e2-bcfd-0800200c9a66"
test_profile_type = "network"
self._create_test_binding_if_not_there(test_tenant_id,
test_profile_id,
test_profile_type)
binding = n1kv_db_v2.get_profile_binding(self.session,
test_tenant_id,
test_profile_id)
self.assertEqual(binding.tenant_id, test_tenant_id)
self.assertEqual(binding.profile_id, test_profile_id)
self.assertEqual(binding.profile_type, test_profile_type)
def test_get_profile_binding_not_found(self):
self.assertRaises(
c_exc.ProfileTenantBindingNotFound,
n1kv_db_v2.get_profile_binding, self.session, "123", "456")
def test_delete_profile_binding(self):
test_tenant_id = "d434dd90-76ec-11e2-bcfd-0800200c9a66"
test_profile_id = "dd7b9741-76ec-11e2-bcfd-0800200c9a66"
test_profile_type = "network"
self._create_test_binding_if_not_there(test_tenant_id,
test_profile_id,
test_profile_type)
n1kv_db_v2.delete_profile_binding(self.session,
test_tenant_id,
test_profile_id)
q = (self.session.query(n1kv_models_v2.ProfileBinding).filter_by(
profile_type=test_profile_type,
tenant_id=test_tenant_id,
profile_id=test_profile_id))
self.assertFalse(q.count())
def test_default_tenant_replace(self):
ctx = context.get_admin_context()
ctx.tenant_id = "d434dd90-76ec-11e2-bcfd-0800200c9a66"
test_profile_id = "AAAAAAAA-76ec-11e2-bcfd-0800200c9a66"
test_profile_type = "policy"
n1kv_db_v2.create_profile_binding(self.session,
c_const.TENANT_ID_NOT_SET,
test_profile_id,
test_profile_type)
network_profile = {"network_profile": TEST_NETWORK_PROFILE}
self.create_network_profile(ctx, network_profile)
binding = n1kv_db_v2.get_profile_binding(self.session,
ctx.tenant_id,
test_profile_id)
self.assertRaises(
c_exc.ProfileTenantBindingNotFound,
n1kv_db_v2.get_profile_binding,
self.session,
c_const.TENANT_ID_NOT_SET,
test_profile_id)
self.assertNotEqual(binding.tenant_id,
c_const.TENANT_ID_NOT_SET)

File diff suppressed because it is too large Load Diff

View File

@ -1,309 +0,0 @@
# Copyright (c) 2013 OpenStack Foundation
# 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 collections
import mock
import testtools
from neutron.plugins.cisco.common import cisco_constants
from neutron.plugins.cisco.common import cisco_credentials_v2
from neutron.plugins.cisco.common import cisco_exceptions as c_exc
from neutron.plugins.cisco.common import config as config
from neutron.plugins.cisco.db import network_db_v2 as cdb
from neutron.plugins.cisco import network_plugin
from neutron.tests.unit import testlib_api
class CiscoNetworkDbTest(testlib_api.SqlTestCase):
"""Base class for Cisco network database unit tests."""
def setUp(self):
super(CiscoNetworkDbTest, self).setUp()
# The Cisco network plugin includes a thin layer of QoS and
# credential API methods which indirectly call Cisco QoS and
# credential database access methods. For better code coverage,
# this test suite will make calls to the QoS and credential database
# access methods indirectly through the network plugin. The network
# plugin's init function can be mocked out for this purpose.
def new_network_plugin_init(instance):
pass
with mock.patch.object(network_plugin.PluginV2,
'__init__', new=new_network_plugin_init):
self._network_plugin = network_plugin.PluginV2()
class CiscoNetworkQosDbTest(CiscoNetworkDbTest):
"""Unit tests for Cisco network QoS database model."""
QosObj = collections.namedtuple('QosObj', 'tenant qname desc')
def _qos_test_obj(self, tnum, qnum, desc=None):
"""Create a Qos test object from a pair of numbers."""
if desc is None:
desc = 'test qos %s-%s' % (str(tnum), str(qnum))
tenant = 'tenant_%s' % str(tnum)
qname = 'qos_%s' % str(qnum)
return self.QosObj(tenant, qname, desc)
def _assert_equal(self, qos, qos_obj):
self.assertEqual(qos.tenant_id, qos_obj.tenant)
self.assertEqual(qos.qos_name, qos_obj.qname)
self.assertEqual(qos.qos_desc, qos_obj.desc)
def test_qos_add_remove(self):
qos11 = self._qos_test_obj(1, 1)
qos = self._network_plugin.create_qos(qos11.tenant, qos11.qname,
qos11.desc)
self._assert_equal(qos, qos11)
qos_id = qos.qos_id
qos = self._network_plugin.delete_qos(qos11.tenant, qos_id)
self._assert_equal(qos, qos11)
qos = self._network_plugin.delete_qos(qos11.tenant, qos_id)
self.assertIsNone(qos)
def test_qos_add_dup(self):
qos22 = self._qos_test_obj(2, 2)
qos = self._network_plugin.create_qos(qos22.tenant, qos22.qname,
qos22.desc)
self._assert_equal(qos, qos22)
qos_id = qos.qos_id
with testtools.ExpectedException(c_exc.QosNameAlreadyExists):
self._network_plugin.create_qos(qos22.tenant, qos22.qname,
"duplicate 22")
qos = self._network_plugin.delete_qos(qos22.tenant, qos_id)
self._assert_equal(qos, qos22)
qos = self._network_plugin.delete_qos(qos22.tenant, qos_id)
self.assertIsNone(qos)
def test_qos_get(self):
qos11 = self._qos_test_obj(1, 1)
qos11_id = self._network_plugin.create_qos(qos11.tenant, qos11.qname,
qos11.desc).qos_id
qos21 = self._qos_test_obj(2, 1)
qos21_id = self._network_plugin.create_qos(qos21.tenant, qos21.qname,
qos21.desc).qos_id
qos22 = self._qos_test_obj(2, 2)
qos22_id = self._network_plugin.create_qos(qos22.tenant, qos22.qname,
qos22.desc).qos_id
qos = self._network_plugin.get_qos_details(qos11.tenant, qos11_id)
self._assert_equal(qos, qos11)
qos = self._network_plugin.get_qos_details(qos21.tenant, qos21_id)
self._assert_equal(qos, qos21)
qos = self._network_plugin.get_qos_details(qos21.tenant, qos22_id)
self._assert_equal(qos, qos22)
with testtools.ExpectedException(c_exc.QosNotFound):
self._network_plugin.get_qos_details(qos11.tenant, "dummyQosId")
with testtools.ExpectedException(c_exc.QosNotFound):
self._network_plugin.get_qos_details(qos11.tenant, qos21_id)
with testtools.ExpectedException(c_exc.QosNotFound):
self._network_plugin.get_qos_details(qos21.tenant, qos11_id)
qos_all_t1 = self._network_plugin.get_all_qoss(qos11.tenant)
self.assertEqual(len(qos_all_t1), 1)
qos_all_t2 = self._network_plugin.get_all_qoss(qos21.tenant)
self.assertEqual(len(qos_all_t2), 2)
qos_all_t3 = self._network_plugin.get_all_qoss("tenant3")
self.assertEqual(len(qos_all_t3), 0)
def test_qos_update(self):
qos11 = self._qos_test_obj(1, 1)
qos11_id = self._network_plugin.create_qos(qos11.tenant, qos11.qname,
qos11.desc).qos_id
self._network_plugin.rename_qos(qos11.tenant, qos11_id,
new_name=None)
new_qname = "new qos name"
new_qos = self._network_plugin.rename_qos(qos11.tenant, qos11_id,
new_qname)
expected_qobj = self.QosObj(qos11.tenant, new_qname, qos11.desc)
self._assert_equal(new_qos, expected_qobj)
new_qos = self._network_plugin.get_qos_details(qos11.tenant, qos11_id)
self._assert_equal(new_qos, expected_qobj)
with testtools.ExpectedException(c_exc.QosNotFound):
self._network_plugin.rename_qos(qos11.tenant, "dummyQosId",
new_name=None)
class CiscoNetworkCredentialDbTest(CiscoNetworkDbTest):
"""Unit tests for Cisco network credentials database model."""
CredObj = collections.namedtuple('CredObj', 'cname usr pwd ctype')
def _cred_test_obj(self, tnum, cnum):
"""Create a Credential test object from a pair of numbers."""
cname = 'credential_%s_%s' % (str(tnum), str(cnum))
usr = 'User_%s_%s' % (str(tnum), str(cnum))
pwd = 'Password_%s_%s' % (str(tnum), str(cnum))
ctype = 'ctype_%s' % str(tnum)
return self.CredObj(cname, usr, pwd, ctype)
def _assert_equal(self, credential, cred_obj):
self.assertEqual(credential.type, cred_obj.ctype)
self.assertEqual(credential.credential_name, cred_obj.cname)
self.assertEqual(credential.user_name, cred_obj.usr)
self.assertEqual(credential.password, cred_obj.pwd)
def test_credential_add_remove(self):
cred11 = self._cred_test_obj(1, 1)
cred = cdb.add_credential(
cred11.cname, cred11.usr, cred11.pwd, cred11.ctype)
self._assert_equal(cred, cred11)
cred_id = cred.credential_id
cred = cdb.remove_credential(cred_id)
self._assert_equal(cred, cred11)
cred = cdb.remove_credential(cred_id)
self.assertIsNone(cred)
def test_credential_add_dup(self):
cred22 = self._cred_test_obj(2, 2)
cred = cdb.add_credential(
cred22.cname, cred22.usr, cred22.pwd, cred22.ctype)
self._assert_equal(cred, cred22)
cred_id = cred.credential_id
with testtools.ExpectedException(c_exc.CredentialAlreadyExists):
cdb.add_credential(
cred22.cname, cred22.usr, cred22.pwd, cred22.ctype)
cred = cdb.remove_credential(cred_id)
self._assert_equal(cred, cred22)
cred = cdb.remove_credential(cred_id)
self.assertIsNone(cred)
def test_credential_get_id(self):
cred11 = self._cred_test_obj(1, 1)
cred11_id = cdb.add_credential(
cred11.cname, cred11.usr, cred11.pwd, cred11.ctype).credential_id
cred21 = self._cred_test_obj(2, 1)
cred21_id = cdb.add_credential(
cred21.cname, cred21.usr, cred21.pwd, cred21.ctype).credential_id
cred22 = self._cred_test_obj(2, 2)
cred22_id = cdb.add_credential(
cred22.cname, cred22.usr, cred22.pwd, cred22.ctype).credential_id
cred = self._network_plugin.get_credential_details(cred11_id)
self._assert_equal(cred, cred11)
cred = self._network_plugin.get_credential_details(cred21_id)
self._assert_equal(cred, cred21)
cred = self._network_plugin.get_credential_details(cred22_id)
self._assert_equal(cred, cred22)
with testtools.ExpectedException(c_exc.CredentialNotFound):
self._network_plugin.get_credential_details("dummyCredentialId")
cred_all_t1 = self._network_plugin.get_all_credentials()
self.assertEqual(len(cred_all_t1), 3)
def test_credential_get_name(self):
cred11 = self._cred_test_obj(1, 1)
cred11_id = cdb.add_credential(
cred11.cname, cred11.usr, cred11.pwd, cred11.ctype).credential_id
cred21 = self._cred_test_obj(2, 1)
cred21_id = cdb.add_credential(
cred21.cname, cred21.usr, cred21.pwd, cred21.ctype).credential_id
cred22 = self._cred_test_obj(2, 2)
cred22_id = cdb.add_credential(
cred22.cname, cred22.usr, cred22.pwd, cred22.ctype).credential_id
self.assertNotEqual(cred11_id, cred21_id)
self.assertNotEqual(cred11_id, cred22_id)
self.assertNotEqual(cred21_id, cred22_id)
cred = cdb.get_credential_name(cred11.cname)
self._assert_equal(cred, cred11)
cred = cdb.get_credential_name(cred21.cname)
self._assert_equal(cred, cred21)
cred = cdb.get_credential_name(cred22.cname)
self._assert_equal(cred, cred22)
with testtools.ExpectedException(c_exc.CredentialNameNotFound):
cdb.get_credential_name("dummyCredentialName")
def test_credential_update(self):
cred11 = self._cred_test_obj(1, 1)
cred11_id = cdb.add_credential(
cred11.cname, cred11.usr, cred11.pwd, cred11.ctype).credential_id
self._network_plugin.rename_credential(cred11_id, new_name=None,
new_password=None)
new_usr = "new user name"
new_pwd = "new password"
new_credential = self._network_plugin.rename_credential(
cred11_id, new_usr, new_pwd)
expected_cred = self.CredObj(
cred11.cname, new_usr, new_pwd, cred11.ctype)
self._assert_equal(new_credential, expected_cred)
new_credential = self._network_plugin.get_credential_details(
cred11_id)
self._assert_equal(new_credential, expected_cred)
with testtools.ExpectedException(c_exc.CredentialNotFound):
self._network_plugin.rename_credential(
"dummyCredentialId", new_usr, new_pwd)
def test_get_credential_not_found_exception(self):
self.assertRaises(c_exc.CredentialNotFound,
self._network_plugin.get_credential_details,
"dummyCredentialId")
def test_credential_delete_all_n1kv(self):
cred_nexus_1 = self._cred_test_obj('nexus', 1)
cred_nexus_2 = self._cred_test_obj('nexus', 2)
cred_n1kv_1 = self.CredObj('n1kv-1', 'cisco', '123456', 'n1kv')
cred_n1kv_2 = self.CredObj('n1kv-2', 'cisco', '123456', 'n1kv')
cred_nexus_1_id = cdb.add_credential(
cred_nexus_1.cname, cred_nexus_1.usr,
cred_nexus_1.pwd, cred_nexus_1.ctype).credential_id
cred_nexus_2_id = cdb.add_credential(
cred_nexus_2.cname, cred_nexus_2.usr,
cred_nexus_2.pwd, cred_nexus_2.ctype).credential_id
cred_n1kv_1_id = cdb.add_credential(
cred_n1kv_1.cname, cred_n1kv_1.usr,
cred_n1kv_1.pwd, cred_n1kv_1.ctype).credential_id
cred_n1kv_2_id = cdb.add_credential(
cred_n1kv_2.cname, cred_n1kv_2.usr,
cred_n1kv_2.pwd, cred_n1kv_2.ctype).credential_id
cdb.delete_all_n1kv_credentials()
cred = cdb.get_credential(cred_nexus_1_id)
self.assertIsNotNone(cred)
cred = cdb.get_credential(cred_nexus_2_id)
self.assertIsNotNone(cred)
self.assertRaises(c_exc.CredentialNotFound,
cdb.get_credential, cred_n1kv_1_id)
self.assertRaises(c_exc.CredentialNotFound,
cdb.get_credential, cred_n1kv_2_id)
class CiscoCredentialStoreTest(testlib_api.SqlTestCase):
"""Cisco Credential Store unit tests."""
def test_cred_store_init_duplicate_creds_ignored(self):
"""Check that with multi store instances, dup creds are ignored."""
# Create a device dictionary containing credentials for 1 switch.
dev_dict = {
('dev_id', '1.1.1.1', cisco_constants.USERNAME): 'user_1',
('dev_id', '1.1.1.1', cisco_constants.PASSWORD): 'password_1',
('dev_id', '1.1.1.1', 'host_a'): '1/1',
('dev_id', '1.1.1.1', 'host_b'): '1/2',
('dev_id', '1.1.1.1', 'host_c'): '1/3',
}
with mock.patch.object(config, 'get_device_dictionary',
return_value=dev_dict):
# Create and initialize 2 instances of credential store.
cisco_credentials_v2.Store().initialize()
cisco_credentials_v2.Store().initialize()
# There should be only 1 switch credential in the database.
self.assertEqual(len(cdb.get_all_credentials()), 1)

View File

@ -52,7 +52,6 @@ data_files =
etc/neutron/plugins/brocade/vyatta = etc/neutron/plugins/brocade/vyatta/vrouter.ini
etc/neutron/plugins/cisco =
etc/neutron/plugins/cisco/cisco_cfg_agent.ini
etc/neutron/plugins/cisco/cisco_plugins.ini
etc/neutron/plugins/cisco/cisco_router_plugin.ini
etc/neutron/plugins/cisco/cisco_vpn_agent.ini
etc/neutron/plugins/embrane = etc/neutron/plugins/embrane/heleos_conf.ini
@ -105,7 +104,6 @@ console_scripts =
neutron.core_plugins =
bigswitch = neutron.plugins.bigswitch.plugin:NeutronRestProxyV2
brocade = neutron.plugins.brocade.NeutronPlugin:BrocadePluginV2
cisco = neutron.plugins.cisco.network_plugin:PluginV2
embrane = neutron.plugins.embrane.plugins.embrane_ml2_plugin:EmbraneMl2Plugin
midonet = neutron.plugins.midonet.plugin:MidonetPluginV2
ml2 = neutron.plugins.ml2.plugin:Ml2Plugin