Merge "ovsdb: don't erase existing ovsdb managers"
This commit is contained in:
commit
d78903dd60
@ -106,6 +106,15 @@ class BaseOVS(object):
|
|||||||
self.vsctl_timeout = cfg.CONF.ovs_vsctl_timeout
|
self.vsctl_timeout = cfg.CONF.ovs_vsctl_timeout
|
||||||
self.ovsdb = ovsdb.API.get(self)
|
self.ovsdb = ovsdb.API.get(self)
|
||||||
|
|
||||||
|
def add_manager(self, connection_uri):
|
||||||
|
self.ovsdb.add_manager(connection_uri).execute()
|
||||||
|
|
||||||
|
def get_manager(self):
|
||||||
|
return self.ovsdb.get_manager().execute()
|
||||||
|
|
||||||
|
def remove_manager(self, connection_uri):
|
||||||
|
self.ovsdb.remove_manager(connection_uri).execute()
|
||||||
|
|
||||||
def add_bridge(self, bridge_name,
|
def add_bridge(self, bridge_name,
|
||||||
datapath_type=constants.OVS_DATAPATH_SYSTEM):
|
datapath_type=constants.OVS_DATAPATH_SYSTEM):
|
||||||
|
|
||||||
|
@ -100,6 +100,36 @@ class API(object):
|
|||||||
:rtype: :class:`Transaction`
|
:rtype: :class:`Transaction`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def add_manager(self, connection_uri):
|
||||||
|
"""Create a command to add a Manager to the OVS switch
|
||||||
|
|
||||||
|
This API will add a new manager without overriding the existing ones.
|
||||||
|
|
||||||
|
:param connection_uri: target to which manager needs to be set
|
||||||
|
:type connection_uri: string, see ovs-vsctl manpage for format
|
||||||
|
:returns: :class:`Command` with no result
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_manager(self):
|
||||||
|
"""Create a command to get Manager list from the OVS switch
|
||||||
|
|
||||||
|
:returns: :class:`Command` with list of Manager names result
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def remove_manager(self, connection_uri):
|
||||||
|
"""Create a command to remove a Manager from the OVS switch
|
||||||
|
|
||||||
|
This API will remove the manager configured on the OVS switch.
|
||||||
|
|
||||||
|
:param connection_uri: target identifying the manager uri that
|
||||||
|
needs to be removed.
|
||||||
|
:type connection_uri: string, see ovs-vsctl manpage for format
|
||||||
|
:returns: :class:`Command` with no result
|
||||||
|
"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def add_br(self, name, may_exist=True, datapath_type=None):
|
def add_br(self, name, may_exist=True, datapath_type=None):
|
||||||
"""Create a command to add an OVS bridge
|
"""Create a command to add an OVS bridge
|
||||||
|
@ -212,6 +212,15 @@ class OvsdbIdl(api.API):
|
|||||||
self.context.vsctl_timeout,
|
self.context.vsctl_timeout,
|
||||||
check_error, log_errors)
|
check_error, log_errors)
|
||||||
|
|
||||||
|
def add_manager(self, connection_uri):
|
||||||
|
return cmd.AddManagerCommand(self, connection_uri)
|
||||||
|
|
||||||
|
def get_manager(self):
|
||||||
|
return cmd.GetManagerCommand(self)
|
||||||
|
|
||||||
|
def remove_manager(self, connection_uri):
|
||||||
|
return cmd.RemoveManagerCommand(self, connection_uri)
|
||||||
|
|
||||||
def add_br(self, name, may_exist=True, datapath_type=None):
|
def add_br(self, name, may_exist=True, datapath_type=None):
|
||||||
return cmd.AddBridgeCommand(self, name, may_exist, datapath_type)
|
return cmd.AddBridgeCommand(self, name, may_exist, datapath_type)
|
||||||
|
|
||||||
|
@ -180,6 +180,21 @@ class OvsdbVsctl(ovsdb.API):
|
|||||||
def transaction(self, check_error=False, log_errors=True, **kwargs):
|
def transaction(self, check_error=False, log_errors=True, **kwargs):
|
||||||
return Transaction(self.context, check_error, log_errors, **kwargs)
|
return Transaction(self.context, check_error, log_errors, **kwargs)
|
||||||
|
|
||||||
|
def add_manager(self, connection_uri):
|
||||||
|
# This will add a new manager without overriding existing ones.
|
||||||
|
conn_uri = 'target="%s"' % connection_uri
|
||||||
|
args = ['create', 'Manager', conn_uri, '--', 'add', 'Open_vSwitch',
|
||||||
|
'.', 'manager_options', '@manager']
|
||||||
|
return BaseCommand(self.context, '--id=@manager', args=args)
|
||||||
|
|
||||||
|
def get_manager(self):
|
||||||
|
return MultiLineCommand(self.context, 'get-manager')
|
||||||
|
|
||||||
|
def remove_manager(self, connection_uri):
|
||||||
|
args = ['get', 'Manager', connection_uri, '--', 'remove',
|
||||||
|
'Open_vSwitch', '.', 'manager_options', '@manager']
|
||||||
|
return BaseCommand(self.context, '--id=@manager', args=args)
|
||||||
|
|
||||||
def add_br(self, name, may_exist=True, datapath_type=None):
|
def add_br(self, name, may_exist=True, datapath_type=None):
|
||||||
opts = ['--may-exist'] if may_exist else None
|
opts = ['--may-exist'] if may_exist else None
|
||||||
params = [name]
|
params = [name]
|
||||||
|
@ -55,6 +55,47 @@ class BaseCommand(api.Command):
|
|||||||
__repr__ = __str__
|
__repr__ = __str__
|
||||||
|
|
||||||
|
|
||||||
|
class AddManagerCommand(BaseCommand):
|
||||||
|
def __init__(self, api, target):
|
||||||
|
super(AddManagerCommand, self).__init__(api)
|
||||||
|
self.target = target
|
||||||
|
|
||||||
|
def run_idl(self, txn):
|
||||||
|
row = txn.insert(self.api._tables['Manager'])
|
||||||
|
row.target = self.target
|
||||||
|
self.api._ovs.verify('manager_options')
|
||||||
|
self.api._ovs.manager_options = self.api._ovs.manager_options + [row]
|
||||||
|
|
||||||
|
|
||||||
|
class GetManagerCommand(BaseCommand):
|
||||||
|
def __init__(self, api):
|
||||||
|
super(GetManagerCommand, self).__init__(api)
|
||||||
|
|
||||||
|
def run_idl(self, txn):
|
||||||
|
self.result = [m.target for m in
|
||||||
|
self.api._tables['Manager'].rows.values()]
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveManagerCommand(BaseCommand):
|
||||||
|
def __init__(self, api, target):
|
||||||
|
super(RemoveManagerCommand, self).__init__(api)
|
||||||
|
self.target = target
|
||||||
|
|
||||||
|
def run_idl(self, txn):
|
||||||
|
try:
|
||||||
|
manager = idlutils.row_by_value(self.api.idl, 'Manager', 'target',
|
||||||
|
self.target)
|
||||||
|
except idlutils.RowNotFound:
|
||||||
|
msg = _("Manager with target %s does not exist") % self.target
|
||||||
|
LOG.error(msg)
|
||||||
|
raise RuntimeError(msg)
|
||||||
|
self.api._ovs.verify('manager_options')
|
||||||
|
manager_list = self.api._ovs.manager_options
|
||||||
|
manager_list.remove(manager)
|
||||||
|
self.api._ovs.manager_options = manager_list
|
||||||
|
self.api._tables['Manager'].rows[manager.uuid].delete()
|
||||||
|
|
||||||
|
|
||||||
class AddBridgeCommand(BaseCommand):
|
class AddBridgeCommand(BaseCommand):
|
||||||
def __init__(self, api, name, may_exist, datapath_type):
|
def __init__(self, api, name, may_exist, datapath_type):
|
||||||
super(AddBridgeCommand, self).__init__(api)
|
super(AddBridgeCommand, self).__init__(api)
|
||||||
|
@ -12,7 +12,11 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from neutron.agent.common import utils
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
from neutron.agent.ovsdb import api as ovsdb
|
||||||
|
|
||||||
|
cfg.CONF.import_opt('ovs_vsctl_timeout', 'neutron.agent.common.ovs_lib')
|
||||||
|
|
||||||
|
|
||||||
def _connection_to_manager_uri(conn_uri):
|
def _connection_to_manager_uri(conn_uri):
|
||||||
@ -25,5 +29,9 @@ def _connection_to_manager_uri(conn_uri):
|
|||||||
|
|
||||||
|
|
||||||
def enable_connection_uri(conn_uri):
|
def enable_connection_uri(conn_uri):
|
||||||
|
class OvsdbVsctlContext(object):
|
||||||
|
vsctl_timeout = cfg.CONF.ovs_vsctl_timeout
|
||||||
|
|
||||||
manager_uri = _connection_to_manager_uri(conn_uri)
|
manager_uri = _connection_to_manager_uri(conn_uri)
|
||||||
utils.execute(['ovs-vsctl', 'set-manager', manager_uri], run_as_root=True)
|
api = ovsdb.API.get(OvsdbVsctlContext, 'vsctl')
|
||||||
|
api.add_manager(manager_uri).execute(check_error=False, log_errors=True)
|
||||||
|
@ -25,10 +25,11 @@ class ExclusivePort(resource_allocator.ExclusiveResource):
|
|||||||
:type port: int
|
:type port: int
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, protocol):
|
def __init__(self, protocol, start=1024, end=None):
|
||||||
super(ExclusivePort, self).__init__(
|
super(ExclusivePort, self).__init__(
|
||||||
'ports',
|
'ports',
|
||||||
functools.partial(net_helpers.get_free_namespace_port, protocol))
|
functools.partial(net_helpers.get_free_namespace_port, protocol,
|
||||||
|
start=start, end=end))
|
||||||
|
|
||||||
def _setUp(self):
|
def _setUp(self):
|
||||||
super(ExclusivePort, self)._setUp()
|
super(ExclusivePort, self)._setUp()
|
||||||
|
@ -74,6 +74,9 @@ CHILD_PROCESS_SLEEP = os.environ.get('OS_TEST_CHILD_PROCESS_SLEEP', 0.5)
|
|||||||
|
|
||||||
TRANSPORT_PROTOCOLS = (n_const.PROTO_NAME_TCP, n_const.PROTO_NAME_UDP)
|
TRANSPORT_PROTOCOLS = (n_const.PROTO_NAME_TCP, n_const.PROTO_NAME_UDP)
|
||||||
|
|
||||||
|
OVS_MANAGER_TEST_PORT_FIRST = 6610
|
||||||
|
OVS_MANAGER_TEST_PORT_LAST = 6639
|
||||||
|
|
||||||
|
|
||||||
def increment_ip_cidr(ip_cidr, offset=1):
|
def increment_ip_cidr(ip_cidr, offset=1):
|
||||||
"""Increment ip_cidr offset times.
|
"""Increment ip_cidr offset times.
|
||||||
@ -189,7 +192,7 @@ def get_unused_port(used, start=1024, end=None):
|
|||||||
return random.choice(list(candidates - used))
|
return random.choice(list(candidates - used))
|
||||||
|
|
||||||
|
|
||||||
def get_free_namespace_port(protocol, namespace=None):
|
def get_free_namespace_port(protocol, namespace=None, start=1024, end=None):
|
||||||
"""Return an unused port from given namespace
|
"""Return an unused port from given namespace
|
||||||
|
|
||||||
WARNING: This function returns a port that is free at the execution time of
|
WARNING: This function returns a port that is free at the execution time of
|
||||||
@ -199,6 +202,10 @@ def get_free_namespace_port(protocol, namespace=None):
|
|||||||
|
|
||||||
:param protocol: Return free port for given protocol. Supported protocols
|
:param protocol: Return free port for given protocol. Supported protocols
|
||||||
are 'tcp' and 'udp'.
|
are 'tcp' and 'udp'.
|
||||||
|
:param namespace: Namespace in which free port has to be returned.
|
||||||
|
:param start: The starting port number.
|
||||||
|
:param end: The ending port number (free port that is returned would be
|
||||||
|
between (start, end) values.
|
||||||
"""
|
"""
|
||||||
if protocol == n_const.PROTO_NAME_TCP:
|
if protocol == n_const.PROTO_NAME_TCP:
|
||||||
param = '-tna'
|
param = '-tna'
|
||||||
@ -211,7 +218,7 @@ def get_free_namespace_port(protocol, namespace=None):
|
|||||||
output = ip_wrapper.netns.execute(['ss', param])
|
output = ip_wrapper.netns.execute(['ss', param])
|
||||||
used_ports = _get_source_ports_from_ss_output(output)
|
used_ports = _get_source_ports_from_ss_output(output)
|
||||||
|
|
||||||
return get_unused_port(used_ports)
|
return get_unused_port(used_ports, start, end)
|
||||||
|
|
||||||
|
|
||||||
def create_patch_ports(source, destination):
|
def create_patch_ports(source, destination):
|
||||||
|
@ -17,10 +17,12 @@ import collections
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
from neutron_lib import constants as const
|
||||||
|
|
||||||
from neutron.agent.common import ovs_lib
|
from neutron.agent.common import ovs_lib
|
||||||
from neutron.agent.linux import ip_lib
|
from neutron.agent.linux import ip_lib
|
||||||
from neutron.common import utils
|
from neutron.common import utils
|
||||||
|
from neutron.tests.common.exclusive_resources import port
|
||||||
from neutron.tests.common import net_helpers
|
from neutron.tests.common import net_helpers
|
||||||
from neutron.tests.functional.agent.linux import base
|
from neutron.tests.functional.agent.linux import base
|
||||||
|
|
||||||
@ -432,6 +434,38 @@ class OVSLibTestCase(base.BaseOVSLinuxTestCase):
|
|||||||
super(OVSLibTestCase, self).setUp()
|
super(OVSLibTestCase, self).setUp()
|
||||||
self.ovs = ovs_lib.BaseOVS()
|
self.ovs = ovs_lib.BaseOVS()
|
||||||
|
|
||||||
|
def test_add_manager_appends(self):
|
||||||
|
port1 = self.useFixture(port.ExclusivePort(const.PROTO_NAME_TCP,
|
||||||
|
start=net_helpers.OVS_MANAGER_TEST_PORT_FIRST,
|
||||||
|
end=net_helpers.OVS_MANAGER_TEST_PORT_LAST)).port
|
||||||
|
port2 = self.useFixture(port.ExclusivePort(const.PROTO_NAME_TCP,
|
||||||
|
start=net_helpers.OVS_MANAGER_TEST_PORT_FIRST,
|
||||||
|
end=net_helpers.OVS_MANAGER_TEST_PORT_LAST)).port
|
||||||
|
manager_list = ["ptcp:%s:127.0.0.1" % port1,
|
||||||
|
"ptcp:%s:127.0.0.1" % port2]
|
||||||
|
# Verify that add_manager does not override the existing manager
|
||||||
|
expected_manager_list = list()
|
||||||
|
for conn_uri in manager_list:
|
||||||
|
self.ovs.add_manager(conn_uri)
|
||||||
|
self.addCleanup(self.ovs.remove_manager, conn_uri)
|
||||||
|
self.assertIn(conn_uri, self.ovs.get_manager())
|
||||||
|
expected_manager_list.append(conn_uri)
|
||||||
|
|
||||||
|
# Verify that switch is configured with both the managers
|
||||||
|
for manager_uri in expected_manager_list:
|
||||||
|
self.assertIn(manager_uri, manager_list)
|
||||||
|
|
||||||
|
def test_add_manager_lifecycle_baseovs(self):
|
||||||
|
port1 = self.useFixture(port.ExclusivePort(const.PROTO_NAME_TCP,
|
||||||
|
start=net_helpers.OVS_MANAGER_TEST_PORT_FIRST,
|
||||||
|
end=net_helpers.OVS_MANAGER_TEST_PORT_LAST)).port
|
||||||
|
conn_uri = "ptcp:%s:127.0.0.1" % port1
|
||||||
|
self.addCleanup(self.ovs.remove_manager, conn_uri)
|
||||||
|
self.ovs.add_manager(conn_uri)
|
||||||
|
self.assertIn(conn_uri, self.ovs.get_manager())
|
||||||
|
self.ovs.remove_manager(conn_uri)
|
||||||
|
self.assertNotIn(conn_uri, self.ovs.get_manager())
|
||||||
|
|
||||||
def test_bridge_lifecycle_baseovs(self):
|
def test_bridge_lifecycle_baseovs(self):
|
||||||
name = utils.get_rand_name(prefix=net_helpers.BR_PREFIX)
|
name = utils.get_rand_name(prefix=net_helpers.BR_PREFIX)
|
||||||
self.addCleanup(self.ovs.delete_bridge, name)
|
self.addCleanup(self.ovs.delete_bridge, name)
|
||||||
|
@ -34,10 +34,3 @@ class TestOVSNativeHelpers(base.BaseTestCase):
|
|||||||
for conn_uri, expected in CONNECTION_TO_MANAGER_URI_MAP:
|
for conn_uri, expected in CONNECTION_TO_MANAGER_URI_MAP:
|
||||||
self.assertEqual(expected,
|
self.assertEqual(expected,
|
||||||
helpers._connection_to_manager_uri(conn_uri))
|
helpers._connection_to_manager_uri(conn_uri))
|
||||||
|
|
||||||
def test_enable_connection_uri(self):
|
|
||||||
for conn_uri, manager_uri in CONNECTION_TO_MANAGER_URI_MAP:
|
|
||||||
helpers.enable_connection_uri(conn_uri)
|
|
||||||
self.execute.assert_called_with(
|
|
||||||
['ovs-vsctl', 'set-manager', manager_uri],
|
|
||||||
run_as_root=True)
|
|
||||||
|
Loading…
Reference in New Issue
Block a user