diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py index f28dd39b0ac..313d6465198 100644 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@ -237,6 +237,10 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, LOG.debug("Port %s had new provisioning blocks added so it " "will not transition to active.", port_id) return + if not port.admin_state_up: + LOG.debug("Port %s is administratively disabled so it will " + "not transition to active.", port_id) + return self.update_port_status(context, port_id, const.PORT_STATUS_ACTIVE) @log_helpers.log_method_call diff --git a/neutron/tests/unit/plugins/ml2/test_plugin.py b/neutron/tests/unit/plugins/ml2/test_plugin.py index 12eb39ea529..49d88ddd015 100644 --- a/neutron/tests/unit/plugins/ml2/test_plugin.py +++ b/neutron/tests/unit/plugins/ml2/test_plugin.py @@ -691,6 +691,19 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): self.assertIsNone(plugin._port_provisioned('port', 'evt', 'trigger', self.context, port_id)) + def test__port_provisioned_port_admin_state_down(self): + plugin = directory.get_plugin() + ups = mock.patch.object(plugin, 'update_port_status').start() + port_id = 'fake_port_id' + binding = mock.Mock(vif_type=portbindings.VIF_TYPE_OVS) + port = mock.Mock( + id=port_id, admin_state_up=False, port_binding=binding) + with mock.patch('neutron.plugins.ml2.plugin.db.get_port', + return_value=port): + plugin._port_provisioned('port', 'evt', 'trigger', + self.context, port_id) + self.assertFalse(ups.called) + def test_create_router_port_and_fail_create_postcommit(self): with mock.patch.object(managers.MechanismManager,