Remove Cisco Meta and N1KV monolithic plugins
This patch removes the Cisco meta plugin and the Cisco Nexus1000V monolithic plugin as they were deprecated in the previous cycle. Closes-bug: #1473217 Change-Id: Id170b9512b2f52a971264336d83b083d487359ee
This commit is contained in:
parent
72d9d2cea9
commit
d12017ad51
@ -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
|
@ -1,2 +1,2 @@
|
||||
11926bcfe72d
|
||||
34af2b5c5a59
|
||||
4af11ca47297
|
||||
|
@ -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')
|
@ -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
|
||||
|
@ -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
|
@ -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'
|
||||
|
@ -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]
|
@ -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.")
|
@ -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.')
|
@ -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
@ -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))
|
@ -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)
|
@ -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)
|
@ -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']))
|
@ -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']))
|
@ -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)]
|
@ -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 {}
|
@ -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
|
@ -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
|
@ -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))
|
@ -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
|
@ -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
|
@ -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
@ -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)
|
@ -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)
|
@ -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
@ -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)
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user