get_hosts_mapped_with_segments add filter agt_type
Extend the get_hosts_mapped_with_segments method to add optional filters to include/exclude based on agent type. Uses a joined query, when both include and exclude filtering is used togheter the exclude filter is most significant. Partial-Bug: #2040172 Change-Id: I2cfd52a2657fad989e24e974fda470ecd960262b Signed-off-by: Harald Jensås <hjensas@redhat.com>
This commit is contained in:
parent
f185379980
commit
64b5787c32
|
@ -31,6 +31,8 @@ from oslo_log import helpers as log_helpers
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
|
from neutron.db.models import agent as agent_model
|
||||||
|
from neutron.db.models import segment as segment_model
|
||||||
from neutron.db import segments_db as db
|
from neutron.db import segments_db as db
|
||||||
from neutron import manager
|
from neutron import manager
|
||||||
from neutron.objects import base as base_obj
|
from neutron.objects import base as base_obj
|
||||||
|
@ -243,14 +245,43 @@ def update_segment_host_mapping(context, host, current_segment_ids):
|
||||||
entry.segment_id, entry.host)
|
entry.segment_id, entry.host)
|
||||||
|
|
||||||
|
|
||||||
def get_hosts_mapped_with_segments(context):
|
def get_hosts_mapped_with_segments(context, include_agent_types=None,
|
||||||
|
exclude_agent_types=None):
|
||||||
"""Get hosts that are mapped with segments.
|
"""Get hosts that are mapped with segments.
|
||||||
|
|
||||||
L2 providers can use this method to get an overview of SegmentHostMapping,
|
L2 providers can use this method to get an overview of SegmentHostMapping,
|
||||||
and then delete the stale SegmentHostMapping.
|
and then delete the stale SegmentHostMapping.
|
||||||
|
|
||||||
|
When using both include_agent_types and exclude_agent_types,
|
||||||
|
exclude_agent_types is most significant.
|
||||||
|
All hosts without agent are excluded when using any agent_type filter.
|
||||||
|
|
||||||
|
:param context: current running context information
|
||||||
|
:param include_agent_types: (set) List of agent types, include hosts
|
||||||
|
with matching agents.
|
||||||
|
:param exclude_agent_types: (set) List of agent types, exclude hosts
|
||||||
|
with matching agents.
|
||||||
"""
|
"""
|
||||||
segment_host_mapping = network.SegmentHostMapping.get_objects(context)
|
def add_filter_by_agent_types(qry, include, exclude):
|
||||||
return {row.host for row in segment_host_mapping}
|
qry = qry.join(
|
||||||
|
agent_model.Agent,
|
||||||
|
segment_model.SegmentHostMapping.host == agent_model.Agent.host)
|
||||||
|
if include:
|
||||||
|
qry = qry.filter(agent_model.Agent.agent_type.in_(include))
|
||||||
|
if exclude:
|
||||||
|
qry = qry.filter(agent_model.Agent.agent_type.not_in(exclude))
|
||||||
|
|
||||||
|
return qry
|
||||||
|
|
||||||
|
with db_api.CONTEXT_READER.using(context):
|
||||||
|
query = context.session.query(segment_model.SegmentHostMapping)
|
||||||
|
if include_agent_types or exclude_agent_types:
|
||||||
|
query = add_filter_by_agent_types(query, include_agent_types,
|
||||||
|
exclude_agent_types)
|
||||||
|
|
||||||
|
res = query.all()
|
||||||
|
|
||||||
|
return {row.host for row in res}
|
||||||
|
|
||||||
|
|
||||||
def _get_phys_nets(agent):
|
def _get_phys_nets(agent):
|
||||||
|
|
|
@ -768,10 +768,37 @@ class TestMl2HostSegmentMappingNoAgent(HostSegmentMappingTestCase):
|
||||||
actual_hosts = db.get_hosts_mapped_with_segments(ctx)
|
actual_hosts = db.get_hosts_mapped_with_segments(ctx)
|
||||||
self.assertEqual(hosts, actual_hosts)
|
self.assertEqual(hosts, actual_hosts)
|
||||||
|
|
||||||
|
def test_get_all_hosts_mapped_with_segments_agent_type_filter(self):
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
hosts = set()
|
||||||
|
with self.network() as network:
|
||||||
|
network_id = network['network']['id']
|
||||||
|
for i in range(1, 3):
|
||||||
|
host = "host%s" % i
|
||||||
|
segment = self._test_create_segment(
|
||||||
|
network_id=network_id, physical_network='physnet%s' % i,
|
||||||
|
segmentation_id=200 + i, network_type=constants.TYPE_VLAN)
|
||||||
|
db.update_segment_host_mapping(
|
||||||
|
ctx, host, {segment['segment']['id']})
|
||||||
|
hosts.add(host)
|
||||||
|
|
||||||
|
# Now they are 2 hosts with segment being mapped.
|
||||||
|
# host1 does not have an agent
|
||||||
|
# host2 does not have an agent
|
||||||
|
# Any agent_type filter excludes hosts that does not have an agent
|
||||||
|
actual_hosts = db.get_hosts_mapped_with_segments(
|
||||||
|
ctx, exclude_agent_types={'fake-agent-type'})
|
||||||
|
self.assertEqual(set(), actual_hosts)
|
||||||
|
actual_hosts = db.get_hosts_mapped_with_segments(
|
||||||
|
ctx, include_agent_types={'fake-agent-type'})
|
||||||
|
self.assertEqual(set(), actual_hosts)
|
||||||
|
|
||||||
|
|
||||||
class TestMl2HostSegmentMappingOVS(HostSegmentMappingTestCase):
|
class TestMl2HostSegmentMappingOVS(HostSegmentMappingTestCase):
|
||||||
_mechanism_drivers = ['openvswitch', 'logger']
|
_mechanism_drivers = ['openvswitch', 'logger']
|
||||||
mock_path = 'neutron.services.segments.db.update_segment_host_mapping'
|
mock_path = 'neutron.services.segments.db.update_segment_host_mapping'
|
||||||
|
agent_type_a = constants.AGENT_TYPE_OVS
|
||||||
|
agent_type_b = constants.AGENT_TYPE_LINUXBRIDGE
|
||||||
|
|
||||||
def test_new_agent(self):
|
def test_new_agent(self):
|
||||||
host = 'host1'
|
host = 'host1'
|
||||||
|
@ -891,9 +918,118 @@ class TestMl2HostSegmentMappingOVS(HostSegmentMappingTestCase):
|
||||||
self.assertFalse(segments_host_db)
|
self.assertFalse(segments_host_db)
|
||||||
self.assertFalse(mock.mock_calls)
|
self.assertFalse(mock.mock_calls)
|
||||||
|
|
||||||
|
def test_get_all_hosts_mapped_with_segments(self):
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
hosts = set()
|
||||||
|
with self.network() as network:
|
||||||
|
network_id = network['network']['id']
|
||||||
|
for i in range(1, 3):
|
||||||
|
host = "host%s" % i
|
||||||
|
segment = self._test_create_segment(
|
||||||
|
network_id=network_id, physical_network='physnet%s' % i,
|
||||||
|
segmentation_id=200 + i, network_type=constants.TYPE_VLAN)
|
||||||
|
self._register_agent(host, mappings={'physnet%s' % i: 'br-eth-1'},
|
||||||
|
plugin=self.plugin)
|
||||||
|
db.update_segment_host_mapping(
|
||||||
|
ctx, host, {segment['segment']['id']})
|
||||||
|
hosts.add(host)
|
||||||
|
|
||||||
|
# Now they are 2 hosts with segment being mapped.
|
||||||
|
actual_hosts = db.get_hosts_mapped_with_segments(ctx)
|
||||||
|
self.assertEqual(hosts, actual_hosts)
|
||||||
|
|
||||||
|
def test_get_all_hosts_mapped_with_segments_agent_type_filters(self):
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
with self.network() as network:
|
||||||
|
network_id = network['network']['id']
|
||||||
|
for i in range(1, 3):
|
||||||
|
host = "host%s" % i
|
||||||
|
segment = self._test_create_segment(
|
||||||
|
network_id=network_id, physical_network='physnet%s' % i,
|
||||||
|
segmentation_id=200 + i, network_type=constants.TYPE_VLAN)
|
||||||
|
if i == 2:
|
||||||
|
agent_type = self.agent_type_a
|
||||||
|
else:
|
||||||
|
agent_type = self.agent_type_b
|
||||||
|
helpers.register_ovs_agent(
|
||||||
|
host, agent_type=agent_type,
|
||||||
|
bridge_mappings={'physnet%s' % i: 'br-eth-1'},
|
||||||
|
plugin=self.plugin, start_flag=True)
|
||||||
|
db.update_segment_host_mapping(
|
||||||
|
ctx, host, {segment['segment']['id']})
|
||||||
|
|
||||||
|
# Now they are 2 hosts with segment being mapped.
|
||||||
|
# host1 is agent_type_b
|
||||||
|
# host2 is agent_type_a
|
||||||
|
# get all hosts (host1 and host2) when not using any filtering
|
||||||
|
actual_hosts = db.get_hosts_mapped_with_segments(ctx)
|
||||||
|
self.assertEqual({"host1", "host2"}, actual_hosts)
|
||||||
|
# get host1 when exclude agent_type_a agents
|
||||||
|
actual_hosts = db.get_hosts_mapped_with_segments(
|
||||||
|
ctx, exclude_agent_types={self.agent_type_a})
|
||||||
|
self.assertEqual({"host1"}, actual_hosts)
|
||||||
|
# get host2 when exclude agent_type_b agents
|
||||||
|
actual_hosts = db.get_hosts_mapped_with_segments(
|
||||||
|
ctx, exclude_agent_types={self.agent_type_b})
|
||||||
|
self.assertEqual({"host2"}, actual_hosts)
|
||||||
|
# get host2 when include agent_type_a agents
|
||||||
|
actual_hosts = db.get_hosts_mapped_with_segments(
|
||||||
|
ctx, include_agent_types={self.agent_type_a})
|
||||||
|
self.assertEqual({"host2"}, actual_hosts)
|
||||||
|
# get host1 when include agent_type_b agents
|
||||||
|
actual_hosts = db.get_hosts_mapped_with_segments(
|
||||||
|
ctx, include_agent_types={self.agent_type_b})
|
||||||
|
self.assertEqual({"host1"}, actual_hosts)
|
||||||
|
# get host1 and host2 when include both agent_type_a and agent_type_b
|
||||||
|
actual_hosts = db.get_hosts_mapped_with_segments(
|
||||||
|
ctx, include_agent_types={self.agent_type_b, self.agent_type_a})
|
||||||
|
self.assertEqual({"host1", "host2"}, actual_hosts)
|
||||||
|
# When using both include and exclude, exclude is most significant
|
||||||
|
actual_hosts = db.get_hosts_mapped_with_segments(
|
||||||
|
ctx,
|
||||||
|
include_agent_types={self.agent_type_b, self.agent_type_a},
|
||||||
|
exclude_agent_types={self.agent_type_b}
|
||||||
|
)
|
||||||
|
self.assertEqual({"host2"}, actual_hosts)
|
||||||
|
# include and exclude both agent types - exclude is most significant
|
||||||
|
actual_hosts = db.get_hosts_mapped_with_segments(
|
||||||
|
ctx,
|
||||||
|
include_agent_types={self.agent_type_b, self.agent_type_a},
|
||||||
|
exclude_agent_types={self.agent_type_b, self.agent_type_a}
|
||||||
|
)
|
||||||
|
self.assertEqual(set(), actual_hosts)
|
||||||
|
|
||||||
|
def test_get_all_hosts_mapped_with_segments_agent_type_filter(self):
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
hosts = set()
|
||||||
|
with self.network() as network:
|
||||||
|
network_id = network['network']['id']
|
||||||
|
for i in range(1, 3):
|
||||||
|
host = "host%s" % i
|
||||||
|
segment = self._test_create_segment(
|
||||||
|
network_id=network_id, physical_network='physnet%s' % i,
|
||||||
|
segmentation_id=200 + i, network_type=constants.TYPE_VLAN)
|
||||||
|
self._register_agent(host, mappings={'physnet%s' % i: 'br-eth-1'},
|
||||||
|
plugin=self.plugin)
|
||||||
|
db.update_segment_host_mapping(
|
||||||
|
ctx, host, {segment['segment']['id']})
|
||||||
|
hosts.add(host)
|
||||||
|
|
||||||
|
# Now they are 2 hosts with segment being mapped.
|
||||||
|
# host1 is agent_type_a
|
||||||
|
# host2 is agent_type_a
|
||||||
|
actual_hosts = db.get_hosts_mapped_with_segments(
|
||||||
|
ctx, exclude_agent_types={self.agent_type_a})
|
||||||
|
self.assertEqual(set(), actual_hosts)
|
||||||
|
actual_hosts = db.get_hosts_mapped_with_segments(
|
||||||
|
ctx, include_agent_types={self.agent_type_a})
|
||||||
|
self.assertEqual(hosts, actual_hosts)
|
||||||
|
|
||||||
|
|
||||||
class TestMl2HostSegmentMappingLinuxBridge(TestMl2HostSegmentMappingOVS):
|
class TestMl2HostSegmentMappingLinuxBridge(TestMl2HostSegmentMappingOVS):
|
||||||
_mechanism_drivers = ['linuxbridge', 'logger']
|
_mechanism_drivers = ['linuxbridge', 'logger']
|
||||||
|
agent_type_a = constants.AGENT_TYPE_LINUXBRIDGE
|
||||||
|
agent_type_b = constants.AGENT_TYPE_OVS
|
||||||
|
|
||||||
def setUp(self, plugin=None):
|
def setUp(self, plugin=None):
|
||||||
cfg.CONF.set_override(c_experimental.EXPERIMENTAL_LINUXBRIDGE, True,
|
cfg.CONF.set_override(c_experimental.EXPERIMENTAL_LINUXBRIDGE, True,
|
||||||
|
@ -908,6 +1044,8 @@ class TestMl2HostSegmentMappingLinuxBridge(TestMl2HostSegmentMappingOVS):
|
||||||
|
|
||||||
class TestMl2HostSegmentMappingMacvtap(TestMl2HostSegmentMappingOVS):
|
class TestMl2HostSegmentMappingMacvtap(TestMl2HostSegmentMappingOVS):
|
||||||
_mechanism_drivers = ['macvtap', 'logger']
|
_mechanism_drivers = ['macvtap', 'logger']
|
||||||
|
agent_type_a = constants.AGENT_TYPE_MACVTAP
|
||||||
|
agent_type_b = constants.AGENT_TYPE_OVS
|
||||||
|
|
||||||
def _register_agent(self, host, mappings=None, plugin=None):
|
def _register_agent(self, host, mappings=None, plugin=None):
|
||||||
helpers.register_macvtap_agent(host=host, interface_mappings=mappings,
|
helpers.register_macvtap_agent(host=host, interface_mappings=mappings,
|
||||||
|
@ -916,6 +1054,8 @@ class TestMl2HostSegmentMappingMacvtap(TestMl2HostSegmentMappingOVS):
|
||||||
|
|
||||||
class TestMl2HostSegmentMappingSriovNicSwitch(TestMl2HostSegmentMappingOVS):
|
class TestMl2HostSegmentMappingSriovNicSwitch(TestMl2HostSegmentMappingOVS):
|
||||||
_mechanism_drivers = ['sriovnicswitch', 'logger']
|
_mechanism_drivers = ['sriovnicswitch', 'logger']
|
||||||
|
agent_type_a = constants.AGENT_TYPE_NIC_SWITCH
|
||||||
|
agent_type_b = constants.AGENT_TYPE_OVS
|
||||||
|
|
||||||
def _register_agent(self, host, mappings=None, plugin=None):
|
def _register_agent(self, host, mappings=None, plugin=None):
|
||||||
helpers.register_sriovnicswitch_agent(host=host,
|
helpers.register_sriovnicswitch_agent(host=host,
|
||||||
|
|
Loading…
Reference in New Issue