support admin-state of port

bind_port only when it's in admin_state_up
unbind it when it's admin_state_down

Change-Id: I1f336e397d9cd61cd294a655498f202a859d1e9c
Closes-Bug: #1568739
This commit is contained in:
Eyal Leshem 2017-10-01 11:55:23 +03:00
parent 0a18338d95
commit e05d715d2b
3 changed files with 74 additions and 10 deletions

View File

@ -20,6 +20,36 @@ from dragonflow.db.models import l2
LOG = log.getLogger(__name__)
def _port_update_unbind(lport, orig_lport):
# wasn't bounded any way
if orig_lport.enabled is False:
return
# port moved between chassis or admin disabled
if (orig_lport.is_local != lport.is_local
or orig_lport.is_remote != lport.is_remote
or lport.enabled is False):
if orig_lport.is_local:
orig_lport.emit_unbind_local()
elif orig_lport.is_remote:
orig_lport.emit_unbind_remote()
def _port_update_bind(lport, orig_lport):
# not needed to be bound
if lport.enabled is False:
return
# port moved between chassis or admin enabled
if (orig_lport.is_local != lport.is_local
or orig_lport.is_remote != lport.is_remote
or orig_lport.enabled is False):
if lport.is_local:
lport.emit_bind_local()
elif lport.is_remote:
lport.emit_bind_remote()
class PortBindingApp(df_base_app.DFlowApp):
def __init__(self, *args, **kwargs):
super(PortBindingApp, self).__init__(*args, **kwargs)
@ -32,6 +62,10 @@ class PortBindingApp(df_base_app.DFlowApp):
@df_base_app.register_event(l2.LogicalPort, model_constants.EVENT_CREATED)
def _port_created(self, lport):
if lport.enabled is False:
return
if lport.is_local:
lport.emit_bind_local()
elif lport.is_remote:
@ -39,25 +73,22 @@ class PortBindingApp(df_base_app.DFlowApp):
@df_base_app.register_event(l2.LogicalPort, model_constants.EVENT_UPDATED)
def _port_updated(self, lport, orig_lport):
# unbind
if orig_lport.is_local and not lport.is_local:
orig_lport.emit_unbind_local()
elif orig_lport.is_remote and not lport.is_remote:
orig_lport.emit_unbind_remote()
_port_update_unbind(lport, orig_lport)
if lport.id in self._local_ports:
lport.emit_local_updated(orig_lport)
elif lport.id in self._remote_ports:
lport.emit_remote_updated(orig_lport)
# bind
if lport.is_local and not orig_lport.is_local:
lport.emit_bind_local()
elif lport.is_remote and not orig_lport.is_remote:
lport.emit_bind_remote()
_port_update_bind(lport, orig_lport)
@df_base_app.register_event(l2.LogicalPort, model_constants.EVENT_DELETED)
def _port_deleted(self, lport):
if lport.enabled is False:
return
if lport.id in self._local_ports:
lport.emit_unbind_local()
elif lport.id in self._remote_ports:

View File

@ -204,6 +204,7 @@ def make_fake_port(id=None,
_lport_index += 1
fake_port = l2.LogicalPort(
enabled=enabled,
id=id,
topic=topic,
name=name,

View File

@ -110,3 +110,35 @@ class TestPortBindingApp(test_app_base.DFAppTestBase):
new_port.emit_updated(old_port)
_M[l2.EVENT_BIND_REMOTE].assert_called_once_with(new_port)
_M[l2.EVENT_REMOTE_UPDATED].assert_not_called()
def test_port_admin_state_create(self):
port = test_app_base.make_fake_local_port(id='id1', enabled=False)
port.emit_created()
_M[l2.EVENT_BIND_LOCAL].assert_not_called()
port2 = test_app_base.make_fake_local_port(id='id1', enabled=True)
port2.emit_created()
_M[l2.EVENT_BIND_LOCAL].assert_called_once_with(port2)
def test_port_admin_state_update(self):
old_port = test_app_base.make_fake_local_port(id='id1', enabled=False)
old_port.emit_created()
_M[l2.EVENT_BIND_LOCAL].reset_mock()
new_port = test_app_base.make_fake_local_port(id='id1', enabled=True)
new_port.emit_updated(old_port)
_M[l2.EVENT_BIND_LOCAL].assert_called_once_with(new_port)
_M[l2.EVENT_BIND_LOCAL].reset_mock()
old_port.emit_updated(new_port)
_M[l2.EVENT_BIND_LOCAL].assert_not_called()
def test_port_admin_state_delete(self):
port = test_app_base.make_fake_local_port(id='id1', enabled=False)
port2 = test_app_base.make_fake_local_port(id='id1', enabled=True)
port.emit_created()
port2.emit_created()
port.emit_deleted()
_M[l2.EVENT_UNBIND_LOCAL].assert_not_called()
port2.emit_deleted()
_M[l2.EVENT_UNBIND_LOCAL].assert_called_once_with(port2)