Merge "remove linuxbridge plugin"
This commit is contained in:
commit
1874af10d9
@ -75,9 +75,10 @@ OPENVSWITCH = 'openvswitch'
|
||||
|
||||
# Releases
|
||||
ICEHOUSE = 'icehouse'
|
||||
JUNO = 'juno'
|
||||
|
||||
|
||||
SUPPORTED_SCHEMA_VERSIONS = [ICEHOUSE]
|
||||
SUPPORTED_SCHEMA_VERSIONS = [ICEHOUSE, JUNO]
|
||||
|
||||
|
||||
def check_db_schema_version(engine, metadata):
|
||||
@ -115,7 +116,7 @@ def interpret_vlan_id(vlan_id):
|
||||
return (p_const.TYPE_VLAN, vlan_id)
|
||||
|
||||
|
||||
class BaseMigrateToMl2_Icehouse(object):
|
||||
class BaseMigrateToMl2(object):
|
||||
|
||||
def __init__(self, vif_type, driver_type, segment_table_name,
|
||||
vlan_allocation_table_name, old_tables):
|
||||
@ -210,6 +211,13 @@ class BaseMigrateToMl2_Icehouse(object):
|
||||
ml2_port_bindings = metadata.tables['ml2_port_bindings']
|
||||
engine.execute(ml2_port_bindings.insert(), ml2_bindings)
|
||||
|
||||
|
||||
class BaseMigrateToMl2_IcehouseMixin(object):
|
||||
"""A mixin to ensure ml2 database schema state for Icehouse.
|
||||
|
||||
This classes the missing tables for Icehouse schema revisions. In Juno,
|
||||
the schema state has been healed, so we do not need to run these.
|
||||
"""
|
||||
def drop_old_tables(self, engine, save_tables=False):
|
||||
if save_tables:
|
||||
return
|
||||
@ -351,10 +359,10 @@ class BaseMigrateToMl2_Icehouse(object):
|
||||
)
|
||||
|
||||
|
||||
class MigrateLinuxBridgeToMl2_Icehouse(BaseMigrateToMl2_Icehouse):
|
||||
class MigrateLinuxBridgeToMl2_Juno(BaseMigrateToMl2):
|
||||
|
||||
def __init__(self):
|
||||
super(MigrateLinuxBridgeToMl2_Icehouse, self).__init__(
|
||||
super(MigrateLinuxBridgeToMl2_Juno, self).__init__(
|
||||
vif_type=portbindings.VIF_TYPE_BRIDGE,
|
||||
driver_type=LINUXBRIDGE,
|
||||
segment_table_name='network_bindings',
|
||||
@ -362,7 +370,7 @@ class MigrateLinuxBridgeToMl2_Icehouse(BaseMigrateToMl2_Icehouse):
|
||||
old_tables=['portbindingports'])
|
||||
|
||||
def migrate_segment_dict(self, binding):
|
||||
super(MigrateLinuxBridgeToMl2_Icehouse, self).migrate_segment_dict(
|
||||
super(MigrateLinuxBridgeToMl2_Juno, self).migrate_segment_dict(
|
||||
binding)
|
||||
vlan_id = binding.pop('vlan_id')
|
||||
network_type, segmentation_id = interpret_vlan_id(vlan_id)
|
||||
@ -370,10 +378,10 @@ class MigrateLinuxBridgeToMl2_Icehouse(BaseMigrateToMl2_Icehouse):
|
||||
binding['segmentation_id'] = segmentation_id
|
||||
|
||||
|
||||
class MigrateOpenvswitchToMl2_Icehouse(BaseMigrateToMl2_Icehouse):
|
||||
class MigrateOpenvswitchToMl2_Juno(BaseMigrateToMl2):
|
||||
|
||||
def __init__(self):
|
||||
super(MigrateOpenvswitchToMl2_Icehouse, self).__init__(
|
||||
super(MigrateOpenvswitchToMl2_Juno, self).__init__(
|
||||
vif_type=portbindings.VIF_TYPE_OVS,
|
||||
driver_type=OPENVSWITCH,
|
||||
segment_table_name='ovs_network_bindings',
|
||||
@ -415,11 +423,25 @@ class MigrateOpenvswitchToMl2_Icehouse(BaseMigrateToMl2_Icehouse):
|
||||
raise ValueError(_('Unknown tunnel type: %s') % tunnel_type)
|
||||
|
||||
|
||||
class MigrateLinuxBridgeToMl2_Icehouse(MigrateLinuxBridgeToMl2_Juno,
|
||||
BaseMigrateToMl2_IcehouseMixin):
|
||||
pass
|
||||
|
||||
|
||||
class MigrateOpenvswitchToMl2_Icehouse(MigrateOpenvswitchToMl2_Juno,
|
||||
BaseMigrateToMl2_IcehouseMixin):
|
||||
pass
|
||||
|
||||
|
||||
migrate_map = {
|
||||
ICEHOUSE: {
|
||||
OPENVSWITCH: MigrateOpenvswitchToMl2_Icehouse,
|
||||
LINUXBRIDGE: MigrateLinuxBridgeToMl2_Icehouse,
|
||||
},
|
||||
JUNO: {
|
||||
OPENVSWITCH: MigrateOpenvswitchToMl2_Juno,
|
||||
LINUXBRIDGE: MigrateLinuxBridgeToMl2_Juno,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -436,7 +458,7 @@ def main():
|
||||
OPENVSWITCH)
|
||||
parser.add_argument('--vxlan-udp-port', default=None, type=int,
|
||||
help=_('The UDP port to use for VXLAN tunnels.'))
|
||||
parser.add_argument('--release', default=ICEHOUSE, choices=[ICEHOUSE])
|
||||
parser.add_argument('--release', default=JUNO, choices=[ICEHOUSE, JUNO])
|
||||
parser.add_argument('--save-tables', default=False, action='store_true',
|
||||
help=_("Retain the old plugin's tables"))
|
||||
#TODO(marun) Provide a verbose option
|
||||
|
@ -1,128 +1,7 @@
|
||||
# -- Background
|
||||
|
||||
The Neutron Linux Bridge plugin is a plugin that allows you to manage
|
||||
connectivity between VMs on hosts that are capable of running a Linux Bridge.
|
||||
|
||||
The Neutron Linux Bridge plugin consists of three components:
|
||||
|
||||
1) The plugin itself: The plugin uses a database backend (mysql for
|
||||
now) to store configuration and mappings that are used by the
|
||||
agent. The mysql server runs on a central server (often the same
|
||||
host as nova itself).
|
||||
|
||||
2) The neutron service host which will be running neutron. This can
|
||||
be run on the server running nova.
|
||||
|
||||
3) An agent which runs on the host and communicates with the host operating
|
||||
system. The agent gathers the configuration and mappings from
|
||||
the mysql database running on the neutron host.
|
||||
|
||||
The sections below describe how to configure and run the neutron
|
||||
service with the Linux Bridge plugin.
|
||||
|
||||
# -- Python library dependencies
|
||||
|
||||
Make sure you have the following package(s) installed on neutron server
|
||||
host as well as any hosts which run the agent:
|
||||
bridge-utils
|
||||
python-mysqldb
|
||||
sqlite3
|
||||
|
||||
# -- Nova configuration (controller node)
|
||||
|
||||
1) Ensure that the neutron network manager is configured in the
|
||||
nova.conf on the node that will be running nova-network.
|
||||
|
||||
network_manager=nova.network.neutron.manager.NeutronManager
|
||||
|
||||
# -- Nova configuration (compute node(s))
|
||||
|
||||
1) Configure the vif driver, and libvirt/vif type
|
||||
|
||||
connection_type=libvirt
|
||||
libvirt_type=qemu
|
||||
libvirt_vif_type=ethernet
|
||||
libvirt_vif_driver=nova.virt.libvirt.vif.NeutronLinuxBridgeVIFDriver
|
||||
linuxnet_interface_driver=nova.network.linux_net.NeutronLinuxBridgeInterfaceDriver
|
||||
|
||||
2) If you want a DHCP server to be run for the VMs to acquire IPs,
|
||||
add the following flag to your nova.conf file:
|
||||
|
||||
neutron_use_dhcp=true
|
||||
|
||||
(Note: For more details on how to work with Neutron using Nova, i.e. how to create networks and such,
|
||||
please refer to the top level Neutron README which points to the relevant documentation.)
|
||||
|
||||
# -- Neutron configuration
|
||||
|
||||
Make the Linux Bridge plugin the current neutron plugin
|
||||
|
||||
- edit neutron.conf and change the core_plugin
|
||||
|
||||
core_plugin = neutron.plugins.linuxbridge.lb_neutron_plugin.LinuxBridgePluginV2
|
||||
|
||||
# -- Database config.
|
||||
|
||||
(Note: The plugin ships with a default SQLite in-memory database configuration,
|
||||
and can be used to run tests without performing the suggested DB config below.)
|
||||
|
||||
The Linux Bridge neutron plugin requires access to a mysql database in order
|
||||
to store configuration and mappings that will be used by the agent. Here is
|
||||
how to set up the database on the host that you will be running the neutron
|
||||
service on.
|
||||
|
||||
MySQL should be installed on the host, and all plugins and clients
|
||||
must be configured with access to the database.
|
||||
|
||||
To prep mysql, run:
|
||||
|
||||
$ mysql -u root -p -e "create database neutron_linux_bridge"
|
||||
|
||||
# log in to mysql service
|
||||
$ mysql -u root -p
|
||||
# The Linux Bridge Neutron agent running on each compute node must be able to
|
||||
# make a mysql connection back to the main database server.
|
||||
mysql> GRANT USAGE ON *.* to root@'yourremotehost' IDENTIFIED BY 'newpassword';
|
||||
# force update of authorization changes
|
||||
mysql> FLUSH PRIVILEGES;
|
||||
|
||||
(Note: If the remote connection fails to MySQL, you might need to add the IP address,
|
||||
and/or fully-qualified hostname, and/or unqualified hostname in the above GRANT sql
|
||||
command. Also, you might need to specify "ALL" instead of "USAGE".)
|
||||
|
||||
# -- Plugin configuration
|
||||
|
||||
- Edit the configuration file:
|
||||
etc/neutron/plugins/linuxbridge/linuxbridge_conf.ini
|
||||
Make sure it matches your mysql configuration. This file must be updated
|
||||
with the addresses and credentials to access the database.
|
||||
|
||||
Note: debug and logging information should be updated in etc/neutron.conf
|
||||
|
||||
Note: When running the tests, set the connection type to sqlite, and when
|
||||
actually running the server set it to mysql. At any given time, only one
|
||||
of these should be active in the conf file (you can comment out the other).
|
||||
|
||||
- On the neutron server, network_vlan_ranges must be configured in
|
||||
linuxbridge_conf.ini to specify the names of the physical networks
|
||||
managed by the linuxbridge plugin, along with the ranges of VLAN IDs
|
||||
available on each physical network for allocation to virtual
|
||||
networks. An entry of the form
|
||||
"<physical_network>:<vlan_min>:<vlan_max>" specifies a VLAN range on
|
||||
the named physical network. An entry of the form
|
||||
"<physical_network>" specifies a named network without making a
|
||||
range of VLANs available for allocation. Networks specified using
|
||||
either form are available for adminstrators to create provider flat
|
||||
networks and provider VLANs. Multiple VLAN ranges can be specified
|
||||
for the same physical network.
|
||||
|
||||
The following example linuxbridge_conf.ini entry shows three
|
||||
physical networks that can be used to create provider networks, with
|
||||
ranges of VLANs available for allocation on two of them:
|
||||
|
||||
[VLANS]
|
||||
network_vlan_ranges = physnet1:1000:2999,physnet1:3000:3999,physnet2,physnet3:1:4094
|
||||
|
||||
The Neutron Linux Bridge plugin has removed from the tree in Juno. You must
|
||||
migrate to ML2 using the script in: neutron/db/migration/migrate_to_ml2.py
|
||||
|
||||
# -- Agent configuration
|
||||
|
||||
|
@ -1,238 +0,0 @@
|
||||
# Copyright (c) 2012 OpenStack Foundation.
|
||||
#
|
||||
# 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
|
||||
|
||||
from neutron.common import exceptions as n_exc
|
||||
import neutron.db.api as db
|
||||
from neutron.db import models_v2
|
||||
from neutron.db import securitygroups_db as sg_db
|
||||
from neutron import manager
|
||||
from neutron.openstack.common import log as logging
|
||||
from neutron.plugins.linuxbridge.common import config # noqa
|
||||
from neutron.plugins.linuxbridge.common import constants
|
||||
from neutron.plugins.linuxbridge.db import l2network_models_v2
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def sync_network_states(network_vlan_ranges):
|
||||
"""Synchronize network_states table with current configured VLAN ranges."""
|
||||
|
||||
session = db.get_session()
|
||||
with session.begin():
|
||||
# get existing allocations for all physical networks
|
||||
allocations = dict()
|
||||
states = (session.query(l2network_models_v2.NetworkState).
|
||||
all())
|
||||
for state in states:
|
||||
if state.physical_network not in allocations:
|
||||
allocations[state.physical_network] = set()
|
||||
allocations[state.physical_network].add(state)
|
||||
|
||||
# process vlan ranges for each configured physical network
|
||||
for physical_network, vlan_ranges in network_vlan_ranges.iteritems():
|
||||
# determine current configured allocatable vlans for this
|
||||
# physical network
|
||||
vlan_ids = set()
|
||||
for vlan_range in vlan_ranges:
|
||||
vlan_ids |= set(moves.xrange(vlan_range[0], vlan_range[1] + 1))
|
||||
|
||||
# remove from table unallocated vlans not currently allocatable
|
||||
if physical_network in allocations:
|
||||
for state in allocations[physical_network]:
|
||||
try:
|
||||
# see if vlan is allocatable
|
||||
vlan_ids.remove(state.vlan_id)
|
||||
except KeyError:
|
||||
# it's not allocatable, so check if its allocated
|
||||
if not state.allocated:
|
||||
# it's not, so remove it from table
|
||||
LOG.debug(_("Removing vlan %(vlan_id)s on "
|
||||
"physical network %(physical_network)s"
|
||||
" from pool"),
|
||||
{'vlan_id': state.vlan_id,
|
||||
'physical_network': physical_network})
|
||||
session.delete(state)
|
||||
del allocations[physical_network]
|
||||
|
||||
# add missing allocatable vlans to table
|
||||
for vlan_id in sorted(vlan_ids):
|
||||
state = l2network_models_v2.NetworkState(physical_network,
|
||||
vlan_id)
|
||||
session.add(state)
|
||||
|
||||
# remove from table unallocated vlans for any unconfigured physical
|
||||
# networks
|
||||
for states in allocations.itervalues():
|
||||
for state in states:
|
||||
if not state.allocated:
|
||||
LOG.debug(_("Removing vlan %(vlan_id)s on physical "
|
||||
"network %(physical_network)s"
|
||||
" from pool"),
|
||||
{'vlan_id': state.vlan_id,
|
||||
'physical_network': state.physical_network})
|
||||
session.delete(state)
|
||||
|
||||
|
||||
def get_network_state(physical_network, vlan_id):
|
||||
"""Get state of specified network."""
|
||||
|
||||
session = db.get_session()
|
||||
try:
|
||||
state = (session.query(l2network_models_v2.NetworkState).
|
||||
filter_by(physical_network=physical_network,
|
||||
vlan_id=vlan_id).
|
||||
one())
|
||||
return state
|
||||
except exc.NoResultFound:
|
||||
return None
|
||||
|
||||
|
||||
def reserve_network(session):
|
||||
with session.begin(subtransactions=True):
|
||||
state = (session.query(l2network_models_v2.NetworkState).
|
||||
filter_by(allocated=False).
|
||||
with_lockmode('update').
|
||||
first())
|
||||
if not state:
|
||||
raise n_exc.NoNetworkAvailable()
|
||||
LOG.debug(_("Reserving vlan %(vlan_id)s on physical network "
|
||||
"%(physical_network)s from pool"),
|
||||
{'vlan_id': state.vlan_id,
|
||||
'physical_network': state.physical_network})
|
||||
state.allocated = True
|
||||
return (state.physical_network, state.vlan_id)
|
||||
|
||||
|
||||
def reserve_specific_network(session, physical_network, vlan_id):
|
||||
with session.begin(subtransactions=True):
|
||||
try:
|
||||
state = (session.query(l2network_models_v2.NetworkState).
|
||||
filter_by(physical_network=physical_network,
|
||||
vlan_id=vlan_id).
|
||||
with_lockmode('update').
|
||||
one())
|
||||
if state.allocated:
|
||||
if vlan_id == constants.FLAT_VLAN_ID:
|
||||
raise n_exc.FlatNetworkInUse(
|
||||
physical_network=physical_network)
|
||||
else:
|
||||
raise n_exc.VlanIdInUse(vlan_id=vlan_id,
|
||||
physical_network=physical_network)
|
||||
LOG.debug(_("Reserving specific vlan %(vlan_id)s on physical "
|
||||
"network %(physical_network)s from pool"),
|
||||
{'vlan_id': vlan_id,
|
||||
'physical_network': physical_network})
|
||||
state.allocated = True
|
||||
except exc.NoResultFound:
|
||||
LOG.debug(_("Reserving specific vlan %(vlan_id)s on physical "
|
||||
"network %(physical_network)s outside pool"),
|
||||
{'vlan_id': vlan_id,
|
||||
'physical_network': physical_network})
|
||||
state = l2network_models_v2.NetworkState(physical_network, vlan_id)
|
||||
state.allocated = True
|
||||
session.add(state)
|
||||
|
||||
|
||||
def release_network(session, physical_network, vlan_id, network_vlan_ranges):
|
||||
with session.begin(subtransactions=True):
|
||||
try:
|
||||
state = (session.query(l2network_models_v2.NetworkState).
|
||||
filter_by(physical_network=physical_network,
|
||||
vlan_id=vlan_id).
|
||||
with_lockmode('update').
|
||||
one())
|
||||
state.allocated = False
|
||||
inside = False
|
||||
for vlan_range in network_vlan_ranges.get(physical_network, []):
|
||||
if vlan_id >= vlan_range[0] and vlan_id <= vlan_range[1]:
|
||||
inside = True
|
||||
break
|
||||
if inside:
|
||||
LOG.debug(_("Releasing vlan %(vlan_id)s on physical network "
|
||||
"%(physical_network)s to pool"),
|
||||
{'vlan_id': vlan_id,
|
||||
'physical_network': physical_network})
|
||||
else:
|
||||
LOG.debug(_("Releasing vlan %(vlan_id)s on physical network "
|
||||
"%(physical_network)s outside pool"),
|
||||
{'vlan_id': vlan_id,
|
||||
'physical_network': physical_network})
|
||||
session.delete(state)
|
||||
except exc.NoResultFound:
|
||||
LOG.warning(_("vlan_id %(vlan_id)s on physical network "
|
||||
"%(physical_network)s not found"),
|
||||
{'vlan_id': vlan_id,
|
||||
'physical_network': physical_network})
|
||||
|
||||
|
||||
def add_network_binding(session, network_id, physical_network, vlan_id):
|
||||
with session.begin(subtransactions=True):
|
||||
binding = l2network_models_v2.NetworkBinding(network_id,
|
||||
physical_network, vlan_id)
|
||||
session.add(binding)
|
||||
|
||||
|
||||
def get_network_binding(session, network_id):
|
||||
try:
|
||||
binding = (session.query(l2network_models_v2.NetworkBinding).
|
||||
filter_by(network_id=network_id).
|
||||
one())
|
||||
return binding
|
||||
except exc.NoResultFound:
|
||||
return
|
||||
|
||||
|
||||
def get_port_from_device(device):
|
||||
"""Get port from database."""
|
||||
LOG.debug(_("get_port_from_device() called"))
|
||||
session = db.get_session()
|
||||
sg_binding_port = sg_db.SecurityGroupPortBinding.port_id
|
||||
|
||||
query = session.query(models_v2.Port,
|
||||
sg_db.SecurityGroupPortBinding.security_group_id)
|
||||
query = query.outerjoin(sg_db.SecurityGroupPortBinding,
|
||||
models_v2.Port.id == sg_binding_port)
|
||||
query = query.filter(models_v2.Port.id.startswith(device))
|
||||
port_and_sgs = query.all()
|
||||
if not port_and_sgs:
|
||||
return
|
||||
port = port_and_sgs[0][0]
|
||||
plugin = manager.NeutronManager.get_plugin()
|
||||
port_dict = plugin._make_port_dict(port)
|
||||
port_dict['security_groups'] = []
|
||||
for port_in_db, sg_id in port_and_sgs:
|
||||
if sg_id:
|
||||
port_dict['security_groups'].append(sg_id)
|
||||
port_dict['security_group_rules'] = []
|
||||
port_dict['security_group_source_groups'] = []
|
||||
port_dict['fixed_ips'] = [ip['ip_address']
|
||||
for ip in port['fixed_ips']]
|
||||
return port_dict
|
||||
|
||||
|
||||
def set_port_status(port_id, status):
|
||||
"""Set the port status."""
|
||||
LOG.debug(_("set_port_status as %s called"), status)
|
||||
session = db.get_session()
|
||||
try:
|
||||
port = session.query(models_v2.Port).filter_by(id=port_id).one()
|
||||
port['status'] = status
|
||||
session.merge(port)
|
||||
session.flush()
|
||||
except exc.NoResultFound:
|
||||
raise n_exc.PortNotFound(port_id=port_id)
|
@ -1,544 +0,0 @@
|
||||
# Copyright (c) 2012 OpenStack Foundation.
|
||||
#
|
||||
# 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 sys
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
from neutron.agent import securitygroups_rpc as sg_rpc
|
||||
from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api
|
||||
from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api
|
||||
from neutron.api.rpc.handlers import dhcp_rpc
|
||||
from neutron.api.rpc.handlers import l3_rpc
|
||||
from neutron.api.rpc.handlers import securitygroups_rpc
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.common import constants as q_const
|
||||
from neutron.common import exceptions as n_exc
|
||||
from neutron.common import rpc as n_rpc
|
||||
from neutron.common import topics
|
||||
from neutron.common import utils
|
||||
from neutron.db import agents_db
|
||||
from neutron.db import agentschedulers_db
|
||||
from neutron.db import api as db_api
|
||||
from neutron.db import db_base_plugin_v2
|
||||
from neutron.db import external_net_db
|
||||
from neutron.db import extraroute_db
|
||||
from neutron.db import l3_agentschedulers_db
|
||||
from neutron.db import l3_gwmode_db
|
||||
from neutron.db import portbindings_db
|
||||
from neutron.db import quota_db # noqa
|
||||
from neutron.db import securitygroups_rpc_base as sg_db_rpc
|
||||
from neutron.extensions import portbindings
|
||||
from neutron.extensions import providernet as provider
|
||||
from neutron import manager
|
||||
from neutron.openstack.common import importutils
|
||||
from neutron.openstack.common import log as logging
|
||||
from neutron.plugins.common import constants as svc_constants
|
||||
from neutron.plugins.common import utils as plugin_utils
|
||||
from neutron.plugins.linuxbridge.common import constants
|
||||
from neutron.plugins.linuxbridge.db import l2network_db_v2 as db
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LinuxBridgeRpcCallbacks(n_rpc.RpcCallback):
|
||||
|
||||
# Device names start with "tap"
|
||||
# history
|
||||
# 1.1 Support Security Group RPC
|
||||
# 1.2 Support get_devices_details_list
|
||||
RPC_API_VERSION = '1.2'
|
||||
|
||||
def get_device_details(self, rpc_context, **kwargs):
|
||||
"""Agent requests device details."""
|
||||
agent_id = kwargs.get('agent_id')
|
||||
device = kwargs.get('device')
|
||||
LOG.debug(_("Device %(device)s details requested from %(agent_id)s"),
|
||||
{'device': device, 'agent_id': agent_id})
|
||||
plugin = manager.NeutronManager.get_plugin()
|
||||
port = plugin.get_port_from_device(device)
|
||||
if port:
|
||||
binding = db.get_network_binding(db_api.get_session(),
|
||||
port['network_id'])
|
||||
(network_type,
|
||||
segmentation_id) = constants.interpret_vlan_id(binding.vlan_id)
|
||||
entry = {'device': device,
|
||||
'network_type': network_type,
|
||||
'physical_network': binding.physical_network,
|
||||
'segmentation_id': segmentation_id,
|
||||
'network_id': port['network_id'],
|
||||
'port_id': port['id'],
|
||||
'admin_state_up': port['admin_state_up']}
|
||||
if cfg.CONF.AGENT.rpc_support_old_agents:
|
||||
entry['vlan_id'] = binding.vlan_id
|
||||
new_status = (q_const.PORT_STATUS_ACTIVE if port['admin_state_up']
|
||||
else q_const.PORT_STATUS_DOWN)
|
||||
if port['status'] != new_status:
|
||||
db.set_port_status(port['id'], new_status)
|
||||
else:
|
||||
entry = {'device': device}
|
||||
LOG.debug(_("%s can not be found in database"), device)
|
||||
return entry
|
||||
|
||||
def get_devices_details_list(self, rpc_context, **kwargs):
|
||||
return [
|
||||
self.get_device_details(
|
||||
rpc_context,
|
||||
device=device,
|
||||
**kwargs
|
||||
)
|
||||
for device in kwargs.pop('devices', [])
|
||||
]
|
||||
|
||||
def update_device_down(self, rpc_context, **kwargs):
|
||||
"""Device no longer exists on agent."""
|
||||
# TODO(garyk) - live migration and port status
|
||||
agent_id = kwargs.get('agent_id')
|
||||
device = kwargs.get('device')
|
||||
host = kwargs.get('host')
|
||||
LOG.debug(_("Device %(device)s no longer exists on %(agent_id)s"),
|
||||
{'device': device, 'agent_id': agent_id})
|
||||
plugin = manager.NeutronManager.get_plugin()
|
||||
port = plugin.get_port_from_device(device)
|
||||
if port:
|
||||
entry = {'device': device,
|
||||
'exists': True}
|
||||
if (host and not
|
||||
plugin.get_port_host(rpc_context, port['id']) == host):
|
||||
LOG.debug(_("Device %(device)s not bound to the"
|
||||
" agent host %(host)s"),
|
||||
{'device': device, 'host': host})
|
||||
elif port['status'] != q_const.PORT_STATUS_DOWN:
|
||||
# Set port status to DOWN
|
||||
db.set_port_status(port['id'], q_const.PORT_STATUS_DOWN)
|
||||
else:
|
||||
entry = {'device': device,
|
||||
'exists': False}
|
||||
LOG.debug(_("%s can not be found in database"), device)
|
||||
return entry
|
||||
|
||||
def update_device_up(self, rpc_context, **kwargs):
|
||||
"""Device is up on agent."""
|
||||
agent_id = kwargs.get('agent_id')
|
||||
device = kwargs.get('device')
|
||||
host = kwargs.get('host')
|
||||
LOG.debug(_("Device %(device)s up on %(agent_id)s"),
|
||||
{'device': device, 'agent_id': agent_id})
|
||||
plugin = manager.NeutronManager.get_plugin()
|
||||
port = plugin.get_port_from_device(device)
|
||||
if port:
|
||||
if (host and
|
||||
not plugin.get_port_host(rpc_context, port['id']) == host):
|
||||
LOG.debug(_("Device %(device)s not bound to the"
|
||||
" agent host %(host)s"),
|
||||
{'device': device, 'host': host})
|
||||
return
|
||||
elif port['status'] != q_const.PORT_STATUS_ACTIVE:
|
||||
db.set_port_status(port['id'],
|
||||
q_const.PORT_STATUS_ACTIVE)
|
||||
else:
|
||||
LOG.debug(_("%s can not be found in database"), device)
|
||||
|
||||
|
||||
class AgentNotifierApi(n_rpc.RpcProxy,
|
||||
sg_rpc.SecurityGroupAgentRpcApiMixin):
|
||||
'''Agent side of the linux bridge rpc API.
|
||||
|
||||
API version history:
|
||||
1.0 - Initial version.
|
||||
1.1 - Added get_active_networks_info, create_dhcp_port,
|
||||
and update_dhcp_port methods.
|
||||
|
||||
|
||||
'''
|
||||
|
||||
BASE_RPC_API_VERSION = '1.1'
|
||||
|
||||
def __init__(self, topic):
|
||||
super(AgentNotifierApi, self).__init__(
|
||||
topic=topic, default_version=self.BASE_RPC_API_VERSION)
|
||||
self.topic = topic
|
||||
self.topic_network_delete = topics.get_topic_name(topic,
|
||||
topics.NETWORK,
|
||||
topics.DELETE)
|
||||
self.topic_port_update = topics.get_topic_name(topic,
|
||||
topics.PORT,
|
||||
topics.UPDATE)
|
||||
|
||||
def network_delete(self, context, network_id):
|
||||
self.fanout_cast(context,
|
||||
self.make_msg('network_delete',
|
||||
network_id=network_id),
|
||||
topic=self.topic_network_delete)
|
||||
|
||||
def port_update(self, context, port, physical_network, vlan_id):
|
||||
network_type, segmentation_id = constants.interpret_vlan_id(vlan_id)
|
||||
kwargs = {'port': port,
|
||||
'network_type': network_type,
|
||||
'physical_network': physical_network,
|
||||
'segmentation_id': segmentation_id}
|
||||
if cfg.CONF.AGENT.rpc_support_old_agents:
|
||||
kwargs['vlan_id'] = vlan_id
|
||||
msg = self.make_msg('port_update', **kwargs)
|
||||
self.fanout_cast(context, msg,
|
||||
topic=self.topic_port_update)
|
||||
|
||||
|
||||
class LinuxBridgePluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
external_net_db.External_net_db_mixin,
|
||||
extraroute_db.ExtraRoute_db_mixin,
|
||||
l3_gwmode_db.L3_NAT_db_mixin,
|
||||
sg_db_rpc.SecurityGroupServerRpcMixin,
|
||||
l3_agentschedulers_db.L3AgentSchedulerDbMixin,
|
||||
agentschedulers_db.DhcpAgentSchedulerDbMixin,
|
||||
portbindings_db.PortBindingMixin):
|
||||
"""Implement the Neutron abstractions using Linux bridging.
|
||||
|
||||
A new VLAN is created for each network. An agent is relied upon
|
||||
to perform the actual Linux bridge configuration on each host.
|
||||
|
||||
The provider extension is also supported. As discussed in
|
||||
https://bugs.launchpad.net/neutron/+bug/1023156, this class could
|
||||
be simplified, and filtering on extended attributes could be
|
||||
handled, by adding support for extended attributes to the
|
||||
NeutronDbPluginV2 base class. When that occurs, this class should
|
||||
be updated to take advantage of it.
|
||||
|
||||
The port binding extension enables an external application relay
|
||||
information to and from the plugin.
|
||||
"""
|
||||
|
||||
# This attribute specifies whether the plugin supports or not
|
||||
# bulk/pagination/sorting operations. Name mangling is used in
|
||||
# order to ensure it is qualified by class
|
||||
__native_bulk_support = True
|
||||
__native_pagination_support = True
|
||||
__native_sorting_support = True
|
||||
|
||||
_supported_extension_aliases = ["provider", "external-net", "router",
|
||||
"ext-gw-mode", "binding", "quotas",
|
||||
"security-group", "agent", "extraroute",
|
||||
"l3_agent_scheduler",
|
||||
"dhcp_agent_scheduler"]
|
||||
|
||||
@property
|
||||
def supported_extension_aliases(self):
|
||||
if not hasattr(self, '_aliases'):
|
||||
aliases = self._supported_extension_aliases[:]
|
||||
sg_rpc.disable_security_group_extension_by_config(aliases)
|
||||
self._aliases = aliases
|
||||
return self._aliases
|
||||
|
||||
def __init__(self):
|
||||
super(LinuxBridgePluginV2, self).__init__()
|
||||
self.base_binding_dict = {
|
||||
portbindings.VIF_TYPE: portbindings.VIF_TYPE_BRIDGE,
|
||||
portbindings.VIF_DETAILS: {
|
||||
# TODO(rkukura): Replace with new VIF security details
|
||||
portbindings.CAP_PORT_FILTER:
|
||||
'security-group' in self.supported_extension_aliases}}
|
||||
self._parse_network_vlan_ranges()
|
||||
db.sync_network_states(self.network_vlan_ranges)
|
||||
self.tenant_network_type = cfg.CONF.VLANS.tenant_network_type
|
||||
if self.tenant_network_type not in [svc_constants.TYPE_LOCAL,
|
||||
svc_constants.TYPE_VLAN,
|
||||
svc_constants.TYPE_NONE]:
|
||||
LOG.error(_("Invalid tenant_network_type: %s. "
|
||||
"Service terminated!"),
|
||||
self.tenant_network_type)
|
||||
sys.exit(1)
|
||||
self._setup_rpc()
|
||||
self.network_scheduler = importutils.import_object(
|
||||
cfg.CONF.network_scheduler_driver
|
||||
)
|
||||
self.router_scheduler = importutils.import_object(
|
||||
cfg.CONF.router_scheduler_driver
|
||||
)
|
||||
LOG.debug(_("Linux Bridge Plugin initialization complete"))
|
||||
|
||||
def _setup_rpc(self):
|
||||
# RPC support
|
||||
self.service_topics = {svc_constants.CORE: topics.PLUGIN,
|
||||
svc_constants.L3_ROUTER_NAT: topics.L3PLUGIN}
|
||||
self.conn = n_rpc.create_connection(new=True)
|
||||
self.endpoints = [LinuxBridgeRpcCallbacks(),
|
||||
securitygroups_rpc.SecurityGroupServerRpcCallback(),
|
||||
dhcp_rpc.DhcpRpcCallback(),
|
||||
l3_rpc.L3RpcCallback(),
|
||||
agents_db.AgentExtRpcCallback()]
|
||||
for svc_topic in self.service_topics.values():
|
||||
self.conn.create_consumer(svc_topic, self.endpoints, fanout=False)
|
||||
# Consume from all consumers in threads
|
||||
self.conn.consume_in_threads()
|
||||
self.notifier = AgentNotifierApi(topics.AGENT)
|
||||
self.agent_notifiers[q_const.AGENT_TYPE_DHCP] = (
|
||||
dhcp_rpc_agent_api.DhcpAgentNotifyAPI()
|
||||
)
|
||||
self.agent_notifiers[q_const.AGENT_TYPE_L3] = (
|
||||
l3_rpc_agent_api.L3AgentNotifyAPI()
|
||||
)
|
||||
|
||||
def _parse_network_vlan_ranges(self):
|
||||
try:
|
||||
self.network_vlan_ranges = plugin_utils.parse_network_vlan_ranges(
|
||||
cfg.CONF.VLANS.network_vlan_ranges)
|
||||
except Exception as ex:
|
||||
LOG.error(_("%s. Agent terminated!"), ex)
|
||||
sys.exit(1)
|
||||
LOG.info(_("Network VLAN ranges: %s"), self.network_vlan_ranges)
|
||||
|
||||
def _add_network_vlan_range(self, physical_network, vlan_min, vlan_max):
|
||||
self._add_network(physical_network)
|
||||
self.network_vlan_ranges[physical_network].append((vlan_min, vlan_max))
|
||||
|
||||
def _add_network(self, physical_network):
|
||||
if physical_network not in self.network_vlan_ranges:
|
||||
self.network_vlan_ranges[physical_network] = []
|
||||
|
||||
def _extend_network_dict_provider(self, context, network):
|
||||
binding = db.get_network_binding(context.session, network['id'])
|
||||
if binding.vlan_id == constants.FLAT_VLAN_ID:
|
||||
network[provider.NETWORK_TYPE] = svc_constants.TYPE_FLAT
|
||||
network[provider.PHYSICAL_NETWORK] = binding.physical_network
|
||||
network[provider.SEGMENTATION_ID] = None
|
||||
elif binding.vlan_id == constants.LOCAL_VLAN_ID:
|
||||
network[provider.NETWORK_TYPE] = svc_constants.TYPE_LOCAL
|
||||
network[provider.PHYSICAL_NETWORK] = None
|
||||
network[provider.SEGMENTATION_ID] = None
|
||||
else:
|
||||
network[provider.NETWORK_TYPE] = svc_constants.TYPE_VLAN
|
||||
network[provider.PHYSICAL_NETWORK] = binding.physical_network
|
||||
network[provider.SEGMENTATION_ID] = binding.vlan_id
|
||||
|
||||
def _process_provider_create(self, context, attrs):
|
||||
network_type = attrs.get(provider.NETWORK_TYPE)
|
||||
physical_network = attrs.get(provider.PHYSICAL_NETWORK)
|
||||
segmentation_id = attrs.get(provider.SEGMENTATION_ID)
|
||||
|
||||
network_type_set = attributes.is_attr_set(network_type)
|
||||
physical_network_set = attributes.is_attr_set(physical_network)
|
||||
segmentation_id_set = attributes.is_attr_set(segmentation_id)
|
||||
|
||||
if not (network_type_set or physical_network_set or
|
||||
segmentation_id_set):
|
||||
return (None, None, None)
|
||||
|
||||
if not network_type_set:
|
||||
msg = _("provider:network_type required")
|
||||
raise n_exc.InvalidInput(error_message=msg)
|
||||
elif network_type == svc_constants.TYPE_FLAT:
|
||||
if segmentation_id_set:
|
||||
msg = _("provider:segmentation_id specified for flat network")
|
||||
raise n_exc.InvalidInput(error_message=msg)
|
||||
else:
|
||||
segmentation_id = constants.FLAT_VLAN_ID
|
||||
elif network_type == svc_constants.TYPE_VLAN:
|
||||
if not segmentation_id_set:
|
||||
msg = _("provider:segmentation_id required")
|
||||
raise n_exc.InvalidInput(error_message=msg)
|
||||
if not utils.is_valid_vlan_tag(segmentation_id):
|
||||
msg = (_("provider:segmentation_id out of range "
|
||||
"(%(min_id)s through %(max_id)s)") %
|
||||
{'min_id': q_const.MIN_VLAN_TAG,
|
||||
'max_id': q_const.MAX_VLAN_TAG})
|
||||
raise n_exc.InvalidInput(error_message=msg)
|
||||
elif network_type == svc_constants.TYPE_LOCAL:
|
||||
if physical_network_set:
|
||||
msg = _("provider:physical_network specified for local "
|
||||
"network")
|
||||
raise n_exc.InvalidInput(error_message=msg)
|
||||
else:
|
||||
physical_network = None
|
||||
if segmentation_id_set:
|
||||
msg = _("provider:segmentation_id specified for local "
|
||||
"network")
|
||||
raise n_exc.InvalidInput(error_message=msg)
|
||||
else:
|
||||
segmentation_id = constants.LOCAL_VLAN_ID
|
||||
else:
|
||||
msg = _("provider:network_type %s not supported") % network_type
|
||||
raise n_exc.InvalidInput(error_message=msg)
|
||||
|
||||
if network_type in [svc_constants.TYPE_VLAN, svc_constants.TYPE_FLAT]:
|
||||
if physical_network_set:
|
||||
if physical_network not in self.network_vlan_ranges:
|
||||
msg = (_("Unknown provider:physical_network %s") %
|
||||
physical_network)
|
||||
raise n_exc.InvalidInput(error_message=msg)
|
||||
elif 'default' in self.network_vlan_ranges:
|
||||
physical_network = 'default'
|
||||
else:
|
||||
msg = _("provider:physical_network required")
|
||||
raise n_exc.InvalidInput(error_message=msg)
|
||||
|
||||
return (network_type, physical_network, segmentation_id)
|
||||
|
||||
def create_network(self, context, network):
|
||||
(network_type, physical_network,
|
||||
vlan_id) = self._process_provider_create(context,
|
||||
network['network'])
|
||||
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
#set up default security groups
|
||||
tenant_id = self._get_tenant_id_for_create(
|
||||
context, network['network'])
|
||||
self._ensure_default_security_group(context, tenant_id)
|
||||
|
||||
if not network_type:
|
||||
# tenant network
|
||||
network_type = self.tenant_network_type
|
||||
if network_type == svc_constants.TYPE_NONE:
|
||||
raise n_exc.TenantNetworksDisabled()
|
||||
elif network_type == svc_constants.TYPE_VLAN:
|
||||
physical_network, vlan_id = db.reserve_network(session)
|
||||
else: # TYPE_LOCAL
|
||||
vlan_id = constants.LOCAL_VLAN_ID
|
||||
else:
|
||||
# provider network
|
||||
if network_type in [svc_constants.TYPE_VLAN,
|
||||
svc_constants.TYPE_FLAT]:
|
||||
db.reserve_specific_network(session, physical_network,
|
||||
vlan_id)
|
||||
# no reservation needed for TYPE_LOCAL
|
||||
net = super(LinuxBridgePluginV2, self).create_network(context,
|
||||
network)
|
||||
db.add_network_binding(session, net['id'],
|
||||
physical_network, vlan_id)
|
||||
self._process_l3_create(context, net, network['network'])
|
||||
self._extend_network_dict_provider(context, net)
|
||||
# note - exception will rollback entire transaction
|
||||
return net
|
||||
|
||||
def update_network(self, context, id, network):
|
||||
provider._raise_if_updates_provider_attributes(network['network'])
|
||||
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
net = super(LinuxBridgePluginV2, self).update_network(context, id,
|
||||
network)
|
||||
self._process_l3_update(context, net, network['network'])
|
||||
self._extend_network_dict_provider(context, net)
|
||||
return net
|
||||
|
||||
def delete_network(self, context, id):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
binding = db.get_network_binding(session, id)
|
||||
self._process_l3_delete(context, id)
|
||||
super(LinuxBridgePluginV2, self).delete_network(context, id)
|
||||
if binding.vlan_id != constants.LOCAL_VLAN_ID:
|
||||
db.release_network(session, binding.physical_network,
|
||||
binding.vlan_id, self.network_vlan_ranges)
|
||||
# the network_binding record is deleted via cascade from
|
||||
# the network record, so explicit removal is not necessary
|
||||
self.notifier.network_delete(context, id)
|
||||
|
||||
def get_network(self, context, id, fields=None):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
net = super(LinuxBridgePluginV2, self).get_network(context,
|
||||
id, None)
|
||||
self._extend_network_dict_provider(context, net)
|
||||
return self._fields(net, fields)
|
||||
|
||||
def get_networks(self, context, filters=None, fields=None,
|
||||
sorts=None, limit=None, marker=None, page_reverse=False):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
nets = super(LinuxBridgePluginV2,
|
||||
self).get_networks(context, filters, None, sorts,
|
||||
limit, marker, page_reverse)
|
||||
for net in nets:
|
||||
self._extend_network_dict_provider(context, net)
|
||||
|
||||
return [self._fields(net, fields) for net in nets]
|
||||
|
||||
def create_port(self, context, port):
|
||||
session = context.session
|
||||
port_data = port['port']
|
||||
with session.begin(subtransactions=True):
|
||||
self._ensure_default_security_group_on_port(context, port)
|
||||
sgids = self._get_security_groups_on_port(context, port)
|
||||
# Set port status as 'DOWN'. This will be updated by agent
|
||||
port['port']['status'] = q_const.PORT_STATUS_DOWN
|
||||
|
||||
port = super(LinuxBridgePluginV2,
|
||||
self).create_port(context, port)
|
||||
self._process_portbindings_create_and_update(context,
|
||||
port_data,
|
||||
port)
|
||||
self._process_port_create_security_group(
|
||||
context, port, sgids)
|
||||
self.notify_security_groups_member_updated(context, port)
|
||||
return port
|
||||
|
||||
def update_port(self, context, id, port):
|
||||
original_port = self.get_port(context, id)
|
||||
session = context.session
|
||||
need_port_update_notify = False
|
||||
|
||||
with session.begin(subtransactions=True):
|
||||
updated_port = super(LinuxBridgePluginV2, self).update_port(
|
||||
context, id, port)
|
||||
self._process_portbindings_create_and_update(context,
|
||||
port['port'],
|
||||
updated_port)
|
||||
need_port_update_notify = self.update_security_group_on_port(
|
||||
context, id, port, original_port, updated_port)
|
||||
|
||||
need_port_update_notify |= self.is_security_group_member_updated(
|
||||
context, original_port, updated_port)
|
||||
|
||||
if original_port['admin_state_up'] != updated_port['admin_state_up']:
|
||||
need_port_update_notify = True
|
||||
|
||||
if need_port_update_notify:
|
||||
self._notify_port_updated(context, updated_port)
|
||||
return updated_port
|
||||
|
||||
def delete_port(self, context, id, l3_port_check=True):
|
||||
|
||||
# if needed, check to see if this is a port owned by
|
||||
# and l3-router. If so, we should prevent deletion.
|
||||
if l3_port_check:
|
||||
self.prevent_l3_port_deletion(context, id)
|
||||
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
router_ids = self.disassociate_floatingips(
|
||||
context, id, do_notify=False)
|
||||
port = self.get_port(context, id)
|
||||
self._delete_port_security_group_bindings(context, id)
|
||||
super(LinuxBridgePluginV2, self).delete_port(context, id)
|
||||
|
||||
# now that we've left db transaction, we are safe to notify
|
||||
self.notify_routers_updated(context, router_ids)
|
||||
self.notify_security_groups_member_updated(context, port)
|
||||
|
||||
def _notify_port_updated(self, context, port):
|
||||
binding = db.get_network_binding(context.session,
|
||||
port['network_id'])
|
||||
self.notifier.port_update(context, port,
|
||||
binding.physical_network,
|
||||
binding.vlan_id)
|
||||
|
||||
@classmethod
|
||||
def get_port_from_device(cls, device):
|
||||
port = db.get_port_from_device(device[len(q_const.TAP_DEVICE_PREFIX):])
|
||||
if port:
|
||||
port['device'] = device
|
||||
return port
|
@ -1,34 +0,0 @@
|
||||
# Copyright (c) 2013 OpenStack Foundation.
|
||||
#
|
||||
# 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.tests.unit.linuxbridge import test_linuxbridge_plugin
|
||||
from neutron.tests.unit.openvswitch import test_agent_scheduler
|
||||
|
||||
|
||||
class LbAgentSchedulerTestCase(
|
||||
test_agent_scheduler.OvsAgentSchedulerTestCase):
|
||||
plugin_str = test_linuxbridge_plugin.PLUGIN_NAME
|
||||
l3_plugin = None
|
||||
|
||||
|
||||
class LbL3AgentNotifierTestCase(
|
||||
test_agent_scheduler.OvsL3AgentNotifierTestCase):
|
||||
plugin_str = test_linuxbridge_plugin.PLUGIN_NAME
|
||||
l3_plugin = None
|
||||
|
||||
|
||||
class LbDhcpAgentNotifierTestCase(
|
||||
test_agent_scheduler.OvsDhcpAgentNotifierTestCase):
|
||||
plugin_str = test_linuxbridge_plugin.PLUGIN_NAME
|
@ -1,169 +0,0 @@
|
||||
# Copyright (c) 2012 OpenStack Foundation.
|
||||
#
|
||||
# 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
|
||||
from six import moves
|
||||
import testtools
|
||||
from testtools import matchers
|
||||
|
||||
from neutron.common import exceptions as n_exc
|
||||
from neutron.db import api as db
|
||||
from neutron.plugins.linuxbridge.db import l2network_db_v2 as lb_db
|
||||
from neutron.tests.unit import test_db_plugin as test_plugin
|
||||
from neutron.tests.unit import testlib_api
|
||||
|
||||
PHYS_NET = 'physnet1'
|
||||
PHYS_NET_2 = 'physnet2'
|
||||
VLAN_MIN = 10
|
||||
VLAN_MAX = 19
|
||||
VLAN_RANGES = {PHYS_NET: [(VLAN_MIN, VLAN_MAX)]}
|
||||
UPDATED_VLAN_RANGES = {PHYS_NET: [(VLAN_MIN + 5, VLAN_MAX + 5)],
|
||||
PHYS_NET_2: [(VLAN_MIN + 20, VLAN_MAX + 20)]}
|
||||
|
||||
PLUGIN_NAME = ('neutron.plugins.linuxbridge.'
|
||||
'lb_neutron_plugin.LinuxBridgePluginV2')
|
||||
|
||||
|
||||
class NetworkStatesTest(testlib_api.SqlTestCase):
|
||||
def setUp(self):
|
||||
super(NetworkStatesTest, self).setUp()
|
||||
lb_db.sync_network_states(VLAN_RANGES)
|
||||
self.session = db.get_session()
|
||||
|
||||
def test_sync_network_states(self):
|
||||
self.assertIsNone(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MIN - 1))
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MIN).allocated)
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MIN + 1).allocated)
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MAX - 1).allocated)
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MAX).allocated)
|
||||
self.assertIsNone(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MAX + 1))
|
||||
|
||||
lb_db.sync_network_states(UPDATED_VLAN_RANGES)
|
||||
|
||||
self.assertIsNone(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MIN + 5 - 1))
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MIN + 5).allocated)
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MIN + 5 + 1).allocated)
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MAX + 5 - 1).allocated)
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MAX + 5).allocated)
|
||||
self.assertIsNone(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MAX + 5 + 1))
|
||||
|
||||
self.assertIsNone(lb_db.get_network_state(PHYS_NET_2,
|
||||
VLAN_MIN + 20 - 1))
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET_2,
|
||||
VLAN_MIN + 20).allocated)
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET_2,
|
||||
VLAN_MIN + 20 + 1).allocated)
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET_2,
|
||||
VLAN_MAX + 20 - 1).allocated)
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET_2,
|
||||
VLAN_MAX + 20).allocated)
|
||||
self.assertIsNone(lb_db.get_network_state(PHYS_NET_2,
|
||||
VLAN_MAX + 20 + 1))
|
||||
|
||||
lb_db.sync_network_states(VLAN_RANGES)
|
||||
|
||||
self.assertIsNone(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MIN - 1))
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MIN).allocated)
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MIN + 1).allocated)
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MAX - 1).allocated)
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MAX).allocated)
|
||||
self.assertIsNone(lb_db.get_network_state(PHYS_NET,
|
||||
VLAN_MAX + 1))
|
||||
|
||||
self.assertIsNone(lb_db.get_network_state(PHYS_NET_2,
|
||||
VLAN_MIN + 20))
|
||||
self.assertIsNone(lb_db.get_network_state(PHYS_NET_2,
|
||||
VLAN_MAX + 20))
|
||||
|
||||
def test_network_pool(self):
|
||||
vlan_ids = set()
|
||||
for x in moves.xrange(VLAN_MIN, VLAN_MAX + 1):
|
||||
physical_network, vlan_id = lb_db.reserve_network(self.session)
|
||||
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)
|
||||
|
||||
with testtools.ExpectedException(n_exc.NoNetworkAvailable):
|
||||
physical_network, vlan_id = lb_db.reserve_network(self.session)
|
||||
|
||||
for vlan_id in vlan_ids:
|
||||
lb_db.release_network(self.session, PHYS_NET, vlan_id, VLAN_RANGES)
|
||||
|
||||
def test_specific_network_inside_pool(self):
|
||||
vlan_id = VLAN_MIN + 5
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
vlan_id).allocated)
|
||||
lb_db.reserve_specific_network(self.session, PHYS_NET, vlan_id)
|
||||
self.assertTrue(lb_db.get_network_state(PHYS_NET,
|
||||
vlan_id).allocated)
|
||||
|
||||
with testtools.ExpectedException(n_exc.VlanIdInUse):
|
||||
lb_db.reserve_specific_network(self.session, PHYS_NET, vlan_id)
|
||||
|
||||
lb_db.release_network(self.session, PHYS_NET, vlan_id, VLAN_RANGES)
|
||||
self.assertFalse(lb_db.get_network_state(PHYS_NET,
|
||||
vlan_id).allocated)
|
||||
|
||||
def test_specific_network_outside_pool(self):
|
||||
vlan_id = VLAN_MAX + 5
|
||||
self.assertIsNone(lb_db.get_network_state(PHYS_NET, vlan_id))
|
||||
lb_db.reserve_specific_network(self.session, PHYS_NET, vlan_id)
|
||||
self.assertTrue(lb_db.get_network_state(PHYS_NET,
|
||||
vlan_id).allocated)
|
||||
|
||||
with testtools.ExpectedException(n_exc.VlanIdInUse):
|
||||
lb_db.reserve_specific_network(self.session, PHYS_NET, vlan_id)
|
||||
|
||||
lb_db.release_network(self.session, PHYS_NET, vlan_id, VLAN_RANGES)
|
||||
self.assertIsNone(lb_db.get_network_state(PHYS_NET, vlan_id))
|
||||
|
||||
|
||||
class NetworkBindingsTest(test_plugin.NeutronDbPluginV2TestCase):
|
||||
def setUp(self):
|
||||
cfg.CONF.set_override('network_vlan_ranges', ['physnet1:1000:2999'],
|
||||
group='VLANS')
|
||||
super(NetworkBindingsTest, self).setUp(plugin=PLUGIN_NAME)
|
||||
self.session = db.get_session()
|
||||
|
||||
def test_add_network_binding(self):
|
||||
params = {'provider:network_type': 'vlan',
|
||||
'provider:physical_network': PHYS_NET,
|
||||
'provider:segmentation_id': 1234}
|
||||
params['arg_list'] = tuple(params.keys())
|
||||
with self.network(**params) as network:
|
||||
TEST_NETWORK_ID = network['network']['id']
|
||||
binding = lb_db.get_network_binding(self.session, TEST_NETWORK_ID)
|
||||
self.assertIsNotNone(binding)
|
||||
self.assertEqual(binding.network_id, TEST_NETWORK_ID)
|
||||
self.assertEqual(binding.physical_network, PHYS_NET)
|
||||
self.assertEqual(binding.vlan_id, 1234)
|
@ -1,97 +0,0 @@
|
||||
# Copyright 2012, Nachi Ueno, NTT MCL, 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 mock
|
||||
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.extensions import securitygroup as ext_sg
|
||||
from neutron.plugins.linuxbridge.db import l2network_db_v2 as lb_db
|
||||
from neutron.tests.unit import test_extension_security_group as test_sg
|
||||
from neutron.tests.unit import test_security_groups_rpc as test_sg_rpc
|
||||
|
||||
|
||||
PLUGIN_NAME = ('neutron.plugins.linuxbridge.'
|
||||
'lb_neutron_plugin.LinuxBridgePluginV2')
|
||||
NOTIFIER = ('neutron.plugins.linuxbridge.'
|
||||
'lb_neutron_plugin.AgentNotifierApi')
|
||||
|
||||
|
||||
class LinuxBridgeSecurityGroupsTestCase(test_sg.SecurityGroupDBTestCase):
|
||||
_plugin_name = PLUGIN_NAME
|
||||
|
||||
def setUp(self, plugin=None):
|
||||
test_sg_rpc.set_firewall_driver(test_sg_rpc.FIREWALL_IPTABLES_DRIVER)
|
||||
notifier_p = mock.patch(NOTIFIER)
|
||||
notifier_cls = notifier_p.start()
|
||||
self.notifier = mock.Mock()
|
||||
notifier_cls.return_value = self.notifier
|
||||
self._attribute_map_bk_ = {}
|
||||
for item in attributes.RESOURCE_ATTRIBUTE_MAP:
|
||||
self._attribute_map_bk_[item] = (attributes.
|
||||
RESOURCE_ATTRIBUTE_MAP[item].
|
||||
copy())
|
||||
super(LinuxBridgeSecurityGroupsTestCase, self).setUp(PLUGIN_NAME)
|
||||
|
||||
def tearDown(self):
|
||||
attributes.RESOURCE_ATTRIBUTE_MAP = self._attribute_map_bk_
|
||||
super(LinuxBridgeSecurityGroupsTestCase, self).tearDown()
|
||||
|
||||
|
||||
class TestLinuxBridgeSecurityGroups(LinuxBridgeSecurityGroupsTestCase,
|
||||
test_sg.TestSecurityGroups,
|
||||
test_sg_rpc.SGNotificationTestMixin):
|
||||
pass
|
||||
|
||||
|
||||
class TestLinuxBridgeSecurityGroupsXML(TestLinuxBridgeSecurityGroups):
|
||||
fmt = 'xml'
|
||||
|
||||
|
||||
class TestLinuxBridgeSecurityGroupsDB(LinuxBridgeSecurityGroupsTestCase):
|
||||
def test_security_group_get_port_from_device(self):
|
||||
with self.network() as n:
|
||||
with self.subnet(n):
|
||||
with self.security_group() as sg:
|
||||
security_group_id = sg['security_group']['id']
|
||||
res = self._create_port(self.fmt, n['network']['id'])
|
||||
port = self.deserialize(self.fmt, res)
|
||||
fixed_ips = port['port']['fixed_ips']
|
||||
data = {'port': {'fixed_ips': fixed_ips,
|
||||
'name': port['port']['name'],
|
||||
ext_sg.SECURITYGROUPS:
|
||||
[security_group_id]}}
|
||||
|
||||
req = self.new_update_request('ports', data,
|
||||
port['port']['id'])
|
||||
res = self.deserialize(self.fmt,
|
||||
req.get_response(self.api))
|
||||
port_id = res['port']['id']
|
||||
device_id = port_id[:8]
|
||||
port_dict = lb_db.get_port_from_device(device_id)
|
||||
self.assertEqual(port_id, port_dict['id'])
|
||||
self.assertEqual([security_group_id],
|
||||
port_dict[ext_sg.SECURITYGROUPS])
|
||||
self.assertEqual([], port_dict['security_group_rules'])
|
||||
self.assertEqual([fixed_ips[0]['ip_address']],
|
||||
port_dict['fixed_ips'])
|
||||
self._delete('ports', port['port']['id'])
|
||||
|
||||
def test_security_group_get_port_from_device_with_no_port(self):
|
||||
port_dict = lb_db.get_port_from_device('bad_device_id')
|
||||
self.assertIsNone(port_dict)
|
||||
|
||||
|
||||
class TestLinuxBridgeSecurityGroupsDBXML(TestLinuxBridgeSecurityGroupsDB):
|
||||
fmt = 'xml'
|
@ -1,127 +0,0 @@
|
||||
# Copyright (c) 2012 OpenStack Foundation.
|
||||
#
|
||||
# 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 mock
|
||||
from oslo.config import cfg
|
||||
|
||||
from neutron.common import constants as q_const
|
||||
from neutron.extensions import portbindings
|
||||
from neutron import manager
|
||||
from neutron.plugins.linuxbridge import lb_neutron_plugin
|
||||
from neutron.tests.unit import _test_extension_portbindings as test_bindings
|
||||
from neutron.tests.unit import test_db_plugin as test_plugin
|
||||
from neutron.tests.unit import test_security_groups_rpc as test_sg_rpc
|
||||
|
||||
PLUGIN_NAME = ('neutron.plugins.linuxbridge.'
|
||||
'lb_neutron_plugin.LinuxBridgePluginV2')
|
||||
|
||||
|
||||
class LinuxBridgePluginV2TestCase(test_plugin.NeutronDbPluginV2TestCase):
|
||||
_plugin_name = PLUGIN_NAME
|
||||
|
||||
def setUp(self):
|
||||
super(LinuxBridgePluginV2TestCase, self).setUp(PLUGIN_NAME)
|
||||
self.port_create_status = 'DOWN'
|
||||
|
||||
|
||||
class TestLinuxBridgeBasicGet(test_plugin.TestBasicGet,
|
||||
LinuxBridgePluginV2TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class TestLinuxBridgeV2HTTPResponse(test_plugin.TestV2HTTPResponse,
|
||||
LinuxBridgePluginV2TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class TestLinuxBridgeNetworksV2(test_plugin.TestNetworksV2,
|
||||
LinuxBridgePluginV2TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class TestLinuxBridgePortsV2(test_plugin.TestPortsV2,
|
||||
LinuxBridgePluginV2TestCase):
|
||||
|
||||
def test_update_port_status_build(self):
|
||||
with self.port() as port:
|
||||
self.assertEqual(port['port']['status'], 'DOWN')
|
||||
self.assertEqual(self.port_create_status, 'DOWN')
|
||||
|
||||
|
||||
class TestLinuxBridgePortBinding(LinuxBridgePluginV2TestCase,
|
||||
test_bindings.PortBindingsTestCase):
|
||||
VIF_TYPE = portbindings.VIF_TYPE_BRIDGE
|
||||
HAS_PORT_FILTER = True
|
||||
ENABLE_SG = True
|
||||
FIREWALL_DRIVER = test_sg_rpc.FIREWALL_IPTABLES_DRIVER
|
||||
|
||||
def setUp(self):
|
||||
test_sg_rpc.set_firewall_driver(self.FIREWALL_DRIVER)
|
||||
cfg.CONF.set_override(
|
||||
'enable_security_group', self.ENABLE_SG,
|
||||
group='SECURITYGROUP')
|
||||
super(TestLinuxBridgePortBinding, self).setUp()
|
||||
|
||||
|
||||
class TestLinuxBridgePortBindingNoSG(TestLinuxBridgePortBinding):
|
||||
HAS_PORT_FILTER = False
|
||||
ENABLE_SG = False
|
||||
FIREWALL_DRIVER = test_sg_rpc.FIREWALL_NOOP_DRIVER
|
||||
|
||||
|
||||
class TestLinuxBridgePortBindingHost(
|
||||
LinuxBridgePluginV2TestCase,
|
||||
test_bindings.PortBindingsHostTestCaseMixin):
|
||||
pass
|
||||
|
||||
|
||||
class TestLinuxBridgePluginRpcCallbacks(test_plugin.NeutronDbPluginV2TestCase):
|
||||
def setUp(self):
|
||||
super(TestLinuxBridgePluginRpcCallbacks, self).setUp(PLUGIN_NAME)
|
||||
self.callbacks = lb_neutron_plugin.LinuxBridgeRpcCallbacks()
|
||||
|
||||
def test_update_device_down(self):
|
||||
with mock.patch.object(manager.NeutronManager, "get_plugin") as gp:
|
||||
plugin = gp.return_value
|
||||
plugin.get_port_from_device.return_value = None
|
||||
self.assertEqual(
|
||||
self.callbacks.update_device_down("fake_context",
|
||||
agent_id="123",
|
||||
device="device",
|
||||
host="host"),
|
||||
{'device': 'device', 'exists': False}
|
||||
)
|
||||
plugin.get_port_from_device.return_value = {
|
||||
'id': 'fakeid',
|
||||
'status': q_const.PORT_STATUS_ACTIVE}
|
||||
self.assertEqual(
|
||||
self.callbacks.update_device_down("fake_context",
|
||||
agent_id="123",
|
||||
device="device",
|
||||
host="host"),
|
||||
{'device': 'device', 'exists': True}
|
||||
)
|
||||
|
||||
def test_update_device_up(self):
|
||||
with mock.patch.object(manager.NeutronManager, "get_plugin") as gp:
|
||||
plugin = gp.return_value
|
||||
plugin.get_port_from_device.return_value = {
|
||||
'id': 'fakeid',
|
||||
'status': q_const.PORT_STATUS_ACTIVE}
|
||||
self.callbacks.update_device_up("fake_context",
|
||||
agent_id="123",
|
||||
device="device",
|
||||
host="host")
|
||||
plugin.get_port_from_device.assert_called_once_with('device')
|
@ -1,143 +0,0 @@
|
||||
# Copyright 2012, Red Hat, 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.
|
||||
|
||||
"""
|
||||
Unit Tests for linuxbridge rpc
|
||||
"""
|
||||
|
||||
import fixtures
|
||||
from oslo.config import cfg
|
||||
|
||||
from neutron.agent import rpc as agent_rpc
|
||||
from neutron.common import topics
|
||||
from neutron.openstack.common import context
|
||||
from neutron.plugins.linuxbridge import lb_neutron_plugin as plb
|
||||
from neutron.tests import base
|
||||
|
||||
|
||||
class rpcApiTestCase(base.BaseTestCase):
|
||||
def _test_lb_api(self, rpcapi, topic, method, rpc_method,
|
||||
expected_msg=None, **kwargs):
|
||||
ctxt = context.RequestContext('fake_user', 'fake_project')
|
||||
expected_retval = 'foo' if method == 'call' else None
|
||||
expected_kwargs = {}
|
||||
if topic:
|
||||
expected_kwargs['topic'] = topic
|
||||
if 'version' in kwargs:
|
||||
expected_kwargs['version'] = kwargs.pop('version')
|
||||
if not expected_msg:
|
||||
expected_msg = rpcapi.make_msg(method, **kwargs)
|
||||
if rpc_method == 'cast' and method == 'run_instance':
|
||||
kwargs['call'] = False
|
||||
|
||||
self.fake_args = None
|
||||
self.fake_kwargs = None
|
||||
|
||||
def _fake_rpc_method(*args, **kwargs):
|
||||
self.fake_args = args
|
||||
self.fake_kwargs = kwargs
|
||||
if expected_retval:
|
||||
return expected_retval
|
||||
|
||||
self.useFixture(fixtures.MonkeyPatch(
|
||||
'neutron.common.rpc.RpcProxy.' + rpc_method,
|
||||
_fake_rpc_method))
|
||||
|
||||
retval = getattr(rpcapi, method)(ctxt, **kwargs)
|
||||
|
||||
self.assertEqual(expected_retval, retval)
|
||||
expected_args = [ctxt, expected_msg]
|
||||
|
||||
# skip the first argument which is 'self'
|
||||
for arg, expected_arg in zip(self.fake_args[1:], expected_args):
|
||||
self.assertEqual(expected_arg, arg)
|
||||
self.assertEqual(expected_kwargs, self.fake_kwargs)
|
||||
|
||||
def test_delete_network(self):
|
||||
rpcapi = plb.AgentNotifierApi(topics.AGENT)
|
||||
self._test_lb_api(rpcapi,
|
||||
topics.get_topic_name(topics.AGENT,
|
||||
topics.NETWORK,
|
||||
topics.DELETE),
|
||||
'network_delete', rpc_method='fanout_cast',
|
||||
network_id='fake_request_spec')
|
||||
|
||||
def test_port_update(self):
|
||||
cfg.CONF.set_override('rpc_support_old_agents', False, 'AGENT')
|
||||
rpcapi = plb.AgentNotifierApi(topics.AGENT)
|
||||
expected_msg = rpcapi.make_msg('port_update',
|
||||
port='fake_port',
|
||||
network_type='vlan',
|
||||
physical_network='fake_net',
|
||||
segmentation_id='fake_vlan_id')
|
||||
self._test_lb_api(rpcapi,
|
||||
topics.get_topic_name(topics.AGENT,
|
||||
topics.PORT,
|
||||
topics.UPDATE),
|
||||
'port_update', rpc_method='fanout_cast',
|
||||
expected_msg=expected_msg,
|
||||
port='fake_port',
|
||||
physical_network='fake_net',
|
||||
vlan_id='fake_vlan_id')
|
||||
|
||||
def test_port_update_old_agent(self):
|
||||
cfg.CONF.set_override('rpc_support_old_agents', True, 'AGENT')
|
||||
rpcapi = plb.AgentNotifierApi(topics.AGENT)
|
||||
expected_msg = rpcapi.make_msg('port_update',
|
||||
port='fake_port',
|
||||
network_type='vlan',
|
||||
physical_network='fake_net',
|
||||
segmentation_id='fake_vlan_id',
|
||||
vlan_id='fake_vlan_id')
|
||||
self._test_lb_api(rpcapi,
|
||||
topics.get_topic_name(topics.AGENT,
|
||||
topics.PORT,
|
||||
topics.UPDATE),
|
||||
'port_update', rpc_method='fanout_cast',
|
||||
expected_msg=expected_msg,
|
||||
port='fake_port',
|
||||
physical_network='fake_net',
|
||||
vlan_id='fake_vlan_id')
|
||||
|
||||
def test_device_details(self):
|
||||
rpcapi = agent_rpc.PluginApi(topics.PLUGIN)
|
||||
self._test_lb_api(rpcapi, None,
|
||||
'get_device_details', rpc_method='call',
|
||||
device='fake_device',
|
||||
agent_id='fake_agent_id',
|
||||
host='fake_host')
|
||||
|
||||
def test_devices_details_list(self):
|
||||
rpcapi = agent_rpc.PluginApi(topics.PLUGIN)
|
||||
self._test_lb_api(rpcapi, None,
|
||||
'get_devices_details_list', rpc_method='call',
|
||||
devices=['fake_device1', 'fake_device2'],
|
||||
agent_id='fake_agent_id', host='fake_host',
|
||||
version='1.3')
|
||||
|
||||
def test_update_device_down(self):
|
||||
rpcapi = agent_rpc.PluginApi(topics.PLUGIN)
|
||||
self._test_lb_api(rpcapi, None,
|
||||
'update_device_down', rpc_method='call',
|
||||
device='fake_device',
|
||||
agent_id='fake_agent_id',
|
||||
host='fake_host')
|
||||
|
||||
def test_update_device_up(self):
|
||||
rpcapi = agent_rpc.PluginApi(topics.PLUGIN)
|
||||
self._test_lb_api(rpcapi, None,
|
||||
'update_device_up', rpc_method='call',
|
||||
device='fake_device',
|
||||
agent_id='fake_agent_id',
|
||||
host='fake_host')
|
@ -32,8 +32,7 @@ from neutron.tests.unit import test_api_v2
|
||||
from neutron.tests.unit import testlib_api
|
||||
from neutron.tests.unit import testlib_plugin
|
||||
|
||||
TARGET_PLUGIN = ('neutron.plugins.linuxbridge.lb_neutron_plugin'
|
||||
'.LinuxBridgePluginV2')
|
||||
TARGET_PLUGIN = 'neutron.plugins.ml2.plugin.Ml2Plugin'
|
||||
|
||||
_get_path = test_api_v2._get_path
|
||||
|
||||
|
@ -134,7 +134,6 @@ neutron.core_plugins =
|
||||
embrane = neutron.plugins.embrane.plugins.embrane_ml2_plugin:EmbraneMl2Plugin
|
||||
hyperv = neutron.plugins.hyperv.hyperv_neutron_plugin:HyperVNeutronPlugin
|
||||
ibm = neutron.plugins.ibm.sdnve_neutron_plugin:SdnvePluginV2
|
||||
linuxbridge = neutron.plugins.linuxbridge.lb_neutron_plugin:LinuxBridgePluginV2
|
||||
midonet = neutron.plugins.midonet.plugin:MidonetPluginV2
|
||||
ml2 = neutron.plugins.ml2.plugin:Ml2Plugin
|
||||
mlnx = neutron.plugins.mlnx.mlnx_plugin:MellanoxEswitchPlugin
|
||||
|
Loading…
Reference in New Issue
Block a user