Skip to content

Commit bd3db31

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "get_hosts_mapped_with_segments add filter agt_type" into stable/yoga
2 parents fe80262 + 6e3cbee commit bd3db31

File tree

2 files changed

+174
-3
lines changed

2 files changed

+174
-3
lines changed

neutron/services/segments/db.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
from oslo_log import helpers as log_helpers
3131
from oslo_utils import uuidutils
3232

33+
from neutron.db.models import agent as agent_model
34+
from neutron.db.models import segment as segment_model
3335
from neutron.db import segments_db as db
3436
from neutron import manager
3537
from neutron.objects import base as base_obj
@@ -237,14 +239,43 @@ def update_segment_host_mapping(context, host, current_segment_ids):
237239
entry.delete()
238240

239241

240-
def get_hosts_mapped_with_segments(context):
242+
def get_hosts_mapped_with_segments(context, include_agent_types=None,
243+
exclude_agent_types=None):
241244
"""Get hosts that are mapped with segments.
242245
243246
L2 providers can use this method to get an overview of SegmentHostMapping,
244247
and then delete the stale SegmentHostMapping.
248+
249+
When using both include_agent_types and exclude_agent_types,
250+
exclude_agent_types is most significant.
251+
All hosts without agent are excluded when using any agent_type filter.
252+
253+
:param context: current running context information
254+
:param include_agent_types: (set) List of agent types, include hosts
255+
with matching agents.
256+
:param exclude_agent_types: (set) List of agent types, exclude hosts
257+
with matching agents.
245258
"""
246-
segment_host_mapping = network.SegmentHostMapping.get_objects(context)
247-
return {row.host for row in segment_host_mapping}
259+
def add_filter_by_agent_types(qry, include, exclude):
260+
qry = qry.join(
261+
agent_model.Agent,
262+
segment_model.SegmentHostMapping.host == agent_model.Agent.host)
263+
if include:
264+
qry = qry.filter(agent_model.Agent.agent_type.in_(include))
265+
if exclude:
266+
qry = qry.filter(agent_model.Agent.agent_type.not_in(exclude))
267+
268+
return qry
269+
270+
with db_api.CONTEXT_READER.using(context):
271+
query = context.session.query(segment_model.SegmentHostMapping)
272+
if include_agent_types or exclude_agent_types:
273+
query = add_filter_by_agent_types(query, include_agent_types,
274+
exclude_agent_types)
275+
276+
res = query.all()
277+
278+
return {row.host for row in res}
248279

249280

250281
def _get_phys_nets(agent):

neutron/tests/unit/extensions/test_segment.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,10 +746,37 @@ def test_get_all_hosts_mapped_with_segments(self):
746746
actual_hosts = db.get_hosts_mapped_with_segments(ctx)
747747
self.assertEqual(hosts, actual_hosts)
748748

749+
def test_get_all_hosts_mapped_with_segments_agent_type_filter(self):
750+
ctx = context.get_admin_context()
751+
hosts = set()
752+
with self.network() as network:
753+
network_id = network['network']['id']
754+
for i in range(1, 3):
755+
host = "host%s" % i
756+
segment = self._test_create_segment(
757+
network_id=network_id, physical_network='physnet%s' % i,
758+
segmentation_id=200 + i, network_type=constants.TYPE_VLAN)
759+
db.update_segment_host_mapping(
760+
ctx, host, {segment['segment']['id']})
761+
hosts.add(host)
762+
763+
# Now they are 2 hosts with segment being mapped.
764+
# host1 does not have an agent
765+
# host2 does not have an agent
766+
# Any agent_type filter excludes hosts that does not have an agent
767+
actual_hosts = db.get_hosts_mapped_with_segments(
768+
ctx, exclude_agent_types={'fake-agent-type'})
769+
self.assertEqual(set(), actual_hosts)
770+
actual_hosts = db.get_hosts_mapped_with_segments(
771+
ctx, include_agent_types={'fake-agent-type'})
772+
self.assertEqual(set(), actual_hosts)
773+
749774

