Files
neutron/neutron/common/ovn/hash_ring_manager.py
Maciej Józefczyk 65692127f6 [OVN] Move OVN commons to neutron tree
Move OVN related commons to neutron tree.

Previous paths in networking-ovn tree:
./networking_ovn/common/constants.py -> ./neutron/common/ovn/constants.py
./networking_ovn/common/exceptions.py -> ./neutron/common/ovn/exceptions.py
./networking_ovn/common/utils.py -> ./neutron/common/ovn/utils.py
./networking_ovn/common/hash_ring_manager.py -> neutron/common/ovn/hash_ring_manager.py
./networking_ovn/common/config.py -> ./neutron/conf/plugins/ml2/drivers/ovn/ovn_conf.py

Co-Authored-By: Gal Sagie <gal.sagie@huawei.com>
Co-Authored-By: Boden R <bodenvmw@gmail.com>
Co-Authored-By: Daniel Alvarez <dalvarez@redhat.com>
Co-Authored-By: Amitabha Biswas <abiswas@us.ibm.com>
Co-Authored-By: Chandra S Vejendla <csvejend@us.ibm.com>
Co-Authored-By: Babu Shanmugam <bschanmu@redhat.com>
Co-Authored-By: Lucas Alvares Gomes <lucasagomes@gmail.com>
Co-Authored-By: Terry Wilson <twilson@redhat.com>
Co-Authored-By: Ramu Ramamurthy <ramu.ramamurthy@us.ibm.com>
Co-Authored-By: Maciej Józefczyk <mjozefcz@redhat.com>
Co-Authored-By: Gary Kotton <gkotton@vmware.com>
Co-Authored-By: Andrew Austin <aaustin@redhat.com>
Co-Authored-By: Miguel Angel Ajo <majopela@redhat.com>
Co-Authored-By: Brian Haley <bhaley@redhat.com>
Co-Authored-By: Dong Jun <dongj@dtdream.com>
Co-Authored-By: xurong00037997 <xu.rong@zte.com.cn>
Co-Authored-By: Rodolfo Alonso Hernandez <ralonsoh@redhat.com>

Change-Id: Ib46bfdd14a150a324dbf28c6a50c839c5c824e35
Related-Blueprint: neutron-ovn-merge
2019-12-04 13:15:16 +00:00

101 lines
3.6 KiB
Python

# Copyright 2019 Red Hat, Inc.
# 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 datetime
from oslo_log import log
from oslo_utils import timeutils
import six
from tooz import hashring
from neutron.common.ovn import constants
from neutron.common.ovn import exceptions
from neutron.db import ovn_hash_ring_db as db_hash_ring
from neutron_lib import context
LOG = log.getLogger(__name__)
class HashRingManager(object):
def __init__(self, group_name):
self._hash_ring = None
self._last_time_loaded = None
self._cache_startup_timeout = True
self._group = group_name
self.admin_ctx = context.get_admin_context()
@property
def _wait_startup_before_caching(self):
# NOTE(lucasagomes): Some events are processed at the service's
# startup time and since many services may be started concurrently
# we do not want to use a cached hash ring at that point. This
# method checks if the created_at and updated_at columns from the
# nodes in the ring from this host is equal, and if so it means
# that the service just started.
# If the startup timeout already expired, there's no reason to
# keep reading from the DB. At this point this will always
# return False
if not self._cache_startup_timeout:
return False
nodes = db_hash_ring.get_active_nodes(
self.admin_ctx,
constants.HASH_RING_CACHE_TIMEOUT, self._group, from_host=True)
dont_cache = nodes and nodes[0].created_at == nodes[0].updated_at
if not dont_cache:
self._cache_startup_timeout = False
return dont_cache
def _load_hash_ring(self, refresh=False):
cache_timeout = timeutils.utcnow() - datetime.timedelta(
seconds=constants.HASH_RING_CACHE_TIMEOUT)
# Refresh the cache if:
# - Refreshed is forced (refresh=True)
# - Service just started (_wait_startup_before_caching)
# - Hash Ring is not yet instantiated
# - Cache has timed out
if (refresh or
self._wait_startup_before_caching or
self._hash_ring is None or
not self._hash_ring.nodes or
cache_timeout >= self._last_time_loaded):
nodes = db_hash_ring.get_active_nodes(
self.admin_ctx,
constants.HASH_RING_NODES_TIMEOUT, self._group)
self._hash_ring = hashring.HashRing({node.node_uuid
for node in nodes})
self._last_time_loaded = timeutils.utcnow()
def refresh(self):
self._load_hash_ring(refresh=True)
def get_node(self, key):
self._load_hash_ring()
# tooz expects a byte string for the hash
if isinstance(key, six.string_types):
key = key.encode('utf-8')
try:
# We need to pop the value from the set. If empty,
# KeyError is raised
return self._hash_ring[key].pop()
except KeyError:
raise exceptions.HashRingIsEmpty(key=key)