Add OVS cleanup utility
Fixes bug 1091605 The utility should be called after rebooting an appliance. This will purge the openvswicth of configured tap devices. A configuration variable quantum_ports has been added. This is by default True which indicates that only Quantum ports will be deleted from the OVS. If this is set as False then all ports on the bridge will be deleted. Change-Id: I442f64cf82f95bfa99d7765eb09db1ce2ecf602e
This commit is contained in:
parent
ca8ed5eee6
commit
767859ddb9
26
bin/quantum-ovs-cleanup
Executable file
26
bin/quantum-ovs-cleanup
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright (c) 2012 Openstack, LLC.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, os.getcwd())
|
||||||
|
|
||||||
|
from quantum.agent.ovs_cleanup_util import main
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
@ -271,6 +271,15 @@ class OVSBridge:
|
|||||||
LOG.info(_("Unable to parse regex results. Exception: %s"), e)
|
LOG.info(_("Unable to parse regex results. Exception: %s"), e)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def delete_ports(self, all_ports=False):
|
||||||
|
if all_ports:
|
||||||
|
port_names = self.get_port_name_list()
|
||||||
|
else:
|
||||||
|
port_names = (port.port_name for port in self.get_vif_ports())
|
||||||
|
|
||||||
|
for port_name in port_names:
|
||||||
|
self.delete_port(port_name)
|
||||||
|
|
||||||
|
|
||||||
def get_bridge_for_iface(root_helper, iface):
|
def get_bridge_for_iface(root_helper, iface):
|
||||||
args = ["ovs-vsctl", "--timeout=2", "iface-to-br", iface]
|
args = ["ovs-vsctl", "--timeout=2", "iface-to-br", iface]
|
||||||
@ -279,3 +288,12 @@ def get_bridge_for_iface(root_helper, iface):
|
|||||||
except Exception, e:
|
except Exception, e:
|
||||||
LOG.error(_("iface %s not found. Exception: %s"), iface, e)
|
LOG.error(_("iface %s not found. Exception: %s"), iface, e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_bridges(root_helper):
|
||||||
|
args = ["ovs-vsctl", "--timeout=2", "list-br"]
|
||||||
|
try:
|
||||||
|
return utils.execute(args, root_helper=root_helper).strip().split("\n")
|
||||||
|
except Exception, e:
|
||||||
|
LOG.error(_("Unable to retrieve bridges. Exception: %s"), e)
|
||||||
|
return []
|
||||||
|
75
quantum/agent/ovs_cleanup_util.py
Normal file
75
quantum/agent/ovs_cleanup_util.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright (c) 2012 OpenStack LLC.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from quantum.agent import l3_agent
|
||||||
|
from quantum.agent.linux import interface
|
||||||
|
from quantum.agent.linux import ovs_lib
|
||||||
|
from quantum.common import config
|
||||||
|
from quantum.openstack.common import cfg
|
||||||
|
from quantum.openstack.common import log as logging
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_conf():
|
||||||
|
"""Setup the cfg for the clean up utility.
|
||||||
|
|
||||||
|
Use separate setup_conf for the utility because there are many options
|
||||||
|
from the main config that do not apply during clean-up.
|
||||||
|
"""
|
||||||
|
opts = [
|
||||||
|
cfg.BoolOpt('ovs_all_ports',
|
||||||
|
default=False,
|
||||||
|
help='True deletes all ports on the bridge. False deletes '
|
||||||
|
'those created by Quantum.'),
|
||||||
|
]
|
||||||
|
|
||||||
|
conf = cfg.CommonConfigOpts()
|
||||||
|
conf.register_opts(opts)
|
||||||
|
conf.register_opts(l3_agent.L3NATAgent.OPTS)
|
||||||
|
conf.register_opts(interface.OPTS)
|
||||||
|
config.setup_logging(conf)
|
||||||
|
return conf
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main method for cleaning up OVS bridges.
|
||||||
|
|
||||||
|
The utility cleans up the integration bridges used by Quantum.
|
||||||
|
"""
|
||||||
|
|
||||||
|
conf = setup_conf()
|
||||||
|
conf(sys.argv)
|
||||||
|
|
||||||
|
configuration_bridges = set([conf.ovs_integration_bridge,
|
||||||
|
conf.external_network_bridge])
|
||||||
|
ovs_bridges = set(ovs_lib.get_bridges(conf.root_helper))
|
||||||
|
|
||||||
|
if conf.ovs_all_ports:
|
||||||
|
bridges = ovs_bridges
|
||||||
|
else:
|
||||||
|
bridges = configuration_bridges & ovs_bridges
|
||||||
|
|
||||||
|
for bridge in bridges:
|
||||||
|
LOG.info(_("Cleaning %s"), bridge)
|
||||||
|
ovs = ovs_lib.OVSBridge(bridge, conf.root_helper)
|
||||||
|
ovs.delete_ports(all_ports=conf.ovs_all_ports)
|
||||||
|
|
||||||
|
LOG.info(_("OVS cleanup completed successfully"))
|
@ -313,3 +313,37 @@ class OVS_Lib_Test(unittest.TestCase):
|
|||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
self.assertIsNone(ovs_lib.get_bridge_for_iface(root_helper, iface))
|
self.assertIsNone(ovs_lib.get_bridge_for_iface(root_helper, iface))
|
||||||
self.mox.VerifyAll()
|
self.mox.VerifyAll()
|
||||||
|
|
||||||
|
def test_delete_all_ports(self):
|
||||||
|
self.mox.StubOutWithMock(self.br, 'get_port_name_list')
|
||||||
|
self.br.get_port_name_list().AndReturn(['port1'])
|
||||||
|
self.mox.StubOutWithMock(self.br, 'delete_port')
|
||||||
|
self.br.delete_port('port1')
|
||||||
|
self.mox.ReplayAll()
|
||||||
|
self.br.delete_ports(all_ports=True)
|
||||||
|
self.mox.VerifyAll()
|
||||||
|
|
||||||
|
def test_delete_quantum_ports(self):
|
||||||
|
port1 = ovs_lib.VifPort('tap1234', 1, uuidutils.generate_uuid(),
|
||||||
|
'ca:fe:de:ad:be:ef', 'br')
|
||||||
|
port2 = ovs_lib.VifPort('tap5678', 2, uuidutils.generate_uuid(),
|
||||||
|
'ca:ee:de:ad:be:ef', 'br')
|
||||||
|
ports = [port1, port2]
|
||||||
|
self.mox.StubOutWithMock(self.br, 'get_vif_ports')
|
||||||
|
self.br.get_vif_ports().AndReturn([port1, port2])
|
||||||
|
self.mox.StubOutWithMock(self.br, 'delete_port')
|
||||||
|
self.br.delete_port('tap1234')
|
||||||
|
self.br.delete_port('tap5678')
|
||||||
|
self.mox.ReplayAll()
|
||||||
|
self.br.delete_ports(all_ports=False)
|
||||||
|
self.mox.VerifyAll()
|
||||||
|
|
||||||
|
def test_get_bridges(self):
|
||||||
|
bridges = ['br-int', 'br-ex']
|
||||||
|
root_helper = 'sudo'
|
||||||
|
utils.execute(["ovs-vsctl", self.TO, "list-br"],
|
||||||
|
root_helper=root_helper).AndReturn('br-int\nbr-ex\n')
|
||||||
|
|
||||||
|
self.mox.ReplayAll()
|
||||||
|
self.assertEqual(ovs_lib.get_bridges(root_helper), bridges)
|
||||||
|
self.mox.VerifyAll()
|
||||||
|
43
quantum/tests/unit/test_agent_ovs_cleanup.py
Normal file
43
quantum/tests/unit/test_agent_ovs_cleanup.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright (c) 2012 OpenStack LLC.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import unittest2 as unittest
|
||||||
|
|
||||||
|
from quantum.agent.linux import ovs_lib
|
||||||
|
from quantum.agent import ovs_cleanup_util as util
|
||||||
|
from quantum.openstack.common import uuidutils
|
||||||
|
|
||||||
|
|
||||||
|
class TestOVSCleanup(unittest.TestCase):
|
||||||
|
def test_setup_conf(self):
|
||||||
|
with mock.patch('quantum.common.config.setup_logging'):
|
||||||
|
conf = util.setup_conf()
|
||||||
|
self.assertEqual(conf.external_network_bridge, 'br-ex')
|
||||||
|
self.assertEqual(conf.ovs_integration_bridge, 'br-int')
|
||||||
|
self.assertFalse(conf.ovs_all_ports)
|
||||||
|
|
||||||
|
def test_main(self):
|
||||||
|
with mock.patch('quantum.common.config.setup_logging'):
|
||||||
|
br_patch = mock.patch('quantum.agent.linux.ovs_lib.get_bridges')
|
||||||
|
with br_patch as mock_get_bridges:
|
||||||
|
mock_get_bridges.return_value = ['br-int', 'br-ex']
|
||||||
|
with mock.patch(
|
||||||
|
'quantum.agent.linux.ovs_lib.OVSBridge') as ovs:
|
||||||
|
util.main()
|
||||||
|
ovs.assert_has_calls([mock.call().delete_ports(
|
||||||
|
all_ports=False)])
|
1
setup.py
1
setup.py
@ -139,6 +139,7 @@ setuptools.setup(
|
|||||||
'quantum.plugins.nec.agent.nec_quantum_agent:main',
|
'quantum.plugins.nec.agent.nec_quantum_agent:main',
|
||||||
'quantum-server = quantum.server:main',
|
'quantum-server = quantum.server:main',
|
||||||
'quantum-debug = quantum.debug.shell:main',
|
'quantum-debug = quantum.debug.shell:main',
|
||||||
|
'quantum-ovs-cleanup = quantum.agent.ovs_cleanup_util:main',
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user