Retry connections to Nova
Sometimes Neutron is failing to send notification to Nova due to timeout, refused connection or another HTTP error. Retry send in those cases. Conflicts: neutron/notifiers/nova.py neutron/tests/unit/notifiers/test_nova.py Closes-Bug: #1987780 Change-Id: Iaaccec770484234b704f70f3c144efac4d8ffba0 (cherry picked from commitcd475f9af8
) (cherry picked from commitb5e9148cc7
) (cherry picked from commit49f49bc2bf
)
This commit is contained in:
parent
c81fb5b394
commit
c9dbbd4192
@ -13,6 +13,8 @@
|
|||||||
# 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 keystoneauth1 import exceptions as ks_exceptions
|
||||||
from keystoneauth1 import loading as ks_loading
|
from keystoneauth1 import loading as ks_loading
|
||||||
from neutron_lib.callbacks import events
|
from neutron_lib.callbacks import events
|
||||||
from neutron_lib.callbacks import registry
|
from neutron_lib.callbacks import registry
|
||||||
@ -29,6 +31,7 @@ from oslo_context import context as common_context
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
from sqlalchemy.orm import attributes as sql_attr
|
from sqlalchemy.orm import attributes as sql_attr
|
||||||
|
import tenacity
|
||||||
|
|
||||||
from neutron.notifiers import batch_notifier
|
from neutron.notifiers import batch_notifier
|
||||||
|
|
||||||
@ -242,6 +245,12 @@ class Notifier(object):
|
|||||||
'tag': port.id})
|
'tag': port.id})
|
||||||
self.send_port_status(None, None, port)
|
self.send_port_status(None, None, port)
|
||||||
|
|
||||||
|
@tenacity.retry(
|
||||||
|
retry=tenacity.retry_if_exception_type(
|
||||||
|
ks_exceptions.RetriableConnectionFailure),
|
||||||
|
wait=tenacity.wait_exponential(multiplier=0.01, max=1),
|
||||||
|
stop=tenacity.stop_after_delay(1),
|
||||||
|
after=tenacity.after_log(LOG, logging.DEBUG))
|
||||||
def send_events(self, batched_events):
|
def send_events(self, batched_events):
|
||||||
LOG.debug("Sending events: %s", batched_events)
|
LOG.debug("Sending events: %s", batched_events)
|
||||||
novaclient = self._get_nova_client()
|
novaclient = self._get_nova_client()
|
||||||
@ -251,6 +260,10 @@ class Notifier(object):
|
|||||||
except nova_exceptions.NotFound:
|
except nova_exceptions.NotFound:
|
||||||
LOG.debug("Nova returned NotFound for event: %s",
|
LOG.debug("Nova returned NotFound for event: %s",
|
||||||
batched_events)
|
batched_events)
|
||||||
|
except ks_exceptions.RetriableConnectionFailure:
|
||||||
|
raise
|
||||||
|
# next clause handles all exceptions
|
||||||
|
# so reraise for retry decorator
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception("Failed to notify nova on events: %s",
|
LOG.exception("Failed to notify nova on events: %s",
|
||||||
batched_events)
|
batched_events)
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
|
from keystoneauth1 import exceptions as ks_exc
|
||||||
from neutron_lib import constants as n_const
|
from neutron_lib import constants as n_const
|
||||||
from neutron_lib import context as n_ctx
|
from neutron_lib import context as n_ctx
|
||||||
from neutron_lib import exceptions as n_exc
|
from neutron_lib import exceptions as n_exc
|
||||||
@ -246,6 +248,14 @@ class TestNovaNotify(base.BaseTestCase):
|
|||||||
nova_exceptions.NotFound)
|
nova_exceptions.NotFound)
|
||||||
self.nova_notifier.send_events([])
|
self.nova_notifier.send_events([])
|
||||||
|
|
||||||
|
@mock.patch('novaclient.client.Client')
|
||||||
|
def test_nova_send_events_raises_connect_exc(self, mock_client):
|
||||||
|
create = mock_client().server_external_events.create
|
||||||
|
create.side_effect = (
|
||||||
|
ks_exc.ConnectFailure, ks_exc.ConnectTimeout, [])
|
||||||
|
self.nova_notifier.send_events([])
|
||||||
|
self.assertEqual(3, create.call_count)
|
||||||
|
|
||||||
@mock.patch('novaclient.client.Client')
|
@mock.patch('novaclient.client.Client')
|
||||||
def test_nova_send_events_raises(self, mock_client):
|
def test_nova_send_events_raises(self, mock_client):
|
||||||
mock_client.server_external_events.create.return_value = Exception
|
mock_client.server_external_events.create.return_value = Exception
|
||||||
|
Loading…
Reference in New Issue
Block a user