Merge "Enable create and delete segments in ML2"
This commit is contained in:
commit
69015e790c
@ -22,13 +22,17 @@ import six
|
|||||||
from sqlalchemy import or_
|
from sqlalchemy import or_
|
||||||
from sqlalchemy.orm import exc
|
from sqlalchemy.orm import exc
|
||||||
|
|
||||||
from neutron._i18n import _LE
|
from neutron._i18n import _, _LE
|
||||||
|
from neutron.callbacks import events
|
||||||
|
from neutron.callbacks import registry
|
||||||
|
from neutron.callbacks import resources
|
||||||
from neutron.db.models import securitygroup as sg_models
|
from neutron.db.models import securitygroup as sg_models
|
||||||
from neutron.db import models_v2
|
from neutron.db import models_v2
|
||||||
from neutron.db import segments_db
|
from neutron.db import segments_db
|
||||||
from neutron.extensions import portbindings
|
from neutron.extensions import portbindings
|
||||||
from neutron import manager
|
from neutron import manager
|
||||||
from neutron.plugins.ml2 import models
|
from neutron.plugins.ml2 import models
|
||||||
|
from neutron.services.segments import exceptions as seg_exc
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
@ -305,3 +309,30 @@ def is_dhcp_active_on_any_subnet(context, subnet_ids):
|
|||||||
return bool(context.session.query(models_v2.Subnet).
|
return bool(context.session.query(models_v2.Subnet).
|
||||||
enable_eagerloads(False).filter_by(enable_dhcp=True).
|
enable_eagerloads(False).filter_by(enable_dhcp=True).
|
||||||
filter(models_v2.Subnet.id.in_(subnet_ids)).count())
|
filter(models_v2.Subnet.id.in_(subnet_ids)).count())
|
||||||
|
|
||||||
|
|
||||||
|
def _prevent_segment_delete_with_port_bound(resource, event, trigger,
|
||||||
|
context, segment):
|
||||||
|
"""Raise exception if there are any ports bound with segment_id."""
|
||||||
|
segment_id = segment['id']
|
||||||
|
query = context.session.query(models_v2.Port)
|
||||||
|
query = query.join(
|
||||||
|
models.PortBindingLevel,
|
||||||
|
models.PortBindingLevel.port_id == models_v2.Port.id)
|
||||||
|
query = query.filter(models.PortBindingLevel.segment_id == segment_id)
|
||||||
|
port_ids = [p.id for p in query]
|
||||||
|
|
||||||
|
# There are still some ports in the segment, segment should not be deleted
|
||||||
|
# TODO(xiaohhui): Should we delete the dhcp port automatically here?
|
||||||
|
if port_ids:
|
||||||
|
reason = _("The segment is still bound with port(s) "
|
||||||
|
"%s") % ", ".join(port_ids)
|
||||||
|
raise seg_exc.SegmentInUse(segment_id=segment_id, reason=reason)
|
||||||
|
|
||||||
|
|
||||||
|
def subscribe():
|
||||||
|
registry.subscribe(_prevent_segment_delete_with_port_bound,
|
||||||
|
resources.SEGMENT,
|
||||||
|
events.BEFORE_DELETE)
|
||||||
|
|
||||||
|
subscribe()
|
||||||
|
@ -208,6 +208,26 @@ class TypeManager(stevedore.named.NamedExtensionManager):
|
|||||||
segment = self._allocate_tenant_net_segment(session)
|
segment = self._allocate_tenant_net_segment(session)
|
||||||
self._add_network_segment(context, network_id, segment)
|
self._add_network_segment(context, network_id, segment)
|
||||||
|
|
||||||
|
def reserve_network_segment(self, session, segment_data):
|
||||||
|
"""Call type drivers to reserve a network segment."""
|
||||||
|
# Validate the data of segment
|
||||||
|
if not validators.is_attr_set(segment_data[api.NETWORK_TYPE]):
|
||||||
|
msg = _("network_type required")
|
||||||
|
raise exc.InvalidInput(error_message=msg)
|
||||||
|
|
||||||
|
net_type = self._get_attribute(segment_data, api.NETWORK_TYPE)
|
||||||
|
phys_net = self._get_attribute(segment_data, api.PHYSICAL_NETWORK)
|
||||||
|
seg_id = self._get_attribute(segment_data, api.SEGMENTATION_ID)
|
||||||
|
segment = {api.NETWORK_TYPE: net_type,
|
||||||
|
api.PHYSICAL_NETWORK: phys_net,
|
||||||
|
api.SEGMENTATION_ID: seg_id}
|
||||||
|
|
||||||
|
self.validate_provider_segment(segment)
|
||||||
|
|
||||||
|
# Reserve segment in type driver
|
||||||
|
with session.begin(subtransactions=True):
|
||||||
|
return self.reserve_provider_segment(session, segment)
|
||||||
|
|
||||||
def is_partial_segment(self, segment):
|
def is_partial_segment(self, segment):
|
||||||
network_type = segment[api.NETWORK_TYPE]
|
network_type = segment[api.NETWORK_TYPE]
|
||||||
driver = self.drivers.get(network_type)
|
driver = self.drivers.get(network_type)
|
||||||
@ -254,6 +274,9 @@ class TypeManager(stevedore.named.NamedExtensionManager):
|
|||||||
filter_dynamic=None)
|
filter_dynamic=None)
|
||||||
|
|
||||||
for segment in segments:
|
for segment in segments:
|
||||||
|
self.release_network_segment(session, segment)
|
||||||
|
|
||||||
|
def release_network_segment(self, session, segment):
|
||||||
network_type = segment.get(api.NETWORK_TYPE)
|
network_type = segment.get(api.NETWORK_TYPE)
|
||||||
driver = self.drivers.get(network_type)
|
driver = self.drivers.get(network_type)
|
||||||
if driver:
|
if driver:
|
||||||
|
@ -84,6 +84,7 @@ from neutron.plugins.ml2 import models
|
|||||||
from neutron.plugins.ml2 import rpc
|
from neutron.plugins.ml2 import rpc
|
||||||
from neutron.quota import resource_registry
|
from neutron.quota import resource_registry
|
||||||
from neutron.services.qos import qos_consts
|
from neutron.services.qos import qos_consts
|
||||||
|
from neutron.services.segments import plugin as segments_plugin
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
@ -163,6 +164,14 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
self.mechanism_manager.initialize()
|
self.mechanism_manager.initialize()
|
||||||
registry.subscribe(self._port_provisioned, resources.PORT,
|
registry.subscribe(self._port_provisioned, resources.PORT,
|
||||||
provisioning_blocks.PROVISIONING_COMPLETE)
|
provisioning_blocks.PROVISIONING_COMPLETE)
|
||||||
|
registry.subscribe(self._handle_segment_change, resources.SEGMENT,
|
||||||
|
events.PRECOMMIT_CREATE)
|
||||||
|
registry.subscribe(self._handle_segment_change, resources.SEGMENT,
|
||||||
|
events.PRECOMMIT_DELETE)
|
||||||
|
registry.subscribe(self._handle_segment_change, resources.SEGMENT,
|
||||||
|
events.AFTER_CREATE)
|
||||||
|
registry.subscribe(self._handle_segment_change, resources.SEGMENT,
|
||||||
|
events.AFTER_DELETE)
|
||||||
self._setup_dhcp()
|
self._setup_dhcp()
|
||||||
self._start_rpc_notifiers()
|
self._start_rpc_notifiers()
|
||||||
self.add_agent_status_check_worker(self.agent_health_check)
|
self.add_agent_status_check_worker(self.agent_health_check)
|
||||||
@ -927,7 +936,11 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
self.mechanism_manager.delete_network_precommit(
|
self.mechanism_manager.delete_network_precommit(
|
||||||
mech_context)
|
mech_context)
|
||||||
|
|
||||||
self.type_manager.release_network_segments(session, id)
|
registry.notify(resources.NETWORK,
|
||||||
|
events.PRECOMMIT_DELETE,
|
||||||
|
self,
|
||||||
|
context=context,
|
||||||
|
network_id=id)
|
||||||
record = self._get_network(context, id)
|
record = self._get_network(context, id)
|
||||||
LOG.debug("Deleting network record %s", record)
|
LOG.debug("Deleting network record %s", record)
|
||||||
session.delete(record)
|
session.delete(record)
|
||||||
@ -1797,3 +1810,47 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
if mech_driver.obj.check_segment_for_agent(segment, agent):
|
if mech_driver.obj.check_segment_for_agent(segment, agent):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _handle_segment_change(self, rtype, event, trigger, context, segment):
|
||||||
|
if (event == events.PRECOMMIT_CREATE and
|
||||||
|
not isinstance(trigger, segments_plugin.Plugin)):
|
||||||
|
# TODO(xiaohhui): Now, when create network, ml2 will reserve
|
||||||
|
# segment and trigger this event handler. This event handler
|
||||||
|
# will reserve segment again, which will lead to error as the
|
||||||
|
# segment has already been reserved. This check could be removed
|
||||||
|
# by unifying segment creation procedure.
|
||||||
|
return
|
||||||
|
|
||||||
|
session = context.session
|
||||||
|
network_id = segment.get('network_id')
|
||||||
|
|
||||||
|
if event == events.PRECOMMIT_CREATE:
|
||||||
|
updated_segment = self.type_manager.reserve_network_segment(
|
||||||
|
session, segment)
|
||||||
|
# The segmentation id might be from ML2 type driver, update it
|
||||||
|
# in the original segment.
|
||||||
|
segment[api.SEGMENTATION_ID] = updated_segment[api.SEGMENTATION_ID]
|
||||||
|
elif event == events.PRECOMMIT_DELETE:
|
||||||
|
self.type_manager.release_network_segment(session, segment)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._notify_mechanism_driver_for_segment_change(
|
||||||
|
event, context, network_id)
|
||||||
|
except ml2_exc.MechanismDriverError:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
LOG.error(_LE("mechanism_manager error occurred when "
|
||||||
|
"handle event %(event)s for segment "
|
||||||
|
"'%(segment)s'"),
|
||||||
|
{'event': event, 'segment': segment['id']})
|
||||||
|
|
||||||
|
def _notify_mechanism_driver_for_segment_change(self, event,
|
||||||
|
context, network_id):
|
||||||
|
network_with_segments = self.get_network(context, network_id)
|
||||||
|
mech_context = driver_context.NetworkContext(
|
||||||
|
self, context, network_with_segments,
|
||||||
|
original_network=network_with_segments)
|
||||||
|
if (event == events.PRECOMMIT_CREATE or
|
||||||
|
event == events.PRECOMMIT_DELETE):
|
||||||
|
self.mechanism_manager.update_network_precommit(mech_context)
|
||||||
|
elif event == events.AFTER_CREATE or event == events.AFTER_DELETE:
|
||||||
|
self.mechanism_manager.update_network_postcommit(mech_context)
|
||||||
|
@ -69,7 +69,8 @@ class SegmentDbMixin(common_db_mixin.CommonDbMixin):
|
|||||||
db.NETWORK_TYPE: segment_db[db.NETWORK_TYPE],
|
db.NETWORK_TYPE: segment_db[db.NETWORK_TYPE],
|
||||||
db.SEGMENTATION_ID: segment_db[db.SEGMENTATION_ID],
|
db.SEGMENTATION_ID: segment_db[db.SEGMENTATION_ID],
|
||||||
'hosts': [mapping.host for mapping in
|
'hosts': [mapping.host for mapping in
|
||||||
segment_db.segment_host_mapping]}
|
segment_db.segment_host_mapping],
|
||||||
|
'segment_index': segment_db['segment_index']}
|
||||||
return self._fields(res, fields)
|
return self._fields(res, fields)
|
||||||
|
|
||||||
def _get_segment(self, context, segment_id):
|
def _get_segment(self, context, segment_id):
|
||||||
@ -98,15 +99,33 @@ class SegmentDbMixin(common_db_mixin.CommonDbMixin):
|
|||||||
db.PHYSICAL_NETWORK: physical_network,
|
db.PHYSICAL_NETWORK: physical_network,
|
||||||
db.NETWORK_TYPE: network_type,
|
db.NETWORK_TYPE: network_type,
|
||||||
db.SEGMENTATION_ID: segmentation_id}
|
db.SEGMENTATION_ID: segmentation_id}
|
||||||
|
# Calculate the index of segment
|
||||||
|
segment_index = 0
|
||||||
|
segments = self.get_segments(
|
||||||
|
context,
|
||||||
|
filters={'network_id': [network_id]},
|
||||||
|
fields=['segment_index'],
|
||||||
|
sorts=[('segment_index', True)])
|
||||||
|
if segments:
|
||||||
|
# NOTE(xiaohhui): The new index is the last index + 1, this
|
||||||
|
# may casue discontinuous segment_index. But segment_index
|
||||||
|
# can functionally work as the order index for segments.
|
||||||
|
segment_index = (segments[-1].get('segment_index') + 1)
|
||||||
|
args['segment_index'] = segment_index
|
||||||
|
|
||||||
new_segment = db.NetworkSegment(**args)
|
new_segment = db.NetworkSegment(**args)
|
||||||
try:
|
try:
|
||||||
context.session.add(new_segment)
|
context.session.add(new_segment)
|
||||||
context.session.flush([new_segment])
|
context.session.flush([new_segment])
|
||||||
except db_exc.DBReferenceError:
|
except db_exc.DBReferenceError:
|
||||||
raise n_exc.NetworkNotFound(net_id=network_id)
|
raise n_exc.NetworkNotFound(net_id=network_id)
|
||||||
|
# Do some preliminary operations before commiting the segment to db
|
||||||
registry.notify(resources.SEGMENT, events.PRECOMMIT_CREATE, self,
|
registry.notify(resources.SEGMENT, events.PRECOMMIT_CREATE, self,
|
||||||
context=context, segment=new_segment)
|
context=context, segment=new_segment)
|
||||||
|
|
||||||
|
registry.notify(resources.SEGMENT, events.AFTER_CREATE, self,
|
||||||
|
context=context, segment=new_segment)
|
||||||
|
|
||||||
return self._make_segment_dict(new_segment)
|
return self._make_segment_dict(new_segment)
|
||||||
|
|
||||||
@log_helpers.log_method_call
|
@log_helpers.log_method_call
|
||||||
@ -156,11 +175,26 @@ class SegmentDbMixin(common_db_mixin.CommonDbMixin):
|
|||||||
@log_helpers.log_method_call
|
@log_helpers.log_method_call
|
||||||
def delete_segment(self, context, uuid):
|
def delete_segment(self, context, uuid):
|
||||||
"""Delete an existing segment."""
|
"""Delete an existing segment."""
|
||||||
|
segment = self.get_segment(context, uuid)
|
||||||
|
# Do some preliminary operations before deleting the segment
|
||||||
|
registry.notify(resources.SEGMENT, events.BEFORE_DELETE,
|
||||||
|
self.delete_segment, context=context,
|
||||||
|
segment=segment)
|
||||||
|
|
||||||
|
# Delete segment in DB
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
query = self._model_query(context, db.NetworkSegment)
|
query = self._model_query(context, db.NetworkSegment)
|
||||||
query = query.filter(db.NetworkSegment.id == uuid)
|
query = query.filter(db.NetworkSegment.id == uuid)
|
||||||
if 0 == query.delete():
|
if 0 == query.delete():
|
||||||
raise exceptions.SegmentNotFound(segment_id=uuid)
|
raise exceptions.SegmentNotFound(segment_id=uuid)
|
||||||
|
# Do some preliminary operations before deleting segment in db
|
||||||
|
registry.notify(resources.SEGMENT, events.PRECOMMIT_DELETE,
|
||||||
|
self.delete_segment, context=context,
|
||||||
|
segment=segment)
|
||||||
|
|
||||||
|
registry.notify(resources.SEGMENT, events.AFTER_DELETE,
|
||||||
|
self.delete_segment, context=context,
|
||||||
|
segment=segment)
|
||||||
|
|
||||||
|
|
||||||
def update_segment_host_mapping(context, host, current_segment_ids):
|
def update_segment_host_mapping(context, host, current_segment_ids):
|
||||||
@ -199,6 +233,10 @@ def _get_phys_nets(agent):
|
|||||||
|
|
||||||
reported_hosts = set()
|
reported_hosts = set()
|
||||||
|
|
||||||
|
# NOTE: Module level variable of segments plugin. It should be removed once
|
||||||
|
# segments becomes a default plugin.
|
||||||
|
segments_plugin = None
|
||||||
|
|
||||||
|
|
||||||
def get_segments_with_phys_nets(context, phys_nets):
|
def get_segments_with_phys_nets(context, phys_nets):
|
||||||
"""Get segments from physical networks.
|
"""Get segments from physical networks.
|
||||||
@ -245,6 +283,12 @@ def _update_segment_host_mapping_for_agent(resource, event, trigger,
|
|||||||
|
|
||||||
def _add_segment_host_mapping_for_segment(resource, event, trigger,
|
def _add_segment_host_mapping_for_segment(resource, event, trigger,
|
||||||
context, segment):
|
context, segment):
|
||||||
|
if not context.session.is_active:
|
||||||
|
# The session might be in partial rollback state, due to errors in
|
||||||
|
# peer callback. In that case, there is no need to add the mapping.
|
||||||
|
# Just return here.
|
||||||
|
return
|
||||||
|
|
||||||
if not segment.physical_network:
|
if not segment.physical_network:
|
||||||
return
|
return
|
||||||
cp = manager.NeutronManager.get_plugin()
|
cp = manager.NeutronManager.get_plugin()
|
||||||
@ -259,6 +303,19 @@ def _add_segment_host_mapping_for_segment(resource, event, trigger,
|
|||||||
map_segment_to_hosts(context, segment.id, hosts)
|
map_segment_to_hosts(context, segment.id, hosts)
|
||||||
|
|
||||||
|
|
||||||
|
def _delete_segments_for_network(resource, event, trigger,
|
||||||
|
context, network_id):
|
||||||
|
admin_ctx = context.elevated()
|
||||||
|
global segments_plugin
|
||||||
|
if not segments_plugin:
|
||||||
|
segments_plugin = manager.NeutronManager.load_class_for_provider(
|
||||||
|
'neutron.service_plugins', 'segments')()
|
||||||
|
segments = segments_plugin.get_segments(
|
||||||
|
admin_ctx, filters={'network_id': [network_id]})
|
||||||
|
for segment in segments:
|
||||||
|
segments_plugin.delete_segment(admin_ctx, segment['id'])
|
||||||
|
|
||||||
|
|
||||||
def subscribe():
|
def subscribe():
|
||||||
registry.subscribe(_update_segment_host_mapping_for_agent,
|
registry.subscribe(_update_segment_host_mapping_for_agent,
|
||||||
resources.AGENT,
|
resources.AGENT,
|
||||||
@ -268,5 +325,8 @@ def subscribe():
|
|||||||
events.AFTER_UPDATE)
|
events.AFTER_UPDATE)
|
||||||
registry.subscribe(_add_segment_host_mapping_for_segment,
|
registry.subscribe(_add_segment_host_mapping_for_segment,
|
||||||
resources.SEGMENT, events.PRECOMMIT_CREATE)
|
resources.SEGMENT, events.PRECOMMIT_CREATE)
|
||||||
|
registry.subscribe(_delete_segments_for_network,
|
||||||
|
resources.NETWORK,
|
||||||
|
events.PRECOMMIT_DELETE)
|
||||||
|
|
||||||
subscribe()
|
subscribe()
|
||||||
|
@ -54,3 +54,7 @@ class HostNotCompatibleWithFixedIps(exceptions.Conflict):
|
|||||||
message = _("Host %(host)s is not connected to a segment where the "
|
message = _("Host %(host)s is not connected to a segment where the "
|
||||||
"existing fixed_ips on port %(port_id)s will function given "
|
"existing fixed_ips on port %(port_id)s will function given "
|
||||||
"the routed network topology.")
|
"the routed network topology.")
|
||||||
|
|
||||||
|
|
||||||
|
class SegmentInUse(exceptions.InUse):
|
||||||
|
message = _("Segment '%(segment_id)s' cannot be deleted: %(reason)s.")
|
||||||
|
@ -16,7 +16,11 @@
|
|||||||
|
|
||||||
from sqlalchemy.orm import session
|
from sqlalchemy.orm import session
|
||||||
|
|
||||||
|
from neutron._i18n import _
|
||||||
from neutron.api.v2 import attributes
|
from neutron.api.v2 import attributes
|
||||||
|
from neutron.callbacks import events
|
||||||
|
from neutron.callbacks import registry
|
||||||
|
from neutron.callbacks import resources
|
||||||
from neutron.db import common_db_mixin
|
from neutron.db import common_db_mixin
|
||||||
from neutron.db import models_v2
|
from neutron.db import models_v2
|
||||||
from neutron.extensions import ip_allocation
|
from neutron.extensions import ip_allocation
|
||||||
@ -24,6 +28,7 @@ from neutron.extensions import l2_adjacency
|
|||||||
from neutron.extensions import segment
|
from neutron.extensions import segment
|
||||||
from neutron import manager
|
from neutron import manager
|
||||||
from neutron.services.segments import db
|
from neutron.services.segments import db
|
||||||
|
from neutron.services.segments import exceptions
|
||||||
|
|
||||||
|
|
||||||
def _extend_network_dict_binding(plugin, network_res, network_db):
|
def _extend_network_dict_binding(plugin, network_res, network_db):
|
||||||
@ -71,8 +76,25 @@ class Plugin(db.SegmentDbMixin, segment.SegmentPluginBase):
|
|||||||
common_db_mixin.CommonDbMixin.register_dict_extend_funcs(
|
common_db_mixin.CommonDbMixin.register_dict_extend_funcs(
|
||||||
attributes.PORTS, [_extend_port_dict_binding])
|
attributes.PORTS, [_extend_port_dict_binding])
|
||||||
|
|
||||||
|
registry.subscribe(
|
||||||
|
self._prevent_segment_delete_with_subnet_associated,
|
||||||
|
resources.SEGMENT,
|
||||||
|
events.BEFORE_DELETE)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_instance(cls):
|
def get_instance(cls):
|
||||||
if cls._instance is None:
|
if cls._instance is None:
|
||||||
cls._instance = cls()
|
cls._instance = cls()
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
|
def _prevent_segment_delete_with_subnet_associated(
|
||||||
|
self, resource, event, trigger, context, segment):
|
||||||
|
"""Raise exception if there are any subnets associated with segment."""
|
||||||
|
segment_id = segment['id']
|
||||||
|
query = context.session.query(models_v2.Subnet.id)
|
||||||
|
query = query.filter(models_v2.Subnet.segment_id == segment_id)
|
||||||
|
subnet_ids = [s[0] for s in query]
|
||||||
|
if subnet_ids:
|
||||||
|
reason = _("The segment is still associated with subnet(s) "
|
||||||
|
"%s") % ", ".join(subnet_ids)
|
||||||
|
raise exceptions.SegmentInUse(segment_id=segment_id, reason=reason)
|
||||||
|
@ -21,6 +21,7 @@ import webob.exc
|
|||||||
|
|
||||||
from neutron.api.v2 import attributes
|
from neutron.api.v2 import attributes
|
||||||
from neutron.callbacks import events
|
from neutron.callbacks import events
|
||||||
|
from neutron.callbacks import exceptions
|
||||||
from neutron.callbacks import registry
|
from neutron.callbacks import registry
|
||||||
from neutron.callbacks import resources
|
from neutron.callbacks import resources
|
||||||
from neutron import context
|
from neutron import context
|
||||||
@ -175,24 +176,82 @@ class TestSegment(SegmentTestCase):
|
|||||||
expected=expected_segment)
|
expected=expected_segment)
|
||||||
|
|
||||||
def test_create_segment_no_segmentation_id(self):
|
def test_create_segment_no_segmentation_id(self):
|
||||||
|
|
||||||
|
def _mock_reserve_segmentation_id(rtype, event, trigger,
|
||||||
|
context, segment):
|
||||||
|
if not segment.get('segmentation_id'):
|
||||||
|
segment['segmentation_id'] = 200
|
||||||
|
|
||||||
with self.network() as network:
|
with self.network() as network:
|
||||||
network = network['network']
|
network = network['network']
|
||||||
|
|
||||||
|
registry.subscribe(_mock_reserve_segmentation_id, resources.SEGMENT,
|
||||||
|
events.PRECOMMIT_CREATE)
|
||||||
expected_segment = {'network_id': network['id'],
|
expected_segment = {'network_id': network['id'],
|
||||||
'physical_network': 'phys_net',
|
'physical_network': 'phys_net',
|
||||||
'network_type': 'net_type',
|
'network_type': 'net_type',
|
||||||
'segmentation_id': None}
|
'segmentation_id': 200}
|
||||||
self._test_create_segment(network_id=network['id'],
|
self._test_create_segment(network_id=network['id'],
|
||||||
physical_network='phys_net',
|
physical_network='phys_net',
|
||||||
expected=expected_segment)
|
expected=expected_segment)
|
||||||
|
|
||||||
|
def test_create_segment_with_exception_in_core_plugin(self):
|
||||||
|
cxt = context.get_admin_context()
|
||||||
|
with self.network() as network:
|
||||||
|
network = network['network']
|
||||||
|
|
||||||
|
with mock.patch.object(registry, 'notify') as notify:
|
||||||
|
notify.side_effect = exceptions.CallbackFailure(errors=Exception)
|
||||||
|
self.assertRaises(webob.exc.HTTPClientError,
|
||||||
|
self.segment,
|
||||||
|
network_id=network['id'],
|
||||||
|
segmentation_id=200)
|
||||||
|
|
||||||
|
network_segments = segments_db.get_network_segments(cxt.session,
|
||||||
|
network['id'])
|
||||||
|
self.assertEqual([], network_segments)
|
||||||
|
|
||||||
|
def test_create_segments_in_certain_order(self):
|
||||||
|
cxt = context.get_admin_context()
|
||||||
|
with self.network() as network:
|
||||||
|
network = network['network']
|
||||||
|
segment1 = self.segment(
|
||||||
|
network_id=network['id'], segmentation_id=200)
|
||||||
|
segment2 = self.segment(
|
||||||
|
network_id=network['id'], segmentation_id=201)
|
||||||
|
segment3 = self.segment(
|
||||||
|
network_id=network['id'], segmentation_id=202)
|
||||||
|
network_segments = segments_db.get_network_segments(cxt.session,
|
||||||
|
network['id'])
|
||||||
|
self.assertEqual(segment1['segment']['id'],
|
||||||
|
network_segments[0]['id'])
|
||||||
|
self.assertEqual(segment2['segment']['id'],
|
||||||
|
network_segments[1]['id'])
|
||||||
|
self.assertEqual(segment3['segment']['id'],
|
||||||
|
network_segments[2]['id'])
|
||||||
|
|
||||||
def test_delete_segment(self):
|
def test_delete_segment(self):
|
||||||
with self.network() as network:
|
with self.network() as network:
|
||||||
network = network['network']
|
network = network['network']
|
||||||
segment = self.segment(network_id=network['id'])
|
self.segment(network_id=network['id'], segmentation_id=200)
|
||||||
|
segment = self.segment(network_id=network['id'], segmentation_id=201)
|
||||||
self._delete('segments', segment['segment']['id'])
|
self._delete('segments', segment['segment']['id'])
|
||||||
self._show('segments', segment['segment']['id'],
|
self._show('segments', segment['segment']['id'],
|
||||||
expected_code=webob.exc.HTTPNotFound.code)
|
expected_code=webob.exc.HTTPNotFound.code)
|
||||||
|
|
||||||
|
def test_delete_segment_failed_with_subnet_associated(self):
|
||||||
|
with self.network() as network:
|
||||||
|
net = network['network']
|
||||||
|
|
||||||
|
segment = self._test_create_segment(network_id=net['id'],
|
||||||
|
segmentation_id=200)
|
||||||
|
segment_id = segment['segment']['id']
|
||||||
|
with self.subnet(network=network, segment_id=segment_id):
|
||||||
|
self._delete('segments', segment_id,
|
||||||
|
expected_code=webob.exc.HTTPConflict.code)
|
||||||
|
exist_segment = self._show('segments', segment_id)
|
||||||
|
self.assertEqual(segment_id, exist_segment['segment']['id'])
|
||||||
|
|
||||||
def test_get_segment(self):
|
def test_get_segment(self):
|
||||||
with self.network() as network:
|
with self.network() as network:
|
||||||
network = network['network']
|
network = network['network']
|
||||||
@ -211,10 +270,19 @@ class TestSegment(SegmentTestCase):
|
|||||||
segmentation_id=200)
|
segmentation_id=200)
|
||||||
self._test_create_segment(network_id=network['id'],
|
self._test_create_segment(network_id=network['id'],
|
||||||
physical_network='phys_net2',
|
physical_network='phys_net2',
|
||||||
segmentation_id=200)
|
segmentation_id=201)
|
||||||
res = self._list('segments')
|
res = self._list('segments')
|
||||||
self.assertEqual(2, len(res['segments']))
|
self.assertEqual(2, len(res['segments']))
|
||||||
|
|
||||||
|
def test_update_segments(self):
|
||||||
|
with self.network() as network:
|
||||||
|
net = network['network']
|
||||||
|
segment = self._test_create_segment(network_id=net['id'],
|
||||||
|
segmentation_id=200)
|
||||||
|
segment['segment']['segmentation_id'] = '201'
|
||||||
|
self._update('segments', segment['segment']['id'], segment,
|
||||||
|
expected_code=webob.exc.HTTPClientError.code)
|
||||||
|
|
||||||
|
|
||||||
class TestSegmentML2(SegmentTestCase):
|
class TestSegmentML2(SegmentTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -236,7 +304,8 @@ class TestSegmentSubnetAssociation(SegmentTestCase):
|
|||||||
with self.network() as network:
|
with self.network() as network:
|
||||||
net = network['network']
|
net = network['network']
|
||||||
|
|
||||||
segment = self._test_create_segment(network_id=net['id'])
|
segment = self._test_create_segment(network_id=net['id'],
|
||||||
|
segmentation_id=200)
|
||||||
segment_id = segment['segment']['id']
|
segment_id = segment['segment']['id']
|
||||||
|
|
||||||
with self.subnet(network=network, segment_id=segment_id) as subnet:
|
with self.subnet(network=network, segment_id=segment_id) as subnet:
|
||||||
@ -253,7 +322,8 @@ class TestSegmentSubnetAssociation(SegmentTestCase):
|
|||||||
with self.network() as network2:
|
with self.network() as network2:
|
||||||
net = network1['network']
|
net = network1['network']
|
||||||
|
|
||||||
segment = self._test_create_segment(network_id=net['id'])
|
segment = self._test_create_segment(network_id=net['id'],
|
||||||
|
segmentation_id=200)
|
||||||
|
|
||||||
res = self._create_subnet(self.fmt,
|
res = self._create_subnet(self.fmt,
|
||||||
net_id=network2['network']['id'],
|
net_id=network2['network']['id'],
|
||||||
@ -282,7 +352,8 @@ class TestSegmentSubnetAssociation(SegmentTestCase):
|
|||||||
with self.subnet(network=network):
|
with self.subnet(network=network):
|
||||||
net = network['network']
|
net = network['network']
|
||||||
|
|
||||||
segment = self._test_create_segment(network_id=net['id'])
|
segment = self._test_create_segment(network_id=net['id'],
|
||||||
|
segmentation_id=200)
|
||||||
|
|
||||||
res = self._create_subnet(self.fmt,
|
res = self._create_subnet(self.fmt,
|
||||||
net_id=net['id'],
|
net_id=net['id'],
|
||||||
@ -322,6 +393,9 @@ class HostSegmentMappingTestCase(SegmentTestCase):
|
|||||||
config.cfg.CONF.set_override('mechanism_drivers',
|
config.cfg.CONF.set_override('mechanism_drivers',
|
||||||
self._mechanism_drivers,
|
self._mechanism_drivers,
|
||||||
group='ml2')
|
group='ml2')
|
||||||
|
config.cfg.CONF.set_override('network_vlan_ranges',
|
||||||
|
['phys_net1', 'phys_net2'],
|
||||||
|
group='ml2_type_vlan')
|
||||||
if not plugin:
|
if not plugin:
|
||||||
plugin = 'ml2'
|
plugin = 'ml2'
|
||||||
super(HostSegmentMappingTestCase, self).setUp(plugin=plugin)
|
super(HostSegmentMappingTestCase, self).setUp(plugin=plugin)
|
||||||
@ -511,7 +585,7 @@ class TestMl2HostSegmentMappingOVS(HostSegmentMappingTestCase):
|
|||||||
network = network['network']
|
network = network['network']
|
||||||
segment2 = self._test_create_segment(
|
segment2 = self._test_create_segment(
|
||||||
network_id=network['id'], physical_network=physical_network,
|
network_id=network['id'], physical_network=physical_network,
|
||||||
segmentation_id=200, network_type=p_constants.TYPE_VLAN)['segment']
|
segmentation_id=201, network_type=p_constants.TYPE_VLAN)['segment']
|
||||||
segments_host_db = self._get_segments_for_host(host1)
|
segments_host_db = self._get_segments_for_host(host1)
|
||||||
self.assertEqual(set((segment['id'], segment2['id'])),
|
self.assertEqual(set((segment['id'], segment2['id'])),
|
||||||
set(segments_host_db))
|
set(segments_host_db))
|
||||||
@ -663,7 +737,8 @@ class TestSegmentAwareIpam(SegmentTestCase):
|
|||||||
|
|
||||||
segment = self._test_create_segment(
|
segment = self._test_create_segment(
|
||||||
network_id=network['network']['id'],
|
network_id=network['network']['id'],
|
||||||
physical_network=physnet)
|
physical_network=physnet,
|
||||||
|
network_type=p_constants.TYPE_VLAN)
|
||||||
|
|
||||||
ip_version = netaddr.IPNetwork(cidr).version if cidr else None
|
ip_version = netaddr.IPNetwork(cidr).version if cidr else None
|
||||||
with self.subnet(network=network,
|
with self.subnet(network=network,
|
||||||
@ -730,7 +805,8 @@ class TestSegmentAwareIpam(SegmentTestCase):
|
|||||||
with self.network() as network:
|
with self.network() as network:
|
||||||
segment = self._test_create_segment(
|
segment = self._test_create_segment(
|
||||||
network_id=network['network']['id'],
|
network_id=network['network']['id'],
|
||||||
physical_network='physnet')
|
physical_network='physnet',
|
||||||
|
network_type=p_constants.TYPE_VLAN)
|
||||||
|
|
||||||
# Map the host to the segment
|
# Map the host to the segment
|
||||||
self._setup_host_mappings([(segment['segment']['id'], 'fakehost')])
|
self._setup_host_mappings([(segment['segment']['id'], 'fakehost')])
|
||||||
@ -753,7 +829,8 @@ class TestSegmentAwareIpam(SegmentTestCase):
|
|||||||
cidr='2001:db8:0:0::/64') as subnet:
|
cidr='2001:db8:0:0::/64') as subnet:
|
||||||
segment = self._test_create_segment(
|
segment = self._test_create_segment(
|
||||||
network_id=network['network']['id'],
|
network_id=network['network']['id'],
|
||||||
physical_network='physnet')
|
physical_network='physnet',
|
||||||
|
network_type=p_constants.TYPE_VLAN)
|
||||||
|
|
||||||
self._validate_l2_adjacency(network['network']['id'], is_adjacent=True)
|
self._validate_l2_adjacency(network['network']['id'], is_adjacent=True)
|
||||||
|
|
||||||
@ -823,7 +900,8 @@ class TestSegmentAwareIpam(SegmentTestCase):
|
|||||||
with self.network() as network:
|
with self.network() as network:
|
||||||
segment = self._test_create_segment(
|
segment = self._test_create_segment(
|
||||||
network_id=network['network']['id'],
|
network_id=network['network']['id'],
|
||||||
physical_network='physnet')
|
physical_network='physnet',
|
||||||
|
network_type=p_constants.TYPE_VLAN)
|
||||||
|
|
||||||
# Create a port with no IP address (since there is no subnet)
|
# Create a port with no IP address (since there is no subnet)
|
||||||
port = self._create_deferred_ip_port(network)
|
port = self._create_deferred_ip_port(network)
|
||||||
@ -864,7 +942,8 @@ class TestSegmentAwareIpam(SegmentTestCase):
|
|||||||
with self.network() as network:
|
with self.network() as network:
|
||||||
segment = self._test_create_segment(
|
segment = self._test_create_segment(
|
||||||
network_id=network['network']['id'],
|
network_id=network['network']['id'],
|
||||||
physical_network='physnet')
|
physical_network='physnet',
|
||||||
|
network_type=p_constants.TYPE_VLAN)
|
||||||
|
|
||||||
# Map the host to the segment
|
# Map the host to the segment
|
||||||
self._setup_host_mappings([(segment['segment']['id'], 'fakehost')])
|
self._setup_host_mappings([(segment['segment']['id'], 'fakehost')])
|
||||||
@ -1155,6 +1234,10 @@ class TestSegmentAwareIpam(SegmentTestCase):
|
|||||||
|
|
||||||
class TestSegmentAwareIpamML2(TestSegmentAwareIpam):
|
class TestSegmentAwareIpamML2(TestSegmentAwareIpam):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
config.cfg.CONF.set_override('network_vlan_ranges',
|
||||||
|
['physnet:200:209', 'physnet0:200:209',
|
||||||
|
'physnet1:200:209', 'physnet2:200:209'],
|
||||||
|
group='ml2_type_vlan')
|
||||||
super(TestSegmentAwareIpamML2, self).setUp(plugin='ml2')
|
super(TestSegmentAwareIpamML2, self).setUp(plugin='ml2')
|
||||||
|
|
||||||
|
|
||||||
@ -1174,7 +1257,7 @@ class TestDhcpAgentSegmentScheduling(HostSegmentMappingTestCase):
|
|||||||
segment = self._test_create_segment(network_id=network['id'],
|
segment = self._test_create_segment(network_id=network['id'],
|
||||||
physical_network=phys_net,
|
physical_network=phys_net,
|
||||||
segmentation_id=200,
|
segmentation_id=200,
|
||||||
network_type='vxlan')
|
network_type='vlan')
|
||||||
dhcp_agents = self.dhcp_agent_db.get_dhcp_agents_hosting_networks(
|
dhcp_agents = self.dhcp_agent_db.get_dhcp_agents_hosting_networks(
|
||||||
self.ctx, [network['id']])
|
self.ctx, [network['id']])
|
||||||
self.assertEqual(0, len(dhcp_agents))
|
self.assertEqual(0, len(dhcp_agents))
|
||||||
@ -1230,7 +1313,7 @@ class TestDhcpAgentSegmentScheduling(HostSegmentMappingTestCase):
|
|||||||
segment2 = self._test_create_segment(network_id=network['id'],
|
segment2 = self._test_create_segment(network_id=network['id'],
|
||||||
physical_network=phys_net2,
|
physical_network=phys_net2,
|
||||||
segmentation_id=200,
|
segmentation_id=200,
|
||||||
network_type='vxlan')['segment']
|
network_type='vlan')['segment']
|
||||||
self._register_agent(DHCP_HOSTA,
|
self._register_agent(DHCP_HOSTA,
|
||||||
mappings={phys_net1: 'br-eth-1'},
|
mappings={phys_net1: 'br-eth-1'},
|
||||||
plugin=self.plugin)
|
plugin=self.plugin)
|
||||||
|
@ -34,7 +34,6 @@ class TestMechanismDriver(api.MechanismDriver):
|
|||||||
assert(context.current['id'] == context.original['id'])
|
assert(context.current['id'] == context.original['id'])
|
||||||
else:
|
else:
|
||||||
assert(not context.original)
|
assert(not context.original)
|
||||||
assert(context.network_segments)
|
|
||||||
|
|
||||||
def create_network_precommit(self, context):
|
def create_network_precommit(self, context):
|
||||||
self._check_network_context(context, False)
|
self._check_network_context(context, False)
|
||||||
|
@ -30,6 +30,7 @@ from sqlalchemy.orm import exc as sqla_exc
|
|||||||
|
|
||||||
from neutron._i18n import _
|
from neutron._i18n import _
|
||||||
from neutron.callbacks import events
|
from neutron.callbacks import events
|
||||||
|
from neutron.callbacks import exceptions as c_exc
|
||||||
from neutron.callbacks import registry
|
from neutron.callbacks import registry
|
||||||
from neutron.callbacks import resources
|
from neutron.callbacks import resources
|
||||||
from neutron.common import utils
|
from neutron.common import utils
|
||||||
@ -58,6 +59,8 @@ from neutron.plugins.ml2 import managers
|
|||||||
from neutron.plugins.ml2 import models
|
from neutron.plugins.ml2 import models
|
||||||
from neutron.plugins.ml2 import plugin as ml2_plugin
|
from neutron.plugins.ml2 import plugin as ml2_plugin
|
||||||
from neutron.services.qos import qos_consts
|
from neutron.services.qos import qos_consts
|
||||||
|
from neutron.services.segments import db as segments_plugin_db
|
||||||
|
from neutron.services.segments import plugin as segments_plugin
|
||||||
from neutron.tests import base
|
from neutron.tests import base
|
||||||
from neutron.tests.common import helpers
|
from neutron.tests.common import helpers
|
||||||
from neutron.tests.unit import _test_extension_portbindings as test_bindings
|
from neutron.tests.unit import _test_extension_portbindings as test_bindings
|
||||||
@ -1840,6 +1843,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase):
|
|||||||
|
|
||||||
with mock.patch.object(type_vlan.VlanTypeDriver,
|
with mock.patch.object(type_vlan.VlanTypeDriver,
|
||||||
'release_segment') as rs:
|
'release_segment') as rs:
|
||||||
|
segments_plugin_db.subscribe()
|
||||||
req = self.new_delete_request('networks', network_id)
|
req = self.new_delete_request('networks', network_id)
|
||||||
res = req.get_response(self.api)
|
res = req.get_response(self.api)
|
||||||
self.assertEqual(2, rs.call_count)
|
self.assertEqual(2, rs.call_count)
|
||||||
@ -2474,3 +2478,131 @@ class TestTransactionGuard(Ml2PluginV2TestCase):
|
|||||||
with ctx.session.begin(subtransactions=True):
|
with ctx.session.begin(subtransactions=True):
|
||||||
with testtools.ExpectedException(RuntimeError):
|
with testtools.ExpectedException(RuntimeError):
|
||||||
plugin.delete_subnet(ctx, 'id')
|
plugin.delete_subnet(ctx, 'id')
|
||||||
|
|
||||||
|
|
||||||
|
class TestML2Segments(Ml2PluginV2TestCase):
|
||||||
|
|
||||||
|
def _reserve_segment(self, network, seg_id=None):
|
||||||
|
segment = {'id': 'fake_id',
|
||||||
|
'network_id': network['network']['id'],
|
||||||
|
'tenant_id': network['network']['tenant_id'],
|
||||||
|
driver_api.NETWORK_TYPE: 'vlan',
|
||||||
|
driver_api.PHYSICAL_NETWORK: self.physnet}
|
||||||
|
if seg_id:
|
||||||
|
segment[driver_api.SEGMENTATION_ID] = seg_id
|
||||||
|
|
||||||
|
self.driver._handle_segment_change(
|
||||||
|
mock.ANY, events.PRECOMMIT_CREATE, segments_plugin.Plugin(),
|
||||||
|
self.context, segment)
|
||||||
|
|
||||||
|
if seg_id:
|
||||||
|
# Assert it is not changed
|
||||||
|
self.assertEqual(seg_id, segment[driver_api.SEGMENTATION_ID])
|
||||||
|
else:
|
||||||
|
self.assertTrue(segment[driver_api.SEGMENTATION_ID] > 0)
|
||||||
|
|
||||||
|
return segment
|
||||||
|
|
||||||
|
def test_reserve_segment_success_with_partial_segment(self):
|
||||||
|
with self.network() as network:
|
||||||
|
self._reserve_segment(network)
|
||||||
|
|
||||||
|
def test_reserve_segment_fail_with_duplicate_param(self):
|
||||||
|
with self.network() as network:
|
||||||
|
self._reserve_segment(network, 10)
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exc.VlanIdInUse, self._reserve_segment, network, 10)
|
||||||
|
|
||||||
|
def test_reserve_segment_update_network_mtu(self):
|
||||||
|
with self.network() as network:
|
||||||
|
network_id = network['network']['id']
|
||||||
|
with mock.patch.object(
|
||||||
|
self.driver, '_get_network_mtu') as mtu:
|
||||||
|
mtu.return_value = 100
|
||||||
|
self._reserve_segment(network)
|
||||||
|
updated_network = self.driver.get_network(self.context,
|
||||||
|
network_id)
|
||||||
|
self.assertEqual(100, updated_network[driver_api.MTU])
|
||||||
|
|
||||||
|
mtu.return_value = 200
|
||||||
|
self._reserve_segment(network)
|
||||||
|
updated_network = self.driver.get_network(self.context,
|
||||||
|
network_id)
|
||||||
|
self.assertEqual(200, updated_network[driver_api.MTU])
|
||||||
|
|
||||||
|
def _test_nofity_mechanism_manager(self, event):
|
||||||
|
seg1 = {driver_api.NETWORK_TYPE: 'vlan',
|
||||||
|
driver_api.PHYSICAL_NETWORK: self.physnet,
|
||||||
|
driver_api.SEGMENTATION_ID: 1000}
|
||||||
|
seg2 = {driver_api.NETWORK_TYPE: 'vlan',
|
||||||
|
driver_api.PHYSICAL_NETWORK: self.physnet,
|
||||||
|
driver_api.SEGMENTATION_ID: 1001}
|
||||||
|
seg3 = {driver_api.NETWORK_TYPE: 'vlan',
|
||||||
|
driver_api.PHYSICAL_NETWORK: self.physnet,
|
||||||
|
driver_api.SEGMENTATION_ID: 1002}
|
||||||
|
with self.network() as network:
|
||||||
|
network = network['network']
|
||||||
|
|
||||||
|
for stale_seg in segments_db.get_network_segments(self.context.session,
|
||||||
|
network['id']):
|
||||||
|
segments_db.delete_network_segment(self.context.session,
|
||||||
|
stale_seg['id'])
|
||||||
|
|
||||||
|
for seg in [seg1, seg2, seg3]:
|
||||||
|
seg['network_id'] = network['id']
|
||||||
|
segments_db.add_network_segment(self.context, network['id'], seg)
|
||||||
|
|
||||||
|
self.net_context = None
|
||||||
|
|
||||||
|
def record_network_context(net_context):
|
||||||
|
self.net_context = net_context
|
||||||
|
|
||||||
|
with mock.patch.object(managers.MechanismManager,
|
||||||
|
'update_network_precommit',
|
||||||
|
side_effect=record_network_context):
|
||||||
|
self.driver._handle_segment_change(
|
||||||
|
mock.ANY, event, segments_plugin.Plugin(), self.context, seg1)
|
||||||
|
# Make sure the mechanism manager can get the right amount of
|
||||||
|
# segments of network
|
||||||
|
self.assertEqual(3, len(self.net_context.current[mpnet.SEGMENTS]))
|
||||||
|
|
||||||
|
def test_reserve_segment_nofity_mechanism_manager(self):
|
||||||
|
self._test_nofity_mechanism_manager(events.PRECOMMIT_CREATE)
|
||||||
|
|
||||||
|
def test_release_segment(self):
|
||||||
|
with self.network() as network:
|
||||||
|
segment = self._reserve_segment(network, 10)
|
||||||
|
segment['network_id'] = network['network']['id']
|
||||||
|
self.driver._handle_segment_change(
|
||||||
|
mock.ANY, events.PRECOMMIT_DELETE, mock.ANY,
|
||||||
|
self.context, segment)
|
||||||
|
# Check that the segment_id is not reserved
|
||||||
|
segment = self._reserve_segment(
|
||||||
|
network, segment[driver_api.SEGMENTATION_ID])
|
||||||
|
|
||||||
|
def test_release_segment_nofity_mechanism_manager(self):
|
||||||
|
self._test_nofity_mechanism_manager(events.PRECOMMIT_DELETE)
|
||||||
|
|
||||||
|
def test_prevent_delete_segment_with_tenant_port(self):
|
||||||
|
fake_owner_compute = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'fake'
|
||||||
|
ml2_db.subscribe()
|
||||||
|
plugin = manager.NeutronManager.get_plugin()
|
||||||
|
with self.port(device_owner=fake_owner_compute) as port:
|
||||||
|
binding = ml2_db.get_locked_port_and_binding(self.context.session,
|
||||||
|
port['port']['id'])[1]
|
||||||
|
binding['host'] = 'host-ovs-no_filter'
|
||||||
|
mech_context = driver_context.PortContext(
|
||||||
|
plugin, self.context, port['port'],
|
||||||
|
plugin.get_network(self.context, port['port']['network_id']),
|
||||||
|
binding, None)
|
||||||
|
plugin._bind_port_if_needed(mech_context)
|
||||||
|
segment = segments_db.get_network_segments(
|
||||||
|
self.context.session, port['port']['network_id'])[0]
|
||||||
|
segment['network_id'] = port['port']['network_id']
|
||||||
|
self.assertRaises(c_exc.CallbackFailure, registry.notify,
|
||||||
|
resources.SEGMENT, events.BEFORE_DELETE,
|
||||||
|
mock.ANY,
|
||||||
|
context=self.context, segment=segment)
|
||||||
|
exist_port = self._show('ports', port['port']['id'])
|
||||||
|
self.assertEqual(port['port']['id'], exist_port['port']['id'])
|
||||||
|
@ -298,8 +298,7 @@ class TestAutoScheduleSegments(test_plugin.Ml2PluginV2TestCase,
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestAutoScheduleSegments, self).setUp()
|
super(TestAutoScheduleSegments, self).setUp()
|
||||||
self.plugin = importutils.import_object('neutron.plugins.ml2.plugin.'
|
self.plugin = self.driver
|
||||||
'Ml2Plugin')
|
|
||||||
self.segments_plugin = importutils.import_object(
|
self.segments_plugin = importutils.import_object(
|
||||||
'neutron.services.segments.plugin.Plugin')
|
'neutron.services.segments.plugin.Plugin')
|
||||||
self.ctx = context.get_admin_context()
|
self.ctx = context.get_admin_context()
|
||||||
@ -317,8 +316,8 @@ class TestAutoScheduleSegments(test_plugin.Ml2PluginV2TestCase,
|
|||||||
seg = self.segments_plugin.create_segment(
|
seg = self.segments_plugin.create_segment(
|
||||||
self.ctx,
|
self.ctx,
|
||||||
{'segment': {'network_id': network_id,
|
{'segment': {'network_id': network_id,
|
||||||
'physical_network': constants.ATTR_NOT_SPECIFIED,
|
'physical_network': 'physnet1',
|
||||||
'network_type': 'meh',
|
'network_type': 'vlan',
|
||||||
'segmentation_id': constants.ATTR_NOT_SPECIFIED}})
|
'segmentation_id': constants.ATTR_NOT_SPECIFIED}})
|
||||||
return seg['id']
|
return seg['id']
|
||||||
|
|
||||||
@ -506,8 +505,7 @@ class DHCPAgentWeightSchedulerTestCase(test_plugin.Ml2PluginV2TestCase):
|
|||||||
weight_scheduler = (
|
weight_scheduler = (
|
||||||
'neutron.scheduler.dhcp_agent_scheduler.WeightScheduler')
|
'neutron.scheduler.dhcp_agent_scheduler.WeightScheduler')
|
||||||
cfg.CONF.set_override('network_scheduler_driver', weight_scheduler)
|
cfg.CONF.set_override('network_scheduler_driver', weight_scheduler)
|
||||||
self.plugin = importutils.import_object('neutron.plugins.ml2.plugin.'
|
self.plugin = self.driver
|
||||||
'Ml2Plugin')
|
|
||||||
mock.patch.object(
|
mock.patch.object(
|
||||||
self.plugin, 'filter_hosts_with_network_access',
|
self.plugin, 'filter_hosts_with_network_access',
|
||||||
side_effect=lambda context, network_id, hosts: hosts).start()
|
side_effect=lambda context, network_id, hosts: hosts).start()
|
||||||
@ -531,8 +529,8 @@ class DHCPAgentWeightSchedulerTestCase(test_plugin.Ml2PluginV2TestCase):
|
|||||||
seg = self.segments_plugin.create_segment(
|
seg = self.segments_plugin.create_segment(
|
||||||
self.ctx,
|
self.ctx,
|
||||||
{'segment': {'network_id': network_id,
|
{'segment': {'network_id': network_id,
|
||||||
'physical_network': constants.ATTR_NOT_SPECIFIED,
|
'physical_network': 'physnet1',
|
||||||
'network_type': 'meh',
|
'network_type': 'vlan',
|
||||||
'segmentation_id': constants.ATTR_NOT_SPECIFIED}})
|
'segmentation_id': constants.ATTR_NOT_SPECIFIED}})
|
||||||
return seg['id']
|
return seg['id']
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user