diff --git a/conf/minion b/conf/minion index a54f1659a79..70cbe8934a4 100644 --- a/conf/minion +++ b/conf/minion @@ -271,9 +271,8 @@ #ping_interval: 0 # To auto recover minions if master changes IP address (DDNS) -# auth_tries: 10 -# auth_safemode: True -# ping_interval: 2 +# master_alive_interval: 10 +# master_tries: -1 # # Minions won't know master is missing until a ping fails. After the ping fail, # the minion will attempt authentication and likely fails out and cause a restart. diff --git a/doc/ref/configuration/minion.rst b/doc/ref/configuration/minion.rst index 0f99da2f1c0..925b54cc47f 100644 --- a/doc/ref/configuration/minion.rst +++ b/doc/ref/configuration/minion.rst @@ -291,7 +291,9 @@ Default: ``0`` Configures how often, in seconds, the minion will verify that the current master is alive and responding. The minion will try to establish a connection -to the next master in the list if it finds the existing one is dead. +to the next master in the list if it finds the existing one is dead. This +setting can also be used to detect master DNS record changes when a minion has +been disconnected. .. code-block:: yaml diff --git a/tests/pytests/scenarios/dns/conftest.py b/tests/pytests/scenarios/dns/conftest.py index e872bda6885..254e8ee9a28 100644 --- a/tests/pytests/scenarios/dns/conftest.py +++ b/tests/pytests/scenarios/dns/conftest.py @@ -7,6 +7,11 @@ import pytest log = logging.getLogger(__name__) +@pytest.fixture(scope="package") +def master_alive_interval(): + return 5 + + class HostsFile: """ Simple helper class for tests that need to modify /etc/hosts. @@ -70,7 +75,7 @@ def salt_cli(master): @pytest.fixture(scope="package") -def minion(master): +def minion(master, master_alive_interval): config_defaults = { "transport": master.config["transport"], } @@ -78,9 +83,7 @@ def minion(master): config_overrides = { "master": f"master.local:{port}", "publish_port": master.config["publish_port"], - "master_alive_interval": 5, - "master_tries": -1, - "auth_safemode": False, + "master_alive_interval": master_alive_interval, } factory = master.salt_minion_daemon( "minion", diff --git a/tests/pytests/scenarios/dns/multimaster/conftest.py b/tests/pytests/scenarios/dns/multimaster/conftest.py index 6b948557dbe..3b50ed65c60 100644 --- a/tests/pytests/scenarios/dns/multimaster/conftest.py +++ b/tests/pytests/scenarios/dns/multimaster/conftest.py @@ -86,26 +86,23 @@ def mm_master_2_salt_cli(salt_mm_master_2): @pytest.fixture(scope="package") -def salt_mm_minion_1(salt_mm_master_1, salt_mm_master_2): +def salt_mm_minion_1(salt_mm_master_1, salt_mm_master_2, master_alive_interval): config_defaults = { "transport": salt_mm_master_1.config["transport"], } mm_master_1_port = salt_mm_master_1.config["ret_port"] - # mm_master_1_addr = salt_mm_master_1.config["interface"] mm_master_2_port = salt_mm_master_2.config["ret_port"] - # mm_master_2_addr = salt_mm_master_2.config["interface"] config_overrides = { "master": [ f"master1.local:{mm_master_1_port}", f"master2.local:{mm_master_2_port}", ], "publish_port": salt_mm_master_1.config["publish_port"], - # "master_type": "failover", - "master_alive_interval": 5, + "master_alive_interval": master_alive_interval, "master_tries": -1, "verify_master_pubkey_sign": True, - "retry_dns": 1, + "retry_dns": True, } factory = salt_mm_master_1.salt_minion_daemon( "mm-minion-1", @@ -120,41 +117,3 @@ def salt_mm_minion_1(salt_mm_master_1, salt_mm_master_2): ) # with factory.started(start_timeout=180): yield factory - - -@pytest.fixture(scope="package") -def salt_mm_minion_2(salt_mm_master_1, salt_mm_master_2): - config_defaults = { - "transport": salt_mm_master_1.config["transport"], - } - - mm_master_1_port = salt_mm_master_1.config["ret_port"] - mm_master_1_addr = salt_mm_master_1.config["interface"] - mm_master_2_port = salt_mm_master_2.config["ret_port"] - mm_master_2_addr = salt_mm_master_2.config["interface"] - # We put the second master first in the list so it has the right startup checks every time. - config_overrides = { - "master": [ - f"{mm_master_2_addr}:{mm_master_2_port}", - f"{mm_master_1_addr}:{mm_master_1_port}", - ], - "publish_port": salt_mm_master_1.config["publish_port"], - "master_type": "failover", - "master_alive_interval": 5, - "master_tries": -1, - "verify_master_pubkey_sign": True, - "retry_dns": 1, - } - factory = salt_mm_master_2.salt_minion_daemon( - "mm-failover-minion-2", - defaults=config_defaults, - overrides=config_overrides, - extra_cli_arguments_after_first_start_failure=["--log-level=info"], - ) - # Need to grab the public signing key from the master, either will do - shutil.copyfile( - os.path.join(salt_mm_master_1.config["pki_dir"], "master_sign.pub"), - os.path.join(factory.config["pki_dir"], "master_sign.pub"), - ) - # with factory.started(start_timeout=180): - yield factory diff --git a/tests/pytests/scenarios/dns/multimaster/test_dns.py b/tests/pytests/scenarios/dns/multimaster/test_dns.py index 4cc9db80718..5e0fc4c80f7 100644 --- a/tests/pytests/scenarios/dns/multimaster/test_dns.py +++ b/tests/pytests/scenarios/dns/multimaster/test_dns.py @@ -9,7 +9,12 @@ log = logging.getLogger(__name__) @pytest.mark.skip_unless_on_linux def test_multimaster_dns( - salt_mm_master_1, salt_mm_minion_1, mm_master_1_salt_cli, etc_hosts, caplog + salt_mm_master_1, + salt_mm_minion_1, + mm_master_1_salt_cli, + etc_hosts, + caplog, + master_alive_interval, ): """ Verify a minion configured with multimaster hot/hot will pick up a master's @@ -26,13 +31,15 @@ def test_multimaster_dns( with caplog.at_level(logging.INFO): ret = mm_master_1_salt_cli.run("test.ping", minion_tgt="mm-minion-1") assert ret.returncode == 0 - log.info("Removing secondary master IP address.") etc_hosts.write_text( f"{etc_hosts.orig_text}\n127.0.0.1 master1.local master2.local" ) - subprocess.check_output(["ip", "addr", "del", "172.16.0.1/32", "dev", "lo"]) log.info("Changed hosts record for master1.local and master2.local") - time.sleep(15) + subprocess.check_output(["ip", "addr", "del", "172.16.0.1/32", "dev", "lo"]) + log.info("Removed secondary master IP address.") + # Wait for the minion's master_alive_interval, adding a second for + # reliablity. + time.sleep(master_alive_interval + 1) assert ( "Master ip address changed from 172.16.0.1 to 127.0.0.1" in caplog.text ) diff --git a/tests/pytests/scenarios/dns/test_dns.py b/tests/pytests/scenarios/dns/test_dns.py index 467fb7c51f1..df19d928c0f 100644 --- a/tests/pytests/scenarios/dns/test_dns.py +++ b/tests/pytests/scenarios/dns/test_dns.py @@ -8,7 +8,7 @@ log = logging.getLogger(__name__) @pytest.mark.skip_unless_on_linux -def test_dns_change(master, minion, salt_cli, etc_hosts, caplog): +def test_dns_change(master, minion, salt_cli, etc_hosts, caplog, master_alive_interval): """ Verify a minion will pick up a master's dns change if it's been disconnected. """ @@ -20,8 +20,12 @@ def test_dns_change(master, minion, salt_cli, etc_hosts, caplog): ret = salt_cli.run("test.ping", minion_tgt="minion") assert ret.returncode == 0 etc_hosts.write_text(f"{etc_hosts.orig_text}\n127.0.0.1 master.local") + log.info("Changed hosts record for master1.local and master2.local") subprocess.check_output(["ip", "addr", "del", "172.16.0.1/32", "dev", "lo"]) - time.sleep(15) + log.info("Removed secondary master IP address.") + # Wait for the minion's master_alive_interval, adding a second for + # reliablity. + time.sleep(master_alive_interval + 1) assert ( "Master ip address changed from 172.16.0.1 to 127.0.0.1" in caplog.text )