Skip to content

Commit

Permalink
Handle of multiple matching assignment rules. Add test cases.
Browse files Browse the repository at this point in the history
Change-Id: Ifd31127e7ca4751b852890c041592bb58ff25f6b
Closes-Bug: #1540777
CLoses-Bug: #1548771
  • Loading branch information
Deepinder Setia committed Feb 29, 2016
1 parent 8f7a47e commit 696c4cd
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 26 deletions.
11 changes: 10 additions & 1 deletion src/config/common/tests/test_utils.py
Expand Up @@ -88,6 +88,10 @@ def get_keyspace_properties(self, ks_name):
def create_column_family(self, *args, **kwargs):
pass

def drop_keyspace(self, ks_name):
if name in self._keyspaces:
self._keyspaces.remove(name)

class CassandraCFs(object):
_all_cfs = {}

Expand All @@ -102,7 +106,12 @@ def get_cf(cls, name):
# end get_cf

@classmethod
def reset(cls):
def reset(cls, cf_list=None):
if cf_list:
for name in cf_list:
if name in cls._all_cfs:
del cls._all_cfs[name]
return
cls._all_cfs = {}
# end CassandraCFs

Expand Down
34 changes: 19 additions & 15 deletions src/discovery/disc_server.py
Expand Up @@ -651,21 +651,17 @@ def match_subscriber(self, dsa_rule, sub):
return True, match_len
return False, 0

def match_publishers(self, dsa_rule, pubs):
def match_publishers(self, rule_list, pubs):
result = []
rule_pub = dsa_rule['publisher']

for pub in pubs:
# include publisher if rule not relevant
if rule_pub['ep_type'] != pub['ep_type']:
result.append(pub)
continue
match, mlen = self.match_dsa_rule_ep(rule_pub, pub)
if match:
result.append(pub)
for dsa_rule in rule_list:
ok, pfxlen = self.match_dsa_rule_ep(dsa_rule['publisher'], pub)
if ok:
result.append(pub)
return result

def apply_dsa_config(self, pubs, sub):
def apply_dsa_config(self, service_type, pubs, sub):
if len(pubs) == 0:
return pubs

Expand All @@ -675,23 +671,31 @@ def apply_dsa_config(self, pubs, sub):
# self.syslog('dsa: rules %s' % dsa_rules)

lpm = -1
matched_sub_rule = None
matched_rules = None
for rule in dsa_rules:
# ignore rule if publisher not relevant
if rule['publisher']['ep_type'] != service_type:
continue

# ignore rule if subscriber doesn't match
matched, matched_len = self.match_subscriber(rule, sub)
if not matched:
continue
self.syslog('dsa: matched sub %s' % sub)

# collect matched rules
if matched_len > lpm:
lpm = matched_len
matched_sub_rule = rule
matched_rules = [rule]
elif matched_len == lpm:
matched_rules.append(rule)
# end for

# return original list if there is no sub match
if not matched_sub_rule:
if not matched_rules:
return pubs

matched_pubs = self.match_publishers(matched_sub_rule, pubs)
matched_pubs = self.match_publishers(matched_rules, pubs)
self.syslog('dsa: matched pubs %s' % matched_pubs)

