diff --git a/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py b/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py index 042aac5b4d..a814895b75 100755 --- a/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py +++ b/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py @@ -199,13 +199,24 @@ class OVSQuantumAgent(object): def port_update(self, context, **kwargs): LOG.debug(_("port_update received")) port = kwargs.get('port') + # Validate that port is on OVS + vif_port = self.int_br.get_vif_port_by_id(port['id']) + if not vif_port: + return network_type = kwargs.get('network_type') segmentation_id = kwargs.get('segmentation_id') physical_network = kwargs.get('physical_network') - vif_port = self.int_br.get_vif_port_by_id(port['id']) self.treat_vif_port(vif_port, port['id'], port['network_id'], network_type, physical_network, segmentation_id, port['admin_state_up']) + if port['admin_state_up']: + # update plugin about port status + self.plugin_rpc.update_device_up(self.context, port['id'], + self.agent_id) + else: + # update plugin about port status + self.agent.plugin_rpc.update_device_down(self.context, port['id'], + self.agent.agent_id) def tunnel_update(self, context, **kwargs): LOG.debug(_("tunnel_update received")) diff --git a/quantum/plugins/openvswitch/ovs_quantum_plugin.py b/quantum/plugins/openvswitch/ovs_quantum_plugin.py index 23b3a4cbc5..9045f7bbdc 100644 --- a/quantum/plugins/openvswitch/ovs_quantum_plugin.py +++ b/quantum/plugins/openvswitch/ovs_quantum_plugin.py @@ -81,8 +81,10 @@ class OVSRpcCallbacks(dhcp_rpc_base.DhcpRpcCallbackMixin, 'network_type': binding.network_type, 'segmentation_id': binding.segmentation_id, 'physical_network': binding.physical_network} - # Set the port status to UP - ovs_db_v2.set_port_status(port['id'], q_const.PORT_STATUS_ACTIVE) + new_status = (q_const.PORT_STATUS_ACTIVE if port['admin_state_up'] + else q_const.PORT_STATUS_DOWN) + if port['status'] != new_status: + ovs_db_v2.set_port_status(port['id'], new_status) else: entry = {'device': device} LOG.debug(_("%s can not be found in database"), device) @@ -99,14 +101,29 @@ class OVSRpcCallbacks(dhcp_rpc_base.DhcpRpcCallbackMixin, if port: entry = {'device': device, 'exists': True} - # Set port status to DOWN - ovs_db_v2.set_port_status(port['id'], q_const.PORT_STATUS_DOWN) + if port['status'] != q_const.PORT_STATUS_DOWN: + # Set port status to DOWN + ovs_db_v2.set_port_status(port['id'], q_const.PORT_STATUS_DOWN) else: entry = {'device': device, 'exists': False} LOG.debug(_("%s can not be found in database"), device) return entry + def update_device_up(self, rpc_context, **kwargs): + """Device is up on agent""" + agent_id = kwargs.get('agent_id') + device = kwargs.get('device') + LOG.debug(_("Device %(device)s up on %(agent_id)s"), + locals()) + port = ovs_db_v2.get_port(device) + if port: + if port['status'] != q_const.PORT_STATUS_ACTIVE: + ovs_db_v2.set_port_status(port['id'], + q_const.PORT_STATUS_ACTIVE) + else: + LOG.debug(_("%s can not be found in database"), device) + def tunnel_sync(self, rpc_context, **kwargs): """Update new tunnel. @@ -502,6 +519,8 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2, return port def create_port(self, context, port): + # Set port status as 'DOWN'. This will be updated by agent + port['port']['status'] = q_const.PORT_STATUS_DOWN port = super(OVSQuantumPluginV2, self).create_port(context, port) return self._extend_port_dict_binding(context, port) diff --git a/quantum/tests/unit/cisco/test_network_plugin.py b/quantum/tests/unit/cisco/test_network_plugin.py index 44416f0a3a..d670bea989 100644 --- a/quantum/tests/unit/cisco/test_network_plugin.py +++ b/quantum/tests/unit/cisco/test_network_plugin.py @@ -38,6 +38,7 @@ class CiscoNetworkPluginV2TestCase(test_db_plugin.QuantumDbPluginV2TestCase): with mock.patch.object(network_db_v2, 'initialize', new=new_init): super(CiscoNetworkPluginV2TestCase, self).setUp(self._plugin_name) + self.port_create_status = 'DOWN' def _get_plugin_ref(self): plugin_obj = QuantumManager.get_plugin() diff --git a/quantum/tests/unit/openvswitch/test_openvswitch_plugin.py b/quantum/tests/unit/openvswitch/test_openvswitch_plugin.py index d7244b53f8..9ce64e0edb 100644 --- a/quantum/tests/unit/openvswitch/test_openvswitch_plugin.py +++ b/quantum/tests/unit/openvswitch/test_openvswitch_plugin.py @@ -25,6 +25,7 @@ class OpenvswitchPluginV2TestCase(test_plugin.QuantumDbPluginV2TestCase): def setUp(self): super(OpenvswitchPluginV2TestCase, self).setUp(self._plugin_name) + self.port_create_status = 'DOWN' class TestOpenvswitchBasicGet(test_plugin.TestBasicGet, @@ -44,6 +45,11 @@ class TestOpenvswitchPortsV2(test_plugin.TestPortsV2, VIF_TYPE = portbindings.VIF_TYPE_OVS HAS_PORT_FILTER = False + def test_update_port_status_build(self): + with self.port() as port: + self.assertEqual(port['port']['status'], 'DOWN') + self.assertEqual(self.port_create_status, 'DOWN') + class TestOpenvswitchNetworksV2(test_plugin.TestNetworksV2, OpenvswitchPluginV2TestCase): diff --git a/quantum/tests/unit/openvswitch/test_ovs_rpcapi.py b/quantum/tests/unit/openvswitch/test_ovs_rpcapi.py index cc0f48a48c..fdb181ba5c 100644 --- a/quantum/tests/unit/openvswitch/test_ovs_rpcapi.py +++ b/quantum/tests/unit/openvswitch/test_ovs_rpcapi.py @@ -108,3 +108,10 @@ class rpcApiTestCase(unittest2.TestCase): self._test_ovs_api(rpcapi, topics.PLUGIN, 'tunnel_sync', rpc_method='call', tunnel_ip='fake_tunnel_ip') + + def test_update_device_up(self): + rpcapi = agent_rpc.PluginApi(topics.PLUGIN) + self._test_ovs_api(rpcapi, topics.PLUGIN, + 'update_device_up', rpc_method='call', + device='fake_device', + agent_id='fake_agent_id')