Cache system config in Zookeeper

The Zuul system config consists of the unparsed abide config and runtime
related attributes from the Zuul config file. In order for this config
to be consistent on all active schedulers, we also need to store it in
Zookeeper.

The system config will be updated during processing of a reconfiguration
event. Other schedulers can detect the updated system config and perform
a local update.

Change-Id: I8aaf52cc66aa44a7eb166cc8e277d8499d7bb86a
This commit is contained in:
Simon Westphahl
2021-07-22 15:36:32 +02:00
parent 8aa2ad2db0
commit d5a2becd11
4 changed files with 154 additions and 2 deletions

View File

@@ -21,6 +21,7 @@ from urllib.parse import quote_plus, unquote_plus
from kazoo.exceptions import NoNodeError
from zuul import model
from zuul.zk import sharding, ZooKeeperSimpleBase
from zuul.zk.vendor import lock
@@ -170,3 +171,62 @@ class UnparsedConfigCache(ZooKeeperSimpleBase):
path = _safe_path(self.cache_path, project_cname, branch_name)
with contextlib.suppress(NoNodeError):
self.kazoo_client.delete(path, recursive=True)
class SystemConfigCache(ZooKeeperSimpleBase):
"""Zookeeper cache for Zuul system configuration.
The system configuration consists of the unparsed abide config and
the runtime related settings from the Zuul config file.
"""
SYSTEM_ROOT = "/zuul/system"
log = logging.getLogger("zuul.zk.SystemConfigCache")
def __init__(self, client):
super().__init__(client)
self.conf_path = f"{self.SYSTEM_ROOT}/conf"
self.lock_path = f"{self.SYSTEM_ROOT}/conf-lock"
@property
def ltime(self):
with lock.ReadLock(self.kazoo_client, self.lock_path):
zstat = self.kazoo_client.exists(self.conf_path)
return -1 if zstat is None else zstat.last_modified_transaction_id
@property
def is_valid(self):
return self.ltime > 0
def get(self):
"""Get the system configuration from Zookeeper.
:returns: A tuple (unparsed abide config, system attributes)
"""
with lock.ReadLock(self.kazoo_client, self.lock_path):
try:
with sharding.BufferedShardReader(
self.kazoo_client, self.conf_path
) as stream:
data = json.loads(stream.read())
except Exception:
raise RuntimeError("No valid system config")
zstat = self.kazoo_client.exists(self.conf_path)
return (model.UnparsedAbideConfig.fromDict(
data["unparsed_abide"],
ltime=zstat.last_modified_transaction_id
), model.SystemAttributes.fromDict(data["system_attributes"]))
def set(self, unparsed_abide, system_attributes):
with lock.WriteLock(self.kazoo_client, self.lock_path):
data = {
"unparsed_abide": unparsed_abide.toDict(),
"system_attributes": system_attributes.toDict(),
}
with sharding.BufferedShardWriter(
self.kazoo_client, self.conf_path
) as stream:
stream.truncate(0)
stream.write(json.dumps(data).encode("utf8"))
zstat = self.kazoo_client.exists(self.conf_path)
unparsed_abide.ltime = zstat.last_modified_transaction_id