return matched_pubs
Expand Down Expand Up @@ -768,7 +772,7 @@ def api_subscribe(self):
# send short ttl if no publishers
pubs = self._db_conn.lookup_service(service_type, include_count=True) or []
pubs_active = [item for item in pubs if not self.service_expired(item)]
pubs_active = self.apply_dsa_config(pubs_active, cl_entry)
pubs_active = self.apply_dsa_config(service_type, pubs_active, cl_entry)
pubs_active = self.service_list(service_type, pubs_active)
plist = dict((entry['service_id'],entry) for entry in pubs_active)
plist_all = dict((entry['service_id'],entry) for entry in pubs)
Expand Down
2 changes: 1 addition & 1 deletion src/discovery/tests/test_case.py
Expand Up @@ -67,7 +67,7 @@ def setUp(self, extra_disc_server_config_knobs = None,


def tearDown(self):
test_utils.CassandraCFs.reset()
test_utils.CassandraCFs.reset(cf_list=['discovery'])
test_common.kill_disc_server(self._disc_server_greenlet)
super(DsTestCase, self).tearDown()

Expand Down
121 changes: 112 additions & 9 deletions src/discovery/tests/test_dsa.py
Expand Up @@ -68,6 +68,113 @@ def info_callback(info):

class TestDsa(test_case.DsTestCase):

def test_bug_1548771(self):
dsa = DiscoveryServiceAssignment()
rule_entry = build_dsa_rule_entry('77.77.3.0/24,xmpp-server 77.77.0.0/16,contrail-vrouter-agent:0')
rule_uuid = uuid.uuid4()
dsa_rule1 = DsaRule(name = str(rule_uuid), parent_obj = dsa, dsa_rule_entry = rule_entry)
dsa_rule1.set_uuid(str(rule_uuid))
self._vnc_lib.dsa_rule_create(dsa_rule1)

rule_entry = build_dsa_rule_entry('77.77.3.0/24,dns-server 77.77.3.11/32,contrail-vrouter-agent:0')
rule_uuid = uuid.uuid4()
dsa_rule2 = DsaRule(name = str(rule_uuid), parent_obj = dsa, dsa_rule_entry = rule_entry)
dsa_rule2.set_uuid(str(rule_uuid))
self._vnc_lib.dsa_rule_create(dsa_rule2)

puburl = '/publish'
suburl = "/subscribe"

# publish 3 control nodes and dns servers
for service_type in ['xmpp-server', 'dns-server']:
for ipaddr in ["77.77.1.10", "77.77.2.10", "77.77.3.10"]:
payload = {
service_type: { "ip-addr" : ipaddr, "port" : "1111" },
'service-type' : '%s' % service_type,
'service-id' : '%s-%s' % (service_type, ipaddr),
'remote-addr': ipaddr,
}
(code, msg) = self._http_post(puburl, json.dumps(payload))
self.assertEqual(code, 200)

# Verify all services are published.
(code, msg) = self._http_get('/services.json')
self.assertEqual(code, 200)
response = json.loads(msg)
self.assertEqual(len(response['services']), 6)

# verify all agents see only 1 xmpp-server (rule #1)
service_type = 'xmpp-server'
expectedpub_set = set(["xmpp-server-77.77.3.10"])
for ipaddr in ["77.77.1.11", "77.77.2.11", "77.77.3.11"]:
payload = {
'service' : '%s' % service_type,
'client' : '%s-%s' % (service_type, ipaddr),
'instances' : 2,
'client-type' : 'contrail-vrouter-agent:0',
'remote-addr' : ipaddr,
}
(code, msg) = self._http_post(suburl, json.dumps(payload))
self.assertEqual(code, 200)
response = json.loads(msg)
self.assertEqual(len(response[service_type]), 1)
receivedpub_set = set([svc['@publisher-id'] for svc in response[service_type]])
self.assertEqual(expectedpub_set == receivedpub_set, True)

self._vnc_lib.dsa_rule_delete(id = dsa_rule1.get_uuid())
self._vnc_lib.dsa_rule_delete(id = dsa_rule2.get_uuid())

def test_bug_1540777(self):
dsa = DiscoveryServiceAssignment()

rule_entry = build_dsa_rule_entry('77.77.3.10/32,pulkit-pub 77.77.3.11/32,pulkit-sub')
rule_uuid = uuid.uuid4()
dsa_rule1 = DsaRule(name = str(rule_uuid), parent_obj = dsa, dsa_rule_entry = rule_entry)
dsa_rule1.set_uuid(str(rule_uuid))
self._vnc_lib.dsa_rule_create(dsa_rule1)

rule_entry = build_dsa_rule_entry('77.77.2.10/32,pulkit-pub 77.77.3.11/32,pulkit-sub')
rule_uuid = uuid.uuid4()
dsa_rule2 = DsaRule(name = str(rule_uuid), parent_obj = dsa, dsa_rule_entry = rule_entry)
dsa_rule2.set_uuid(str(rule_uuid))
self._vnc_lib.dsa_rule_create(dsa_rule2)

puburl = '/publish'
suburl = "/subscribe"
service_type = 'pulkit-pub'

# publish 3 control nodes - 2 subject to rules above
for ipaddr in ["77.77.1.10", "77.77.2.10", "77.77.3.10"]:
payload = {
service_type: { "ip-addr" : ipaddr, "port" : "1111" },
'service-type' : '%s' % service_type,
'service-id' : 'pulkit-pub-%s' % ipaddr,
'remote-addr': ipaddr,
}
(code, msg) = self._http_post(puburl, json.dumps(payload))
self.assertEqual(code, 200)

payload = {
'service' : '%s' % service_type,
'client' : 'discovery-ut',
'instances' : 3,
'client-type' : 'pulkit-sub',
'remote-addr' : '77.77.3.11',
}

# should see 2 publishers due to two rules
(code, msg) = self._http_post(suburl, json.dumps(payload))
self.assertEqual(code, 200)
response = json.loads(msg)
self.assertEqual(len(response[service_type]), 2)

expectedpub_set = set(["pulkit-pub-77.77.2.10", "pulkit-pub-77.77.3.10"])
receivedpub_set = set([svc['@publisher-id'] for svc in response[service_type]])
self.assertEqual(expectedpub_set == receivedpub_set, True)

self._vnc_lib.dsa_rule_delete(id = dsa_rule1.get_uuid())
self._vnc_lib.dsa_rule_delete(id = dsa_rule2.get_uuid())

def test_dsa_config(self):
# Assign DC1 control nodes to DC1 agents
rule_entry = build_dsa_rule_entry('1.1.1.0/24,Control-Node 1.1.1.0/24,Vrouter-Agent')
Expand Down Expand Up @@ -167,11 +274,9 @@ def test_dsa_config(self):
for svc in response[service_type]:
self.assertEqual("DC2-CN" in svc['@publisher-id'], True)

"""
Subscribe to IfmapServer from DC1, DC2 and DC3. There are no
assignment rules applicable to IfmapServer. Thus clients from
all DC should be able to subscribe to singtleton IfmapServer
"""
# Subscribe to IfmapServer from DC1, DC2 and DC3. There are no
# assignment rules applicable to IfmapServer. Thus clients from
# all DC should be able to subscribe to singtleton IfmapServer
service_type = 'IfmapServer'
payload = {
service_type: { "ip-addr" : "4.4.4.4", "port" : "4444" },
Expand All @@ -195,10 +300,8 @@ def test_dsa_config(self):
response = json.loads(msg)
self.assertEqual(len(response[service_type]), 1)

"""
Delete service assignment rule.
Subs from any DC should see all DC1+DC2 services
"""
# Delete service assignment rule.
# Subs from any DC should see all DC1+DC2 services
self._vnc_lib.dsa_rule_delete(id = dsa_rule1.uuid)
self._vnc_lib.dsa_rule_delete(id = dsa_rule2.uuid)

Expand Down

0 comments on commit 696c4cd

Please sign in to comment.