750775
class TestMl2HostSegmentMappingOVS(HostSegmentMappingTestCase):
751776
_mechanism_drivers = ['openvswitch', 'logger']
752777
mock_path = 'neutron.services.segments.db.update_segment_host_mapping'
778+
agent_type_a = constants.AGENT_TYPE_OVS
779+
agent_type_b = constants.AGENT_TYPE_LINUXBRIDGE
753780

754781
def test_new_agent(self):
755782
host = 'host1'
@@ -869,9 +896,118 @@ def test_agent_with_no_mappings(self, mock):
869896
self.assertFalse(segments_host_db)
870897
self.assertFalse(mock.mock_calls)
871898

899+
def test_get_all_hosts_mapped_with_segments(self):
900+
ctx = context.get_admin_context()
901+
hosts = set()
902+
with self.network() as network:
903+
network_id = network['network']['id']
904+
for i in range(1, 3):
905+
host = "host%s" % i
906+
segment = self._test_create_segment(
907+
network_id=network_id, physical_network='physnet%s' % i,
908+
segmentation_id=200 + i, network_type=constants.TYPE_VLAN)
909+
self._register_agent(host, mappings={'physnet%s' % i: 'br-eth-1'},
910+
plugin=self.plugin)
911+
db.update_segment_host_mapping(
912+
ctx, host, {segment['segment']['id']})
913+
hosts.add(host)
914+
915+
# Now they are 2 hosts with segment being mapped.
916+
actual_hosts = db.get_hosts_mapped_with_segments(ctx)
917+
self.assertEqual(hosts, actual_hosts)
918+
919+
def test_get_all_hosts_mapped_with_segments_agent_type_filters(self):
920+
ctx = context.get_admin_context()
921+
with self.network() as network:
922+
network_id = network['network']['id']
923+
for i in range(1, 3):
924+
host = "host%s" % i
925+
segment = self._test_create_segment(
926+
network_id=network_id, physical_network='physnet%s' % i,
927+
segmentation_id=200 + i, network_type=constants.TYPE_VLAN)
928+
if i == 2:
929+
agent_type = self.agent_type_a
930+
else:
931+
agent_type = self.agent_type_b
932+
helpers.register_ovs_agent(
933+
host, agent_type=agent_type,
934+
bridge_mappings={'physnet%s' % i: 'br-eth-1'},
935+
plugin=self.plugin, start_flag=True)
936+
db.update_segment_host_mapping(
937+
ctx, host, {segment['segment']['id']})
938+
939+
# Now they are 2 hosts with segment being mapped.
940+
# host1 is agent_type_b
941+
# host2 is agent_type_a
942+
# get all hosts (host1 and host2) when not using any filtering
943+
actual_hosts = db.get_hosts_mapped_with_segments(ctx)
944+
self.assertEqual({"host1", "host2"}, actual_hosts)
945+
# get host1 when exclude agent_type_a agents
946+
actual_hosts = db.get_hosts_mapped_with_segments(
947+
ctx, exclude_agent_types={self.agent_type_a})
948+
self.assertEqual({"host1"}, actual_hosts)
949+
# get host2 when exclude agent_type_b agents
950+
actual_hosts = db.get_hosts_mapped_with_segments(
951+
ctx, exclude_agent_types={self.agent_type_b})
952+
self.assertEqual({"host2"}, actual_hosts)
953+
# get host2 when include agent_type_a agents
954+
actual_hosts = db.get_hosts_mapped_with_segments(
955+
ctx, include_agent_types={self.agent_type_a})
956+
self.assertEqual({"host2"}, actual_hosts)
957+
# get host1 when include agent_type_b agents
958+
actual_hosts = db.get_hosts_mapped_with_segments(
959+
ctx, include_agent_types={self.agent_type_b})
960+
self.assertEqual({"host1"}, actual_hosts)
961+
# get host1 and host2 when include both agent_type_a and agent_type_b
962+
actual_hosts = db.get_hosts_mapped_with_segments(
963+
ctx, include_agent_types={self.agent_type_b, self.agent_type_a})
964+
self.assertEqual({"host1", "host2"}, actual_hosts)
965+
# When using both include and exclude, exclude is most significant
966+
actual_hosts = db.get_hosts_mapped_with_segments(
967+
ctx,
968+
include_agent_types={self.agent_type_b, self.agent_type_a},
969+
exclude_agent_types={self.agent_type_b}
970+
)
971+
self.assertEqual({"host2"}, actual_hosts)
972+
# include and exclude both agent types - exclude is most significant
973+
actual_hosts = db.get_hosts_mapped_with_segments(
974+
ctx,
975+
include_agent_types={self.agent_type_b, self.agent_type_a},
976+
exclude_agent_types={self.agent_type_b, self.agent_type_a}
977+
)
978+
self.assertEqual(set(), actual_hosts)
979+
980+
def test_get_all_hosts_mapped_with_segments_agent_type_filter(self):
981+
ctx = context.get_admin_context()
982+
hosts = set()
983+
with self.network() as network:
984+
network_id = network['network']['id']
985+
for i in range(1, 3):
986+
host = "host%s" % i
987+
segment = self._test_create_segment(
988+
network_id=network_id, physical_network='physnet%s' % i,
989+
segmentation_id=200 + i, network_type=constants.TYPE_VLAN)
990+
self._register_agent(host, mappings={'physnet%s' % i: 'br-eth-1'},
991+
plugin=self.plugin)
992+
db.update_segment_host_mapping(
993+
ctx, host, {segment['segment']['id']})
994+
hosts.add(host)
995+
996+
# Now they are 2 hosts with segment being mapped.
997+
# host1 is agent_type_a
998+
# host2 is agent_type_a
999+
actual_hosts = db.get_hosts_mapped_with_segments(
1000+
ctx, exclude_agent_types={self.agent_type_a})
1001+
self.assertEqual(set(), actual_hosts)
1002+
actual_hosts = db.get_hosts_mapped_with_segments(
1003+
ctx, include_agent_types={self.agent_type_a})
1004+
self.assertEqual(hosts, actual_hosts)
1005+
8721006

