+++ /dev/null
-[hyperv]
-# (StrOpt) Type of network to allocate for tenant networks. The
-# default value 'local' is useful only for single-box testing and
-# provides no connectivity between hosts. You MUST either change this
-# to 'vlan' and configure network_vlan_ranges below or to 'flat'.
-# Set to 'none' to disable creation of tenant networks.
-#
-# tenant_network_type = local
-# Example: tenant_network_type = vlan
-
-# (ListOpt) Comma-separated list of
-# <physical_network>[:<vlan_min>:<vlan_max>] tuples enumerating ranges
-# of VLAN IDs on named physical networks that are available for
-# allocation. All physical networks listed are available for flat and
-# VLAN provider network creation. Specified ranges of VLAN IDs are
-# available for tenant network allocation if tenant_network_type is
-# 'vlan'. If empty, only gre and local networks may be created.
-#
-# network_vlan_ranges =
-# Example: network_vlan_ranges = physnet1:1000:2999
-
-[agent]
-# Agent's polling interval in seconds
-# polling_interval = 2
-
-# (ListOpt) Comma separated list of <physical_network>:<vswitch>
-# where the physical networks can be expressed with wildcards,
-# e.g.: ."*:external".
-# The referred external virtual switches need to be already present on
-# the Hyper-V server.
-# If a given physical network name will not match any value in the list
-# the plugin will look for a virtual switch with the same name.
-#
-# physical_network_vswitch_mappings = *:external
-# Example: physical_network_vswitch_mappings = net1:external1,net2:external2
-
-# (StrOpt) Private virtual switch name used for local networking.
-#
-# local_network_vswitch = private
-# Example: local_network_vswitch = custom_vswitch
-
-# (BoolOpt) Enables metrics collections for switch ports by using Hyper-V's
-# metric APIs. Collected data can by retrieved by other apps and services,
-# e.g.: Ceilometer. Requires Hyper-V / Windows Server 2012 and above.
-#
-# enable_metrics_collection = False
-
-#-----------------------------------------------------------------------------
-# Sample Configurations.
-#-----------------------------------------------------------------------------
-#
-# Neutron server:
-#
-# [HYPERV]
-# tenant_network_type = vlan
-# network_vlan_ranges = default:2000:3999
-#
-# Agent running on Hyper-V node:
-#
-# [AGENT]
-# polling_interval = 2
-# physical_network_vswitch_mappings = *:external
-# local_network_vswitch = private
--- /dev/null
+# Copyright 2015 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.
+#
+
+"""Remove Hyper-V Neutron Plugin
+
+Migrates the contents of the tables 'hyperv_vlan_allocations' and
+'hyperv_network_bindings' to 'ml2_vlan_allocations' and 'ml2_network_segments'
+respectively, and then removes the tables.
+
+Thse tables are used by HyperVNeutronPlugin, which will be removed.
+
+Revision ID: 2b801560a332
+Revises: 4119216b7365
+Create Date: 2015-02-12 09:23:40.346104
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '2b801560a332'
+down_revision = '2d2a8a565438'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.sql import expression as sa_expr
+
+from neutron.extensions import portbindings
+from neutron.openstack.common import uuidutils
+from neutron.plugins.common import constants as p_const
+
+FLAT_VLAN_ID = -1
+LOCAL_VLAN_ID = -2
+HYPERV = 'hyperv'
+
+
+# Duplicated from neutron.plugins.linuxbridge.common.constants to
+# avoid being dependent on it, as it will eventually be removed.
+def _interpret_vlan_id(vlan_id):
+ """Return (network_type, segmentation_id) tuple for encoded vlan_id."""
+ if vlan_id == LOCAL_VLAN_ID:
+ return (p_const.TYPE_LOCAL, None)
+ elif vlan_id == FLAT_VLAN_ID:
+ return (p_const.TYPE_FLAT, None)
+ else:
+ return (p_const.TYPE_VLAN, vlan_id)
+
+
+def _migrate_segment_dict(binding):
+ binding['id'] = uuidutils.generate_uuid()
+ vlan_id = binding.pop('segmentation_id')
+ network_type, segmentation_id = _interpret_vlan_id(vlan_id)
+ binding['network_type'] = network_type
+ binding['segmentation_id'] = segmentation_id
+
+
+def _migrate_vlan_allocations():
+ # Code similar to migrate_to_ml2.BaseMigrateToMl2.migrate_vlan_allocations
+ op.execute('INSERT INTO ml2_vlan_allocations '
+ 'SELECT physical_network, vlan_id, allocated '
+ 'FROM hyperv_vlan_allocations '
+ 'WHERE allocated = TRUE')
+
+
+def _migrate_network_segments(engine):
+ # Code similar to migrate_to_ml2.BaseMigrateToMl2.migrate_network_segments
+ source_table = sa_expr.table('hyperv_network_bindings')
+ source_segments = engine.execute(
+ sa_expr.select(['*'], from_obj=source_table))
+ ml2_segments = [dict(x) for x in source_segments]
+ for segment in ml2_segments:
+ _migrate_segment_dict(segment)
+
+ if ml2_segments:
+ ml2_network_segments = sa_expr.table('ml2_network_segments')
+ op.execute(ml2_network_segments.insert(), ml2_segments)
+
+
+def _get_port_segment_map(engine):
+ # Code from migrate_to_ml2.BaseMigrateToMl2.get_port_segment_map
+ port_segments = engine.execute("""
+ SELECT ports_network.port_id, ml2_network_segments.id AS segment_id
+ FROM ml2_network_segments, (
+ SELECT portbindingports.port_id, ports.network_id
+ FROM portbindingports, ports
+ WHERE portbindingports.port_id = ports.id
+ ) AS ports_network
+ WHERE ml2_network_segments.network_id = ports_network.network_id
+ """)
+ return dict(x for x in port_segments)
+
+
+def _migrate_port_bindings(engine):
+ # Code similar to migrate_to_ml2.BaseMigrateToMl2.migrate_port_bindings
+ port_segment_map = _get_port_segment_map(engine)
+ port_binding_ports = sa_expr.table('portbindingports')
+ source_bindings = engine.execute(
+ sa_expr.select(['*'], from_obj=port_binding_ports))
+ ml2_bindings = [dict(x) for x in source_bindings]
+ for binding in ml2_bindings:
+ binding['vif_type'] = portbindings.VIF_TYPE_HYPERV
+ binding['driver'] = HYPERV
+ segment = port_segment_map.get(binding['port_id'])
+ if segment:
+ binding['segment'] = segment
+ if ml2_bindings:
+ ml2_port_bindings = sa_expr.table('ml2_port_bindings')
+ op.execute(ml2_port_bindings.insert(), ml2_bindings)
+
+
+def upgrade():
+ bind = op.get_bind()
+
+ _migrate_vlan_allocations()
+ _migrate_network_segments(bind)
+ _migrate_port_bindings(bind)
+
+ op.drop_table('hyperv_vlan_allocations')
+ op.drop_table('hyperv_network_bindings')
+
+
+def downgrade():
+ op.create_table(
+ 'hyperv_vlan_allocations',
+ sa.Column('physical_network', sa.String(length=64), nullable=False),
+ sa.Column('vlan_id', sa.Integer(), autoincrement=False,
+ nullable=False),
+ sa.Column('allocated', sa.Boolean(), nullable=False),
+ sa.PrimaryKeyConstraint('physical_network', 'vlan_id'))
+
+ op.create_table(
+ 'hyperv_network_bindings',
+ sa.Column('network_id', sa.String(length=36), nullable=False),
+ sa.Column('network_type', sa.String(length=32), nullable=False),
+ sa.Column('physical_network', sa.String(length=64), nullable=True),
+ sa.Column('segmentation_id', sa.Integer(), nullable=True),
+ sa.ForeignKeyConstraint(['network_id'], ['networks.id'],
+ ondelete='CASCADE'),
+ sa.PrimaryKeyConstraint('network_id'))
-2d2a8a565438
+2b801560a332
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.hyperv import model # noqa
from neutron.plugins.linuxbridge.db import l2network_models_v2 # noqa
from neutron.plugins.metaplugin import meta_models_v2 # noqa
from neutron.plugins.ml2.drivers.arista import db # noqa
+++ /dev/null
-# Copyright 2013 Cloudbase Solutions SRL
-# 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 oslo_messaging
-
-from neutron.common import rpc as n_rpc
-from neutron.common import topics
-from neutron.plugins.hyperv.common import constants
-
-
-class AgentNotifierApi(object):
- '''Agent side of the openvswitch rpc API.
-
- API version history:
- 1.0 - Initial version.
-
- '''
-
- def __init__(self, topic):
- 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)
- self.topic_port_delete = topics.get_topic_name(topic,
- topics.PORT,
- topics.DELETE)
- self.topic_tunnel_update = topics.get_topic_name(topic,
- constants.TUNNEL,
- topics.UPDATE)
- target = oslo_messaging.Target(topic=topic, version='1.0')
- self.client = n_rpc.get_client(target)
-
- def network_delete(self, context, network_id):
- cctxt = self.client.prepare(topic=self.topic_network_delete,
- fanout=True)
- cctxt.cast(context, 'network_delete', network_id=network_id)
-
- def port_update(self, context, port, network_type, segmentation_id,
- physical_network):
- cctxt = self.client.prepare(topic=self.topic_port_update,
- fanout=True)
- cctxt.cast(context, 'port_update', port=port,
- network_type=network_type, segmentation_id=segmentation_id,
- physical_network=physical_network)
-
- def port_delete(self, context, port_id):
- cctxt = self.client.prepare(topic=self.topic_port_delete,
- fanout=True)
- cctxt.cast(context, 'port_delete', port_id=port_id)
-
- def tunnel_update(self, context, tunnel_ip, tunnel_id):
- cctxt = self.client.prepare(topic=self.topic_tunnel_update,
- fanout=True)
- cctxt.cast(context, 'tunnel_update', tunnel_ip=tunnel_ip,
- tunnel_id=tunnel_id)
+++ /dev/null
-# Copyright 2013 Cloudbase Solutions SRL
-# 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 six import moves
-from sqlalchemy.orm import exc
-
-from neutron.common import exceptions as n_exc
-import neutron.db.api as db_api
-from neutron.db import models_v2
-from neutron.i18n import _LW
-from neutron.openstack.common import log as logging
-from neutron.plugins.hyperv.common import constants
-from neutron.plugins.hyperv import model as hyperv_model
-
-LOG = logging.getLogger(__name__)
-
-
-class HyperVPluginDB(object):
-
- def reserve_vlan(self, session):
- with session.begin(subtransactions=True):
- alloc_q = session.query(hyperv_model.VlanAllocation)
- alloc_q = alloc_q.filter_by(allocated=False)
- alloc = alloc_q.first()
- if alloc:
- LOG.debug("Reserving vlan %(vlan_id)s on physical network "
- "%(physical_network)s from pool",
- {'vlan_id': alloc.vlan_id,
- 'physical_network': alloc.physical_network})
- alloc.allocated = True
- return (alloc.physical_network, alloc.vlan_id)
- raise n_exc.NoNetworkAvailable()
-
- def reserve_flat_net(self, session):
- with session.begin(subtransactions=True):
- alloc_q = session.query(hyperv_model.VlanAllocation)
- alloc_q = alloc_q.filter_by(allocated=False,
- vlan_id=constants.FLAT_VLAN_ID)
- alloc = alloc_q.first()
- if alloc:
- LOG.debug("Reserving flat physical network "
- "%(physical_network)s from pool",
- {'physical_network': alloc.physical_network})
- alloc.allocated = True
- return alloc.physical_network
- raise n_exc.NoNetworkAvailable()
-
- def reserve_specific_vlan(self, session, physical_network, vlan_id):
- with session.begin(subtransactions=True):
- try:
- alloc_q = session.query(hyperv_model.VlanAllocation)
- alloc_q = alloc_q.filter_by(
- physical_network=physical_network,
- vlan_id=vlan_id)
- alloc = alloc_q.one()
- if alloc.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})
- alloc.allocated = True
- except exc.NoResultFound:
- raise n_exc.NoNetworkAvailable()
-
- def reserve_specific_flat_net(self, session, physical_network):
- return self.reserve_specific_vlan(session, physical_network,
- constants.FLAT_VLAN_ID)
-
- def add_network_binding(self, session, network_id, network_type,
- physical_network, segmentation_id):
- with session.begin(subtransactions=True):
- binding = hyperv_model.NetworkBinding(
- network_id, network_type,
- physical_network,
- segmentation_id)
- session.add(binding)
-
- def get_port(self, port_id):
- session = db_api.get_session()
- try:
- port = session.query(models_v2.Port).filter_by(id=port_id).one()
- except exc.NoResultFound:
- port = None
- return port
-
- def get_network_binding(self, session, network_id):
- session = session or db_api.get_session()
- try:
- binding_q = session.query(hyperv_model.NetworkBinding)
- binding_q = binding_q.filter_by(network_id=network_id)
- return binding_q.one()
- except exc.NoResultFound:
- return
-
- def set_port_status(self, port_id, status):
- session = db_api.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)
-
- def release_vlan(self, session, physical_network, vlan_id):
- with session.begin(subtransactions=True):
- try:
- alloc_q = session.query(hyperv_model.VlanAllocation)
- alloc_q = alloc_q.filter_by(physical_network=physical_network,
- vlan_id=vlan_id)
- alloc = alloc_q.one()
- alloc.allocated = False
- #session.delete(alloc)
- LOG.debug("Releasing vlan %(vlan_id)s on physical network "
- "%(physical_network)s",
- {'vlan_id': vlan_id,
- 'physical_network': physical_network})
- except exc.NoResultFound:
- LOG.warning(_LW("vlan_id %(vlan_id)s on physical network "
- "%(physical_network)s not found"),
- {'vlan_id': vlan_id,
- 'physical_network': physical_network})
-
- def _add_missing_allocatable_vlans(self, session, vlan_ids,
- physical_network):
- for vlan_id in sorted(vlan_ids):
- alloc = hyperv_model.VlanAllocation(
- physical_network, vlan_id)
- session.add(alloc)
-
- def _remove_non_allocatable_vlans(self, session,
- physical_network,
- vlan_ids,
- allocations):
- if physical_network in allocations:
- for alloc in allocations[physical_network]:
- try:
- # see if vlan is allocatable
- vlan_ids.remove(alloc.vlan_id)
- except KeyError:
- # it's not allocatable, so check if its allocated
- if not alloc.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': alloc.vlan_id,
- 'physical_network': physical_network})
- session.delete(alloc)
- del allocations[physical_network]
-
- def _remove_unconfigured_vlans(self, session, allocations):
- for allocs in allocations.itervalues():
- for alloc in allocs:
- if not alloc.allocated:
- LOG.debug("Removing vlan %(vlan_id)s on physical "
- "network %(physical_network)s from pool",
- {'vlan_id': alloc.vlan_id,
- 'physical_network': alloc.physical_network})
- session.delete(alloc)
-
- def sync_vlan_allocations(self, network_vlan_ranges):
- """Synchronize vlan_allocations table with configured VLAN ranges."""
-
- session = db_api.get_session()
- with session.begin():
- # get existing allocations for all physical networks
- allocations = dict()
- allocs_q = session.query(hyperv_model.VlanAllocation)
- for alloc in allocs_q:
- allocations.setdefault(alloc.physical_network,
- set()).add(alloc)
-
- # process vlan ranges for each configured physical network
- for physical_network, vlan_ranges in network_vlan_ranges.items():
- # 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
- self._remove_non_allocatable_vlans(session,
- physical_network,
- vlan_ids,
- allocations)
-
- # add missing allocatable vlans to table
- self._add_missing_allocatable_vlans(session, vlan_ids,
- physical_network)
-
- # remove from table unallocated vlans for any unconfigured physical
- # networks
- self._remove_unconfigured_vlans(session, allocations)
+++ /dev/null
-# Copyright 2013 Cloudbase Solutions SRL
-# 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_config import cfg
-
-from neutron.api.rpc.handlers import dhcp_rpc
-from neutron.api.rpc.handlers import l3_rpc
-from neutron.api.rpc.handlers import metadata_rpc
-from neutron.api.v2 import attributes
-from neutron.common import exceptions as n_exc
-from neutron.common import rpc as n_rpc
-from neutron.common import topics
-from neutron.db import agents_db
-from neutron.db import db_base_plugin_v2
-from neutron.db import external_net_db
-from neutron.db import l3_gwmode_db
-from neutron.db import portbindings_base
-from neutron.db import quota_db # noqa
-from neutron.extensions import portbindings
-from neutron.extensions import providernet as provider
-from neutron.i18n import _LI
-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.hyperv import agent_notifier_api
-from neutron.plugins.hyperv.common import constants
-from neutron.plugins.hyperv import db as hyperv_db
-from neutron.plugins.hyperv import rpc_callbacks
-
-
-DEFAULT_VLAN_RANGES = []
-
-hyperv_opts = [
- cfg.StrOpt('tenant_network_type', default='local',
- help=_("Network type for tenant networks "
- "(local, flat, vlan or none)")),
- cfg.ListOpt('network_vlan_ranges',
- default=DEFAULT_VLAN_RANGES,
- help=_("List of <physical_network>:<vlan_min>:<vlan_max> "
- "or <physical_network>")),
-]
-
-cfg.CONF.register_opts(hyperv_opts, "HYPERV")
-
-LOG = logging.getLogger(__name__)
-
-
-class BaseNetworkProvider(object):
- def __init__(self):
- self._db = hyperv_db.HyperVPluginDB()
-
- def create_network(self, session, attrs):
- pass
-
- def delete_network(self, session, binding):
- pass
-
- def extend_network_dict(self, network, binding):
- pass
-
-
-class LocalNetworkProvider(BaseNetworkProvider):
- def create_network(self, session, attrs):
- network_type = attrs.get(provider.NETWORK_TYPE)
- segmentation_id = attrs.get(provider.SEGMENTATION_ID)
- if attributes.is_attr_set(segmentation_id):
- msg = _("segmentation_id specified "
- "for %s network") % network_type
- raise n_exc.InvalidInput(error_message=msg)
- attrs[provider.SEGMENTATION_ID] = None
-
- physical_network = attrs.get(provider.PHYSICAL_NETWORK)
- if attributes.is_attr_set(physical_network):
- msg = _("physical_network specified "
- "for %s network") % network_type
- raise n_exc.InvalidInput(error_message=msg)
- attrs[provider.PHYSICAL_NETWORK] = None
-
- def extend_network_dict(self, network, binding):
- network[provider.PHYSICAL_NETWORK] = None
- network[provider.SEGMENTATION_ID] = None
-
-
-class FlatNetworkProvider(BaseNetworkProvider):
- def create_network(self, session, attrs):
- network_type = attrs.get(provider.NETWORK_TYPE)
- segmentation_id = attrs.get(provider.SEGMENTATION_ID)
- if attributes.is_attr_set(segmentation_id):
- msg = _("segmentation_id specified "
- "for %s network") % network_type
- raise n_exc.InvalidInput(error_message=msg)
- segmentation_id = constants.FLAT_VLAN_ID
- attrs[provider.SEGMENTATION_ID] = segmentation_id
-
- physical_network = attrs.get(provider.PHYSICAL_NETWORK)
- if not attributes.is_attr_set(physical_network):
- physical_network = self._db.reserve_flat_net(session)
- attrs[provider.PHYSICAL_NETWORK] = physical_network
- else:
- self._db.reserve_specific_flat_net(session, physical_network)
-
- def delete_network(self, session, binding):
- self._db.release_vlan(session, binding.physical_network,
- constants.FLAT_VLAN_ID)
-
- def extend_network_dict(self, network, binding):
- network[provider.PHYSICAL_NETWORK] = binding.physical_network
-
-
-class VlanNetworkProvider(BaseNetworkProvider):
- def create_network(self, session, attrs):
- segmentation_id = attrs.get(provider.SEGMENTATION_ID)
- if attributes.is_attr_set(segmentation_id):
- physical_network = attrs.get(provider.PHYSICAL_NETWORK)
- if not attributes.is_attr_set(physical_network):
- msg = _("physical_network not provided")
- raise n_exc.InvalidInput(error_message=msg)
- self._db.reserve_specific_vlan(session, physical_network,
- segmentation_id)
- else:
- (physical_network,
- segmentation_id) = self._db.reserve_vlan(session)
- attrs[provider.SEGMENTATION_ID] = segmentation_id
- attrs[provider.PHYSICAL_NETWORK] = physical_network
-
- def delete_network(self, session, binding):
- self._db.release_vlan(
- session, binding.physical_network,
- binding.segmentation_id)
-
- def extend_network_dict(self, network, binding):
- network[provider.PHYSICAL_NETWORK] = binding.physical_network
- network[provider.SEGMENTATION_ID] = binding.segmentation_id
-
-
-class HyperVNeutronPlugin(agents_db.AgentDbMixin,
- db_base_plugin_v2.NeutronDbPluginV2,
- external_net_db.External_net_db_mixin,
- l3_gwmode_db.L3_NAT_db_mixin,
- portbindings_base.PortBindingBaseMixin):
-
- # This attribute specifies whether the plugin supports or not
- # bulk operations. Name mangling is used in order to ensure it
- # is qualified by class
- __native_bulk_support = True
- supported_extension_aliases = ["provider", "external-net", "router",
- "agent", "ext-gw-mode", "binding", "quotas"]
-
- def __init__(self, configfile=None):
- self._db = hyperv_db.HyperVPluginDB()
- self.base_binding_dict = {
- portbindings.VIF_TYPE: portbindings.VIF_TYPE_HYPERV}
- portbindings_base.register_port_dict_function()
- self._set_tenant_network_type()
-
- self._parse_network_vlan_ranges()
- self._create_network_providers_map()
- self._db.sync_vlan_allocations(self._network_vlan_ranges)
-
- self._setup_rpc()
-
- def _set_tenant_network_type(self):
- tenant_network_type = cfg.CONF.HYPERV.tenant_network_type
- if tenant_network_type not in [svc_constants.TYPE_LOCAL,
- svc_constants.TYPE_FLAT,
- svc_constants.TYPE_VLAN,
- svc_constants.TYPE_NONE]:
- msg = _(
- "Invalid tenant_network_type: %s. "
- "Agent terminated!") % tenant_network_type
- raise n_exc.InvalidInput(error_message=msg)
- self._tenant_network_type = tenant_network_type
-
- 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.notifier = agent_notifier_api.AgentNotifierApi(
- topics.AGENT)
- self.endpoints = [rpc_callbacks.HyperVRpcCallbacks(self.notifier),
- dhcp_rpc.DhcpRpcCallback(),
- l3_rpc.L3RpcCallback(),
- agents_db.AgentExtRpcCallback(),
- metadata_rpc.MetadataRpcCallback()]
- 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()
-
- def _parse_network_vlan_ranges(self):
- self._network_vlan_ranges = plugin_utils.parse_network_vlan_ranges(
- cfg.CONF.HYPERV.network_vlan_ranges)
- LOG.info(_LI("Network VLAN ranges: %s"), self._network_vlan_ranges)
-
- def _check_vlan_id_in_range(self, physical_network, vlan_id):
- for r in self._network_vlan_ranges[physical_network]:
- if vlan_id >= r[0] and vlan_id <= r[1]:
- return True
- return False
-
- def _create_network_providers_map(self):
- self._network_providers_map = {
- svc_constants.TYPE_LOCAL: LocalNetworkProvider(),
- svc_constants.TYPE_FLAT: FlatNetworkProvider(),
- svc_constants.TYPE_VLAN: VlanNetworkProvider()
- }
-
- def _process_provider_create(self, context, session, attrs):
- network_type = attrs.get(provider.NETWORK_TYPE)
- network_type_set = attributes.is_attr_set(network_type)
- if not network_type_set:
- if self._tenant_network_type == svc_constants.TYPE_NONE:
- raise n_exc.TenantNetworksDisabled()
- network_type = self._tenant_network_type
- attrs[provider.NETWORK_TYPE] = network_type
-
- if network_type not in self._network_providers_map:
- msg = _("Network type %s not supported") % network_type
- raise n_exc.InvalidInput(error_message=msg)
- p = self._network_providers_map[network_type]
- # Provider specific network creation
- p.create_network(session, attrs)
-
- def create_network(self, context, network):
- session = context.session
- with session.begin(subtransactions=True):
- network_attrs = network['network']
- self._process_provider_create(context, session, network_attrs)
-
- net = super(HyperVNeutronPlugin, self).create_network(
- context, network)
-
- network_type = network_attrs[provider.NETWORK_TYPE]
- physical_network = network_attrs[provider.PHYSICAL_NETWORK]
- segmentation_id = network_attrs[provider.SEGMENTATION_ID]
-
- self._db.add_network_binding(
- session, net['id'], network_type,
- physical_network, segmentation_id)
-
- self._process_l3_create(context, net, network['network'])
- self._extend_network_dict_provider(context, net)
-
- LOG.debug("Created network: %s", net['id'])
- return net
-
- def _extend_network_dict_provider(self, context, network):
- binding = self._db.get_network_binding(
- context.session, network['id'])
- network[provider.NETWORK_TYPE] = binding.network_type
- p = self._network_providers_map[binding.network_type]
- p.extend_network_dict(network, binding)
-
- 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(HyperVNeutronPlugin, 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 = self._db.get_network_binding(session, id)
- self._process_l3_delete(context, id)
- super(HyperVNeutronPlugin, self).delete_network(context, id)
- p = self._network_providers_map[binding.network_type]
- p.delete_network(session, binding)
- # 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):
- net = super(HyperVNeutronPlugin, 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):
- nets = super(HyperVNeutronPlugin, self).get_networks(
- context, filters, None)
- 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):
- port_data = port['port']
- port = super(HyperVNeutronPlugin, self).create_port(context, port)
- self._process_portbindings_create_and_update(context,
- port_data,
- port)
- return port
-
- def update_port(self, context, id, port):
- original_port = super(HyperVNeutronPlugin, self).get_port(
- context, id)
- port_data = port['port']
- port = super(HyperVNeutronPlugin, self).update_port(context, id, port)
- self._process_portbindings_create_and_update(context,
- port_data,
- port)
- if original_port['admin_state_up'] != port['admin_state_up']:
- binding = self._db.get_network_binding(
- None, port['network_id'])
- self.notifier.port_update(context, port,
- binding.network_type,
- binding.segmentation_id,
- binding.physical_network)
- return 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)
- self.disassociate_floatingips(context, id)
-
- super(HyperVNeutronPlugin, self).delete_port(context, id)
- self.notifier.port_delete(context, id)
+++ /dev/null
-# Copyright 2013 Cloudbase Solutions SRL
-# 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 sqlalchemy import Boolean, Column, ForeignKey, Integer, String
-
-from neutron.db import model_base
-
-
-class VlanAllocation(model_base.BASEV2):
- """Represents allocation state of vlan_id on physical network."""
- __tablename__ = 'hyperv_vlan_allocations'
-
- physical_network = Column(String(64), nullable=False, primary_key=True)
- vlan_id = Column(Integer, nullable=False, primary_key=True,
- autoincrement=False)
- allocated = Column(Boolean, nullable=False)
-
- def __init__(self, physical_network, vlan_id):
- self.physical_network = physical_network
- self.vlan_id = vlan_id
- self.allocated = False
-
-
-class NetworkBinding(model_base.BASEV2):
- """Represents binding of virtual network to physical realization."""
- __tablename__ = 'hyperv_network_bindings'
-
- network_id = Column(String(36),
- ForeignKey('networks.id', ondelete="CASCADE"),
- primary_key=True)
- network_type = Column(String(32), nullable=False)
- physical_network = Column(String(64))
- segmentation_id = Column(Integer)
-
- def __init__(self, network_id, network_type, physical_network,
- segmentation_id):
- self.network_id = network_id
- self.network_type = network_type
- self.physical_network = physical_network
- self.segmentation_id = segmentation_id
+++ /dev/null
-# Copyright 2013 Cloudbase Solutions SRL
-# 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 oslo_messaging
-
-from neutron.common import constants as q_const
-from neutron.openstack.common import log as logging
-from neutron.plugins.hyperv import db as hyperv_db
-
-
-LOG = logging.getLogger(__name__)
-
-
-class HyperVRpcCallbacks(object):
-
- # history
- # 1.1 Support Security Group RPC
- # 1.2 Support get_devices_details_list
- target = oslo_messaging.Target(version='1.2')
-
- def __init__(self, notifier):
- super(HyperVRpcCallbacks, self).__init__()
- self.notifier = notifier
- self._db = hyperv_db.HyperVPluginDB()
-
- 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})
- port = self._db.get_port(device)
- if port:
- binding = self._db.get_network_binding(None, port['network_id'])
- entry = {'device': device,
- 'network_id': port['network_id'],
- 'port_id': port['id'],
- 'admin_state_up': port['admin_state_up'],
- 'network_type': binding.network_type,
- 'segmentation_id': binding.segmentation_id,
- 'physical_network': binding.physical_network}
- # Set the port status to UP
- self._db.set_port_status(port['id'], q_const.PORT_STATUS_ACTIVE)
- 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')
- LOG.debug("Device %(device)s no longer exists on %(agent_id)s",
- {'device': device, 'agent_id': agent_id})
- port = self._db.get_port(device)
- if port:
- entry = {'device': device,
- 'exists': True}
- # Set port status to DOWN
- self._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 tunnel_sync(self, rpc_context, **kwargs):
- """Tunnel sync.
-
- Dummy function for ovs agent running on Linux to
- work with Hyper-V plugin and agent.
- """
- entry = dict()
- entry['tunnels'] = {}
- # Return the list of tunnels IP's to the agent
- return entry
+++ /dev/null
-# Copyright 2013 Cloudbase Solutions SRL
-# Copyright 2013 Pedro Navarro Perez
-# 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 contextlib
-
-from oslo_config import cfg
-
-from neutron import context
-from neutron.extensions import portbindings
-from neutron import manager
-from neutron.tests.unit import test_db_plugin as test_plugin
-
-
-class HyperVNeutronPluginTestCase(test_plugin.NeutronDbPluginV2TestCase):
-
- _plugin_name = ('neutron.plugins.hyperv.'
- 'hyperv_neutron_plugin.HyperVNeutronPlugin')
-
- def setUp(self):
- super(HyperVNeutronPluginTestCase, self).setUp(self._plugin_name)
-
-
-class TestHyperVVirtualSwitchBasicGet(
- test_plugin.TestBasicGet, HyperVNeutronPluginTestCase):
- pass
-
-
-class TestHyperVVirtualSwitchV2HTTPResponse(
- test_plugin.TestV2HTTPResponse, HyperVNeutronPluginTestCase):
- pass
-
-
-class TestHyperVVirtualSwitchPortsV2(
- test_plugin.TestPortsV2, HyperVNeutronPluginTestCase):
- def test_port_vif_details(self):
- with self.port(name='name') as port:
- self.assertEqual(port['port']['binding:vif_type'],
- portbindings.VIF_TYPE_HYPERV)
-
- def test_ports_vif_details(self):
- cfg.CONF.set_default('allow_overlapping_ips', True)
- plugin = manager.NeutronManager.get_plugin()
- with contextlib.nested(self.port(), self.port()) as (port1, port2):
- ctx = context.get_admin_context()
- ports = plugin.get_ports(ctx)
- self.assertEqual(len(ports), 2)
- for port in ports:
- self.assertEqual(port['binding:vif_type'],
- portbindings.VIF_TYPE_HYPERV)
-
-
-class TestHyperVVirtualSwitchNetworksV2(
- test_plugin.TestNetworksV2, HyperVNeutronPluginTestCase):
- pass
+++ /dev/null
-# Copyright 2013 Cloudbase Solutions SRL
-# Copyright 2013 Pedro Navarro Perez
-# 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.
-
-"""
-Unit Tests for hyperv neutron rpc
-"""
-
-import contextlib
-
-import mock
-from oslo_context import context as oslo_context
-
-from neutron.agent import rpc as agent_rpc
-from neutron.common import topics
-from neutron.plugins.hyperv import agent_notifier_api as ana
-from neutron.plugins.hyperv.common import constants
-from neutron.tests import base
-
-
-class rpcHyperVApiTestCase(base.BaseTestCase):
-
- def _test_hyperv_neutron_api(
- self, rpcapi, topic, method, rpc_method, **kwargs):
- ctxt = oslo_context.RequestContext('fake_user', 'fake_project')
- expected_retval = 'foo' if rpc_method == 'call' else None
- expected_version = kwargs.pop('version', None)
- fanout = kwargs.pop('fanout', False)
-
- with contextlib.nested(
- mock.patch.object(rpcapi.client, rpc_method),
- mock.patch.object(rpcapi.client, 'prepare'),
- ) as (
- rpc_mock, prepare_mock
- ):
- prepare_mock.return_value = rpcapi.client
- rpc_mock.return_value = expected_retval
- retval = getattr(rpcapi, method)(ctxt, **kwargs)
-
- self.assertEqual(retval, expected_retval)
-
- prepare_args = {}
- if expected_version:
- prepare_args['version'] = expected_version
- if fanout:
- prepare_args['fanout'] = True
- if topic:
- prepare_args['topic'] = topic
- prepare_mock.assert_called_once_with(**prepare_args)
-
- rpc_mock.assert_called_once_with(ctxt, method, **kwargs)
-
- def test_delete_network(self):
- rpcapi = ana.AgentNotifierApi(topics.AGENT)
- self._test_hyperv_neutron_api(
- rpcapi,
- topics.get_topic_name(
- topics.AGENT,
- topics.NETWORK,
- topics.DELETE),
- 'network_delete', rpc_method='cast', fanout=True,
- network_id='fake_request_spec')
-
- def test_port_update(self):
- rpcapi = ana.AgentNotifierApi(topics.AGENT)
- self._test_hyperv_neutron_api(
- rpcapi,
- topics.get_topic_name(
- topics.AGENT,
- topics.PORT,
- topics.UPDATE),
- 'port_update', rpc_method='cast', fanout=True,
- port='fake_port',
- network_type='fake_network_type',
- segmentation_id='fake_segmentation_id',
- physical_network='fake_physical_network')
-
- def test_port_delete(self):
- rpcapi = ana.AgentNotifierApi(topics.AGENT)
- self._test_hyperv_neutron_api(
- rpcapi,
- topics.get_topic_name(
- topics.AGENT,
- topics.PORT,
- topics.DELETE),
- 'port_delete', rpc_method='cast', fanout=True,
- port_id='port_id')
-
- def test_tunnel_update(self):
- rpcapi = ana.AgentNotifierApi(topics.AGENT)
- self._test_hyperv_neutron_api(
- rpcapi,
- topics.get_topic_name(
- topics.AGENT,
- constants.TUNNEL,
- topics.UPDATE),
- 'tunnel_update', rpc_method='cast', fanout=True,
- tunnel_ip='fake_ip', tunnel_id='fake_id')
-
- def test_device_details(self):
- rpcapi = agent_rpc.PluginApi(topics.PLUGIN)
- self._test_hyperv_neutron_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_hyperv_neutron_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_hyperv_neutron_api(
- rpcapi, None,
- 'update_device_down', rpc_method='call',
- device='fake_device',
- agent_id='fake_agent_id',
- host='fake_host')
-
- def test_tunnel_sync(self):
- rpcapi = agent_rpc.PluginApi(topics.PLUGIN)
- self._test_hyperv_neutron_api(
- rpcapi, None,
- 'tunnel_sync', rpc_method='call',
- tunnel_ip='fake_tunnel_ip',
- tunnel_type=None,
- host='fake_host',
- version='1.4')
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
- etc/neutron/plugins/hyperv = etc/neutron/plugins/hyperv/hyperv_neutron_plugin.ini
etc/neutron/plugins/ibm = etc/neutron/plugins/ibm/sdnve_neutron_plugin.ini
etc/neutron/plugins/linuxbridge = etc/neutron/plugins/linuxbridge/linuxbridge_conf.ini
etc/neutron/plugins/metaplugin = etc/neutron/plugins/metaplugin/metaplugin.ini
brocade = neutron.plugins.brocade.NeutronPlugin:BrocadePluginV2
cisco = neutron.plugins.cisco.network_plugin:PluginV2
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
midonet = neutron.plugins.midonet.plugin:MidonetPluginV2
ml2 = neutron.plugins.ml2.plugin:Ml2Plugin