123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- """
- :copyright: Copyright 2017 by the SaltStack Team, see AUTHORS for more details.
- :license: Apache 2.0, see LICENSE for more details.
- tests.support.processes
- ~~~~~~~~~~~~~~~~~~~~~~~
- Process handling utilities
- """
- import logging
- from saltfactories.utils.processes import ( # pylint: disable=unused-import
- collect_child_processes,
- terminate_process,
- terminate_process_list,
- )
- from tests.support.cli_scripts import ScriptPathMixin, get_script_path
- from tests.support.runtests import RUNTIME_VARS
- try:
- from pytestsalt.fixtures.daemons import Salt as PytestSalt
- from pytestsalt.fixtures.daemons import SaltCall as PytestSaltCall
- from pytestsalt.fixtures.daemons import SaltKey as PytestSaltKey
- from pytestsalt.fixtures.daemons import SaltMaster as PytestSaltMaster
- from pytestsalt.fixtures.daemons import SaltMinion as PytestSaltMinion
- from pytestsalt.fixtures.daemons import SaltProxy as PytestSaltProxy
- from pytestsalt.fixtures.daemons import SaltRun as PytestSaltRun
- from pytestsalt.fixtures.daemons import SaltSyndic as PytestSaltSyndic
- except ImportError:
- # If this happens, we are running under pytest which uninstalls pytest-salt due to impatabilites
- # These imports won't actually work but these classes are only used when running under runtests,
- # so, we're just making sure we also don't hit NameError's
- from tests.support.saltfactories_compat import SaltCallCLI as PytestSaltCall
- from tests.support.saltfactories_compat import SaltCLI as PytestSalt
- from tests.support.saltfactories_compat import SaltKeyCLI as PytestSaltKey
- from tests.support.saltfactories_compat import SaltMaster as PytestSaltMaster
- from tests.support.saltfactories_compat import SaltMinion as PytestSaltMinion
- from tests.support.saltfactories_compat import SaltProxyMinion as PytestSaltProxy
- from tests.support.saltfactories_compat import SaltRunCLI as PytestSaltRun
- from tests.support.saltfactories_compat import SaltSyndic as PytestSaltSyndic
- log = logging.getLogger(__name__)
- class GetSaltRunFixtureMixin(ScriptPathMixin):
- """
- Override this classes `get_salt_run_fixture` because we're still not running under pytest
- """
- def get_salt_run_fixture(self):
- pass
- class Salt(ScriptPathMixin, PytestSalt):
- """
- Class which runs salt-call commands
- """
- def __init__(self, *args, **kwargs):
- super().__init__(None, *args, **kwargs)
- class SaltCall(ScriptPathMixin, PytestSaltCall):
- """
- Class which runs salt-call commands
- """
- def __init__(self, *args, **kwargs):
- super().__init__(None, *args, **kwargs)
- class SaltKey(ScriptPathMixin, PytestSaltKey):
- """
- Class which runs salt-key commands
- """
- def __init__(self, *args, **kwargs):
- super().__init__(None, *args, **kwargs)
- class SaltRun(ScriptPathMixin, PytestSaltRun):
- """
- Class which runs salt-run commands
- """
- def __init__(self, *args, **kwargs):
- super().__init__(None, *args, **kwargs)
- class SaltProxy(GetSaltRunFixtureMixin, PytestSaltProxy):
- """
- Class which runs the salt-proxy daemon
- """
- class SaltMinion(GetSaltRunFixtureMixin, PytestSaltMinion):
- """
- Class which runs the salt-minion daemon
- """
- class SaltMaster(GetSaltRunFixtureMixin, PytestSaltMaster):
- """
- Class which runs the salt-master daemon
- """
- class SaltSyndic(GetSaltRunFixtureMixin, PytestSaltSyndic):
- """
- Class which runs the salt-syndic daemon
- """
- def start_daemon(
- daemon_name=None,
- daemon_id=None,
- daemon_log_prefix=None,
- daemon_cli_script_name=None,
- daemon_config=None,
- daemon_config_dir=None,
- daemon_class=None,
- bin_dir_path=None,
- fail_hard=False,
- start_timeout=10,
- slow_stop=False,
- environ=None,
- cwd=None,
- event_listener_config_dir=None,
- ):
- """
- Returns a running salt daemon
- """
- # Old config name
- daemon_config["pytest_port"] = daemon_config["runtests_conn_check_port"]
- # New config name
- daemon_config["pytest_engine_port"] = daemon_config["runtests_conn_check_port"]
- request = None
- if fail_hard:
- fail_method = RuntimeError
- else:
- fail_method = RuntimeWarning
- log.info("[%s] Starting pytest %s(%s)", daemon_name, daemon_log_prefix, daemon_id)
- attempts = 0
- process = None
- get_script_path(RUNTIME_VARS.TMP_SCRIPT_DIR, daemon_cli_script_name)
- while attempts <= 3: # pylint: disable=too-many-nested-blocks
- attempts += 1
- try:
- process = daemon_class(
- request=request,
- config=daemon_config,
- config_dir=daemon_config_dir,
- bin_dir_path=bin_dir_path,
- log_prefix=daemon_log_prefix,
- cli_script_name=daemon_cli_script_name,
- slow_stop=slow_stop,
- environ=environ,
- cwd=cwd,
- event_listener_config_dir=event_listener_config_dir,
- )
- except TypeError:
- process = daemon_class(
- request=request,
- config=daemon_config,
- config_dir=daemon_config_dir,
- bin_dir_path=bin_dir_path,
- log_prefix=daemon_log_prefix,
- cli_script_name=daemon_cli_script_name,
- slow_stop=slow_stop,
- environ=environ,
- cwd=cwd,
- )
- process.start()
- if process.is_alive():
- try:
- connectable = process.wait_until_running(timeout=start_timeout)
- if connectable is False:
- connectable = process.wait_until_running(timeout=start_timeout / 2)
- if connectable is False:
- process.terminate()
- if attempts >= 3:
- fail_method(
- "The pytest {}({}) has failed to confirm running status "
- "after {} attempts".format(
- daemon_name, daemon_id, attempts
- )
- )
- continue
- except Exception as exc: # pylint: disable=broad-except
- log.exception("[%s] %s", daemon_log_prefix, exc, exc_info=True)
- terminate_process(process.pid, kill_children=True, slow_stop=slow_stop)
- if attempts >= 3:
- raise fail_method(str(exc))
- continue
- log.info(
- "[%s] The pytest %s(%s) is running and accepting commands "
- "after %d attempts",
- daemon_log_prefix,
- daemon_name,
- daemon_id,
- attempts,
- )
- break
- else:
- terminate_process(process.pid, kill_children=True, slow_stop=slow_stop)
- continue
- else:
- if process is not None:
- terminate_process(process.pid, kill_children=True, slow_stop=slow_stop)
- raise fail_method(
- "The pytest {}({}) has failed to start after {} attempts".format(
- daemon_name, daemon_id, attempts - 1
- )
- )
- return process
|