+++ /dev/null
-diff --git a/neunton/agent/l3_agent.py b/neunton/agent/l3_agent.py
-index 79156cd..0037b80 100644
---- a/neunton/agent/l3_agent.py
-+++ b/neunton/agent/l3_agent.py
-@@ -23,6 +23,7 @@ import eventlet
- from eventlet import semaphore
- import netaddr
- from oslo.config import cfg
-+from quantum.agent.linux.interface import OVSInterfaceDriver
-
- from neunton.agent.common import config
- from neunton.agent.linux import external_process
-@@ -233,7 +234,8 @@ class L3NATAgent(manager.Manager):
- for c, r in self.metadata_nat_rules():
- ri.iptables_manager.ipv4['nat'].add_rule(c, r)
- ri.iptables_manager.apply()
-- self._spawn_metadata_proxy(ri)
-+ if self.conf.use_namespaces:
-+ self._spawn_metadata_proxy(ri)
-
- def _router_removed(self, router_id):
- ri = self.router_info[router_id]
-@@ -246,7 +248,8 @@ class L3NATAgent(manager.Manager):
- for c, r in self.metadata_nat_rules():
- ri.iptables_manager.ipv4['nat'].remove_rule(c, r)
- ri.iptables_manager.apply()
-- self._destroy_metadata_proxy(ri)
-+ if self.conf.use_namespaces:
-+ self._destroy_metadata_proxy(ri)
- del self.router_info[router_id]
- self._destroy_router_namespace(ri.ns_name())
-
-@@ -370,7 +373,9 @@ class L3NATAgent(manager.Manager):
- ri.floating_ips.append(new_fip)
-
- def _get_ex_gw_port(self, ri):
-- return ri.router.get('gw_port')
-+ rv = ri.router.get('gw_port')
-+ LOG.debug("***SV::_get_ex_gw_port: {0}".format(rv))
-+ return rv
-
- def _send_gratuitous_arp_packet(self, ri, interface_name, ip_address):
- if self.conf.send_arp_for_ha > 0:
-@@ -390,49 +395,78 @@ class L3NATAgent(manager.Manager):
- LOG.error(_("Failed sending gratuitous ARP: %s"), str(e))
-
- def get_internal_device_name(self, port_id):
-- return (INTERNAL_DEV_PREFIX + port_id)[:self.driver.DEV_NAME_LEN]
-+ devname = INTERNAL_DEV_PREFIX + port_id
-+ LOG.debug("***SV::get_internal_device_name: {0}".format(devname))
-+ return devname[:self.driver.DEV_NAME_LEN]
-
- def get_external_device_name(self, port_id):
-- return (EXTERNAL_DEV_PREFIX + port_id)[:self.driver.DEV_NAME_LEN]
-+ devname = EXTERNAL_DEV_PREFIX + port_id
-+ LOG.debug("***SV::get_external_device_name: {0}".format(devname))
-+ return devname[:self.driver.DEV_NAME_LEN]
-
-- def external_gateway_added(self, ri, ex_gw_port, internal_cidrs):
-+ def get_effective_interface_name(self, ifname):
-+ if not self.conf.use_namespaces:
-+ return self.conf.external_network_bridge
-+ else:
-+ return ifname
-
-+ def external_gateway_added(self, ri, ex_gw_port, internal_cidrs):
-+ ### SV: patched !!!
- interface_name = self.get_external_device_name(ex_gw_port['id'])
-+ effective_interface_name = self.get_effective_interface_name(interface_name)
- ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
-- if not ip_lib.device_exists(interface_name,
-- root_helper=self.root_helper,
-- namespace=ri.ns_name()):
-+ ip_address = ex_gw_port['ip_cidr'].split('/')[0]
-+ if not ip_lib.device_exists(interface_name, root_helper=self.root_helper, namespace=ri.ns_name()):
- self.driver.plug(ex_gw_port['network_id'],
- ex_gw_port['id'], interface_name,
- ex_gw_port['mac_address'],
- bridge=self.conf.external_network_bridge,
- namespace=ri.ns_name(),
-- prefix=EXTERNAL_DEV_PREFIX)
-- self.driver.init_l3(interface_name, [ex_gw_port['ip_cidr']],
-- namespace=ri.ns_name())
-- ip_address = ex_gw_port['ip_cidr'].split('/')[0]
-- self._send_gratuitous_arp_packet(ri, interface_name, ip_address)
-+ prefix=EXTERNAL_DEV_PREFIX
-+ )
-+
-+ if not self.conf.use_namespaces:
-+ LOG.info("Warning! You are not using network namespaces! "
-+ "IP {ip} will be assigned to interface {iface}, instead {eiface}."
-+ .format(
-+ ip=ex_gw_port['ip_cidr'],
-+ iface=interface_name,
-+ eiface=effective_interface_name
-+ )
-+ )
-+ net = netaddr.IPNetwork(ex_gw_port['ip_cidr'])
-+ device = ip_lib.IPDevice(effective_interface_name, self.root_helper, namespace=ri.ns_name())
-+ device.addr.add(net.version, ex_gw_port['ip_cidr'], str(net.broadcast))
-+ else:
-+ self.driver.init_l3(interface_name, [ex_gw_port['ip_cidr']], namespace=ri.ns_name())
-+
-+ self._send_gratuitous_arp_packet(ri, effective_interface_name, ip_address)
-
- gw_ip = ex_gw_port['subnet']['gateway_ip']
-- if ex_gw_port['subnet']['gateway_ip']:
-- cmd = ['route', 'add', 'default', 'gw', gw_ip]
-- if self.conf.use_namespaces:
-- ip_wrapper = ip_lib.IPWrapper(self.root_helper,
-- namespace=ri.ns_name())
-- ip_wrapper.netns.execute(cmd, check_exit_code=False)
-- else:
-- utils.execute(cmd, check_exit_code=False,
-- root_helper=self.root_helper)
-+ if interface_name == effective_interface_name:
-+ # work in net.namespaces, or 1st assignation on this interface
-+ if ex_gw_port['subnet']['gateway_ip']:
-+ cmd = ['route', 'add', 'default', 'gw', gw_ip]
-+ if self.conf.use_namespaces:
-+ ip_wrapper = ip_lib.IPWrapper(self.root_helper, namespace=ri.ns_name())
-+ ip_wrapper.netns.execute(cmd, check_exit_code=False)
-+ else:
-+ utils.execute(cmd, check_exit_code=False, root_helper=self.root_helper)
-
-- for (c, r) in self.external_gateway_nat_rules(ex_gw_ip,
-- internal_cidrs,
-- interface_name):
-+ for (c, r) in self.external_gateway_nat_rules(ex_gw_ip, internal_cidrs, effective_interface_name):
- ri.iptables_manager.ipv4['nat'].add_rule(c, r)
- ri.iptables_manager.apply()
-
- def external_gateway_removed(self, ri, ex_gw_port, internal_cidrs):
--
- interface_name = self.get_external_device_name(ex_gw_port['id'])
-+ effective_interface_name = self.get_effective_interface_name(interface_name)
-+ ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
-+
-+ if not self.conf.use_namespaces:
-+ net = netaddr.IPNetwork(ex_gw_ip)
-+ device = ip_lib.IPDevice(effective_interface_name, self.root_helper, namespace=ri.ns_name())
-+ device.addr.delete(net.version, ex_gw_ip)
-+
- if ip_lib.device_exists(interface_name,
- root_helper=self.root_helper,
- namespace=ri.ns_name()):
-@@ -441,9 +475,7 @@ class L3NATAgent(manager.Manager):
- namespace=ri.ns_name(),
- prefix=EXTERNAL_DEV_PREFIX)
-
-- ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
-- for c, r in self.external_gateway_nat_rules(ex_gw_ip, internal_cidrs,
-- interface_name):
-+ for c, r in self.external_gateway_nat_rules(ex_gw_ip, internal_cidrs, effective_interface_name):
- ri.iptables_manager.ipv4['nat'].remove_rule(c, r)
- ri.iptables_manager.apply()
-
-@@ -463,6 +495,7 @@ class L3NATAgent(manager.Manager):
-
- def external_gateway_nat_rules(self, ex_gw_ip, internal_cidrs,
- interface_name):
-+ ### SV: need-patch !!!
- rules = [('POSTROUTING', '! -i %(interface_name)s '
- '! -o %(interface_name)s -m conntrack ! '
- '--ctstate DNAT -j ACCEPT' % locals())]
-@@ -475,7 +508,7 @@ class L3NATAgent(manager.Manager):
- interface_name = self.get_internal_device_name(port_id)
- if not ip_lib.device_exists(interface_name,
- root_helper=self.root_helper,
-- namespace=ri.ns_name()):
-+ namespace=ri.ns_name()): # check existing MAC address of qr_*
- self.driver.plug(network_id, port_id, interface_name, mac_address,
- namespace=ri.ns_name(),
- prefix=INTERNAL_DEV_PREFIX)
-@@ -513,27 +546,38 @@ class L3NATAgent(manager.Manager):
- return rules
-
- def floating_ip_added(self, ri, ex_gw_port, floating_ip, fixed_ip):
-+ ### SV: patched !!!
- ip_cidr = str(floating_ip) + '/32'
- interface_name = self.get_external_device_name(ex_gw_port['id'])
-- device = ip_lib.IPDevice(interface_name, self.root_helper,
-- namespace=ri.ns_name())
-+ effective_interface_name = self.get_effective_interface_name(interface_name)
-+ if not self.conf.use_namespaces:
-+ LOG.info("Warning! You are not using network namespaces! "
-+ "Floating IP {ip} will be assigned to interface {iface}, instead {eiface}."
-+ .format(
-+ ip=ip_cidr,
-+ iface=interface_name,
-+ eiface=effective_interface_name
-+ )
-+ )
-+ device = ip_lib.IPDevice(effective_interface_name, self.root_helper, namespace=ri.ns_name())
-
- if ip_cidr not in [addr['cidr'] for addr in device.addr.list()]:
- net = netaddr.IPNetwork(ip_cidr)
- device.addr.add(net.version, ip_cidr, str(net.broadcast))
-- self._send_gratuitous_arp_packet(ri, interface_name, floating_ip)
-+ self._send_gratuitous_arp_packet(ri, effective_interface_name, floating_ip)
-
- for chain, rule in self.floating_forward_rules(floating_ip, fixed_ip):
- ri.iptables_manager.ipv4['nat'].add_rule(chain, rule)
- ri.iptables_manager.apply()
-
- def floating_ip_removed(self, ri, ex_gw_port, floating_ip, fixed_ip):
-+ ### SV: patched !!!
- ip_cidr = str(floating_ip) + '/32'
- net = netaddr.IPNetwork(ip_cidr)
- interface_name = self.get_external_device_name(ex_gw_port['id'])
-+ effective_interface_name = self.get_effective_interface_name(interface_name)
-
-- device = ip_lib.IPDevice(interface_name, self.root_helper,
-- namespace=ri.ns_name())
-+ device = ip_lib.IPDevice(effective_interface_name, self.root_helper, namespace=ri.ns_name())
- device.addr.delete(net.version, ip_cidr)
-
- for chain, rule in self.floating_forward_rules(floating_ip, fixed_ip):
-@@ -642,7 +686,16 @@ class L3NATAgent(manager.Manager):
- self.fullsync = True
-
- def after_start(self):
-- LOG.info(_("L3 agent started"))
-+ LOG.info(_("L3 agent started (Mirantis-patched)"))
-+ LOG.debug("*Ext.bridge name is '{0}'".format(self.conf.external_network_bridge))
-+ if not self.conf.use_namespaces:
-+ LOG.info("Warning!!!")
-+ LOG.info("You are not using network namespaces! "
-+ "Floating IPs will be assigned to interface {iface}".format(
-+ iface=self.conf.external_network_bridge
-+ )
-+ )
-+
-
- def _update_routing_table(self, ri, operation, route):
- cmd = ['ip', 'route', operation, 'to', route['destination'],
+++ /dev/null
-diff --git a/neunton/common/exceptions.py b/neunton/common/exceptions.py
-index c99c254..e24f7bc 100644
---- a/neunton/common/exceptions.py
-+++ b/neunton/common/exceptions.py
-@@ -235,3 +235,7 @@ class InvalidSharedSetting(QuantumException):
-
- class InvalidExtenstionEnv(QuantumException):
- message = _("Invalid extension environment: %(reason)s")
-+
-+class DBError(Error):
-+ message = _("Database error")
-+
-diff --git a/neunton/db/api.py b/neunton/db/api.py
-index 238a9f9..737c748 100644
---- a/neunton/db/api.py
-+++ b/neunton/db/api.py
-@@ -20,12 +20,16 @@
- import logging
- import time
-
-+import time
-+
- import sqlalchemy as sql
- from sqlalchemy import create_engine
- from sqlalchemy.exc import DisconnectionError
-+from sqlalchemy.exc import OperationalError
- from sqlalchemy.orm import sessionmaker, exc
-
- from quantum.db import model_base
-+from quantum.common.exceptions import DBError
-
- LOG = logging.getLogger(__name__)
-
-@@ -33,28 +37,61 @@ LOG = logging.getLogger(__name__)
- _ENGINE = None
- _MAKER = None
- BASE = model_base.BASE
-+OPTIONS = None
-
-+def is_db_connection_error(args):
-+ """Return True if error in connecting to db."""
-+ # NOTE(adam_g): This is currently MySQL specific and needs to be extended
-+ # to support Postgres and others.
-+ conn_err_codes = ('2002', '2003', '2006', '2013', '2014', '2045', '2055')
-+ for err_code in conn_err_codes:
-+ if args.find(err_code) != -1:
-+ return True
-+ return False
-
--class MySQLPingListener(object):
-
-- """
-- Ensures that MySQL connections checked out of the
-- pool are alive.
-+def wrap_db_error(f):
-+ """Function wrapper to capture DB errors
-
-- Borrowed from:
-- http://groups.google.com/group/sqlalchemy/msg/a4ce563d802c929f
-- """
-+ If an exception is thrown by the wrapped function,
-+ determine if it represents a database connection error.
-+ If so, retry the wrapped function, and repeat until it succeeds
-+ or we reach a configurable maximum number of retries.
-+ If it is not a connection error, or we exceeded the retry limit,
-+ raise a DBError.
-
-- def checkout(self, dbapi_con, con_record, con_proxy):
-- try:
-- dbapi_con.cursor().execute('select 1')
-- except dbapi_con.OperationalError, ex:
-- if ex.args[0] in (2006, 2013, 2014, 2045, 2055):
-- LOG.warn('Got mysql server has gone away: %s', ex)
-- raise DisconnectionError("Database server went away")
-- else:
-+ """
-+ global OPTIONS
-+ def _wrap_db_error(*args, **kwargs):
-+ next_interval = OPTIONS.get('reconnect_interval', 1)
-+ remaining = OPTIONS.get('sql_max_retries', -1)
-+ if remaining == -1:
-+ remaining = 'infinite'
-+ while True:
-+ try:
-+ return f(*args, **kwargs)
-+ except OperationalError, e:
-+ if is_db_connection_error(e.args[0]):
-+ if remaining == 0:
-+ logging.warn('DB exceeded retry limit.')
-+ raise DBError(e)
-+ if remaining != 'infinite':
-+ remaining -= 1
-+ logging.warn('DB connection error, '
-+ 'retrying in %i seconds.' % next_interval)
-+ time.sleep(next_interval)
-+ if OPTIONS.get('inc_reconnect_interval', True):
-+ next_interval = min(next_interval * 2,
-+ OPTIONS.get('max_reconnect_interval', 60))
-+ else:
-+ logging.warn('DB exception wrapped.')
-+ raise DBError(e)
-+ except Exception, e:
- raise
-
-+ _wrap_db_error.func_name = f.func_name
-+ return _wrap_db_error
-+
-
- def configure_db(options):
- """
-@@ -63,6 +100,8 @@ def configure_db(options):
-
- :param options: Mapping of configuration options
- """
-+ global OPTIONS
-+ OPTIONS = options
- global _ENGINE
- if not _ENGINE:
- connection_dict = sql.engine.url.make_url(options['sql_connection'])
-@@ -72,9 +111,6 @@ def configure_db(options):
- 'convert_unicode': True,
- }
-
-- if 'mysql' in connection_dict.drivername:
-- engine_args['listeners'] = [MySQLPingListener()]
--
- _ENGINE = create_engine(options['sql_connection'], **engine_args)
- base = options.get('base', BASE)
- if not register_models(base):
-@@ -101,10 +137,18 @@ def get_session(autocommit=True, expire_on_commit=False):
- global _MAKER, _ENGINE
- if not _MAKER:
- assert _ENGINE
-+ class OurQuery(sql.orm.query.Query):
-+ pass
-+ query = OurQuery
-+ query.all = wrap_db_error(query.all)
-+ query.first = wrap_db_error(query.first)
- _MAKER = sessionmaker(bind=_ENGINE,
- autocommit=autocommit,
-- expire_on_commit=expire_on_commit)
-- return _MAKER()
-+ expire_on_commit=expire_on_commit,
-+ query_cls=OurQuery)
-+ session = _MAKER()
-+ session.flush = wrap_db_error(session.flush)
-+ return session
-
-
- def retry_registration(remaining, reconnect_interval, base=BASE):