Merge "Raise file limits to allow max-connections >4190"

This commit is contained in:
Zuul 2020-12-17 20:11:22 +00:00 committed by Gerrit Code Review
commit eac7bceb0c
3 changed files with 137 additions and 13 deletions

View File

@ -51,6 +51,7 @@ from charmhelpers.core.host import (
mkdir, mkdir,
CompareHostReleases, CompareHostReleases,
pwgen, pwgen,
init_is_systemd
) )
from charmhelpers.core.templating import render from charmhelpers.core.templating import render
from charmhelpers.fetch import ( from charmhelpers.fetch import (
@ -171,6 +172,8 @@ RES_MONITOR_PARAMS = ('params user="sstuser" password="%(sstpass)s" '
'OCF_CHECK_LEVEL="1" ' 'OCF_CHECK_LEVEL="1" '
'meta migration-threshold=INFINITY failure-timeout=5s') 'meta migration-threshold=INFINITY failure-timeout=5s')
SYSTEMD_OVERRIDE_PATH = '/etc/systemd/system/mysql.service.d/charm-nofile.conf'
MYSQL_SOCKET = "/var/run/mysqld/mysqld.sock" MYSQL_SOCKET = "/var/run/mysqld/mysqld.sock"
@ -216,6 +219,24 @@ def install():
install_mysql_ocf() install_mysql_ocf()
def render_override(ctx):
# max_connections/table_open_cache are shrunk to fit within ulimits.
# The following formula is taken from sql/mysqld.cc.
if init_is_systemd():
open_files_limit = max(
(ctx['max_connections'] + 1) + 10 + (ctx['table_open_cache']*2),
(ctx['max_connections'] + 1) * 5,
5000)
if not os.path.exists(os.path.dirname(SYSTEMD_OVERRIDE_PATH)):
os.makedirs(os.path.dirname(SYSTEMD_OVERRIDE_PATH))
pre_hash = file_hash(SYSTEMD_OVERRIDE_PATH)
render(os.path.basename(SYSTEMD_OVERRIDE_PATH),
SYSTEMD_OVERRIDE_PATH,
{'open_files_limit': open_files_limit})
if pre_hash != file_hash(SYSTEMD_OVERRIDE_PATH):
subprocess.check_call(['systemctl', 'daemon-reload'])
def render_config(hosts=None): def render_config(hosts=None):
if hosts is None: if hosts is None:
hosts = [] hosts = []
@ -282,8 +303,10 @@ def render_config(hosts=None):
context.update(PerconaClusterHelper().parse_config()) context.update(PerconaClusterHelper().parse_config())
render(os.path.basename(config_file), config_file, context, perms=0o444) render(os.path.basename(config_file), config_file, context, perms=0o444)
render_override(context)
def render_config_restart_on_changed(hosts, bootstrap=False):
def render_config_restart_on_changed(hosts):
"""Render mysql config and restart mysql service if file changes as a """Render mysql config and restart mysql service if file changes as a
result. result.
@ -295,12 +318,22 @@ def render_config_restart_on_changed(hosts, bootstrap=False):
it is started so long as the new node to be added is guaranteed to have it is started so long as the new node to be added is guaranteed to have
been restarted so as to apply the new config. been restarted so as to apply the new config.
""" """
if is_leader() and not is_leader_bootstrapped():
bootstrap = True
else:
bootstrap = False
config_file = resolve_cnf_file() config_file = resolve_cnf_file()
pre_hash = file_hash(config_file) pre_hash_config = file_hash(config_file)
pre_hash_override = file_hash(SYSTEMD_OVERRIDE_PATH)
render_config(hosts) render_config(hosts)
create_binlogs_directory() create_binlogs_directory()
update_db_rels = False update_db_rels = False
if file_hash(config_file) != pre_hash or bootstrap:
hashes_changed = (file_hash(config_file) != pre_hash_config) or \
(file_hash(SYSTEMD_OVERRIDE_PATH) != pre_hash_override)
if hashes_changed or bootstrap:
if bootstrap: if bootstrap:
bootstrap_pxc() bootstrap_pxc()
# NOTE(dosaboy): this will not actually do anything if no cluster # NOTE(dosaboy): this will not actually do anything if no cluster
@ -589,8 +622,7 @@ def config_changed():
log("Leader unit - bootstrap required={}" log("Leader unit - bootstrap required={}"
.format(not leader_bootstrapped), .format(not leader_bootstrapped),
DEBUG) DEBUG)
render_config_restart_on_changed(hosts, render_config_restart_on_changed(hosts)
bootstrap=not leader_bootstrapped)
elif (leader_bootstrapped and elif (leader_bootstrapped and
is_sufficient_peers() and not is_sufficient_peers() and not
cluster_series_upgrading): cluster_series_upgrading):

View File

@ -0,0 +1,2 @@
[Service]
LimitNOFILE={{ open_files_limit }}

View File

@ -502,16 +502,14 @@ class TestConfigChanged(CharmTestCase):
self.get_cluster_hosts.return_value = [] self.get_cluster_hosts.return_value = []
hooks.config_changed() hooks.config_changed()
self.install_percona_xtradb_cluster.assert_called_once() self.install_percona_xtradb_cluster.assert_called_once()
self.render_config_restart_on_changed.assert_called_once_with( self.render_config_restart_on_changed.assert_called_once_with([])
[], bootstrap=True)
# Render without peers, leader bootstrapped # Render without peers, leader bootstrapped
self.is_leader_bootstrapped.return_value = True self.is_leader_bootstrapped.return_value = True
self.get_cluster_hosts.return_value = [] self.get_cluster_hosts.return_value = []
self.render_config_restart_on_changed.reset_mock() self.render_config_restart_on_changed.reset_mock()
hooks.config_changed() hooks.config_changed()
self.render_config_restart_on_changed.assert_called_once_with( self.render_config_restart_on_changed.assert_called_once_with([])
[], bootstrap=False)
# Render without hosts, leader bootstrapped, never clustered # Render without hosts, leader bootstrapped, never clustered
self.is_leader_bootstrapped.return_value = True self.is_leader_bootstrapped.return_value = True
@ -519,8 +517,7 @@ class TestConfigChanged(CharmTestCase):
self.render_config_restart_on_changed.reset_mock() self.render_config_restart_on_changed.reset_mock()
hooks.config_changed() hooks.config_changed()
self.render_config_restart_on_changed.assert_called_once_with( self.render_config_restart_on_changed.assert_called_once_with([])
[], bootstrap=False)
# Clustered at least once # Clustered at least once
self.clustered_once.return_value = True self.clustered_once.return_value = True
@ -532,7 +529,7 @@ class TestConfigChanged(CharmTestCase):
self.render_config_restart_on_changed.reset_mock() self.render_config_restart_on_changed.reset_mock()
hooks.config_changed() hooks.config_changed()
self.render_config_restart_on_changed.assert_called_once_with( self.render_config_restart_on_changed.assert_called_once_with(
['10.10.10.20', '10.10.10.30'], bootstrap=False) ['10.10.10.20', '10.10.10.30'])
# In none of the prior scenarios should update_root_password have been # In none of the prior scenarios should update_root_password have been
# called. # called.
@ -546,7 +543,7 @@ class TestConfigChanged(CharmTestCase):
self.render_config_restart_on_changed.reset_mock() self.render_config_restart_on_changed.reset_mock()
hooks.config_changed() hooks.config_changed()
self.render_config_restart_on_changed.assert_called_once_with( self.render_config_restart_on_changed.assert_called_once_with(
['10.10.10.20', '10.10.10.30'], bootstrap=False) ['10.10.10.20', '10.10.10.30'])
self.update_root_password.assert_called_once() self.update_root_password.assert_called_once()
def test_config_changed_render_non_leader(self): def test_config_changed_render_non_leader(self):
@ -844,6 +841,7 @@ class TestConfigs(CharmTestCase):
TO_PATCH = [ TO_PATCH = [
'config', 'config',
'is_leader', 'is_leader',
'render_override',
] ]
def setUp(self): def setUp(self):
@ -1062,6 +1060,98 @@ class TestConfigs(CharmTestCase):
perms=0o444) perms=0o444)
class TestRenderConfigRestartOnChanged(CharmTestCase):
TO_PATCH = [
'is_leader',
'is_leader_bootstrapped',
'bootstrap_pxc',
'resolve_cnf_file',
'file_hash',
'render_config',
'create_binlogs_directory',
'bootstrap_pxc',
'notify_bootstrapped',
'service_running',
'service_stop',
'service_restart',
'cluster_wait',
'mark_seeded',
'cluster_wait',
'update_client_db_relations',
]
def setUp(self):
CharmTestCase.setUp(self, hooks, self.TO_PATCH)
self.is_leader.return_value = False
self.is_leader_bootstrapped.return_value = False
self.bootstrap_pxc.return_value = None
self.service_running.return_value = True
self.resolve_cnf_file.return_value = \
'/etc/mysql/percona-xtradb-cluster.conf.d/mysqld.cnf'
self.file_hash.return_value = 'original'
self.service_restart.return_value = True
def _render_config_changed(self, hosts):
self.file_hash.return_value = 'changed'
def test_bootstrap_leader(self):
self.is_leader.return_value = True
self.is_leader_bootstrapped.return_value = False
self.render_config.side_effect = self._render_config_changed
hooks.render_config_restart_on_changed([])
self.bootstrap_pxc.assert_called_once()
self.service_restart.assert_not_called()
def test_bootstrapped_leader(self):
self.is_leader.return_value = True
self.is_leader_bootstrapped.return_value = True
self.render_config.side_effect = self._render_config_changed
hooks.render_config_restart_on_changed([])
self.bootstrap_pxc.assert_not_called()
self.service_restart.assert_called_once()
def test_noleader(self):
self.is_leader.return_value = False
self.is_leader_bootstrapped.return_value = False
self.render_config.side_effect = self._render_config_changed
hooks.render_config_restart_on_changed([])
self.bootstrap_pxc.assert_not_called()
self.service_restart.assert_called_once()
def test_nochange_bootstrap_leader(self):
self.is_leader.return_value = True
self.is_leader_bootstrapped.return_value = False
hooks.render_config_restart_on_changed([])
self.bootstrap_pxc.assert_called_once()
self.service_restart.assert_not_called()
def test_nochange_bootstrapped_leader(self):
self.is_leader.return_value = True
self.is_leader_bootstrapped.return_value = True
hooks.render_config_restart_on_changed([])
self.bootstrap_pxc.assert_not_called()
self.service_restart.assert_not_called()
def test_nochange_noleader(self):
self.is_leader.return_value = False
self.is_leader_bootstrapped.return_value = False
hooks.render_config_restart_on_changed([])
self.bootstrap_pxc.assert_not_called()
self.service_restart.assert_not_called()
class TestClusterRelation(CharmTestCase): class TestClusterRelation(CharmTestCase):
def setUp(self): def setUp(self):