8731007
class TestMl2HostSegmentMappingLinuxBridge(TestMl2HostSegmentMappingOVS):
8741008
_mechanism_drivers = ['linuxbridge', 'logger']
1009+
agent_type_a = constants.AGENT_TYPE_LINUXBRIDGE
1010+
agent_type_b = constants.AGENT_TYPE_OVS
8751011

8761012
def _register_agent(self, host, mappings=None, plugin=None):
8771013
helpers.register_linuxbridge_agent(host=host,
@@ -881,6 +1017,8 @@ def _register_agent(self, host, mappings=None, plugin=None):
8811017

8821018
class TestMl2HostSegmentMappingMacvtap(TestMl2HostSegmentMappingOVS):
8831019
_mechanism_drivers = ['macvtap', 'logger']
1020+
agent_type_a = constants.AGENT_TYPE_MACVTAP
1021+
agent_type_b = constants.AGENT_TYPE_OVS
8841022

8851023
def _register_agent(self, host, mappings=None, plugin=None):
8861024
helpers.register_macvtap_agent(host=host, interface_mappings=mappings,
@@ -889,6 +1027,8 @@ def _register_agent(self, host, mappings=None, plugin=None):
8891027

8901028
class TestMl2HostSegmentMappingSriovNicSwitch(TestMl2HostSegmentMappingOVS):
8911029
_mechanism_drivers = ['sriovnicswitch', 'logger']
1030+
agent_type_a = constants.AGENT_TYPE_NIC_SWITCH
1031+
agent_type_b = constants.AGENT_TYPE_OVS
8921032

8931033
def _register_agent(self, host, mappings=None, plugin=None):
8941034
helpers.register_sriovnicswitch_agent(host=host,

0 commit comments

Comments
 (0)