PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/cli/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/cli/daemons.py |
""" Make me some salt! """ import logging import os import warnings import salt.utils.kinds as kinds from salt.exceptions import SaltClientError, SaltSystemExit, get_error_message from salt.utils import migrations from salt.utils.platform import is_junos from salt.utils.process import HAS_PSUTIL # All salt related deprecation warnings should be shown once each! warnings.filterwarnings( "once", # Show once "", # No deprecation message match DeprecationWarning, # This filter is for DeprecationWarnings r"^(salt|salt\.(.*))$", # Match module(s) 'salt' and 'salt.<whatever>' append=True, ) # While we are supporting Python2.6, hide nested with-statements warnings warnings.filterwarnings( "ignore", "With-statements now directly support multiple context managers", DeprecationWarning, append=True, ) # Filter the backports package UserWarning about being re-imported warnings.filterwarnings( "ignore", "^Module backports was already imported from (.*), but (.*) is being added to" " sys.path$", UserWarning, append=True, ) # the try block below bypasses an issue at build time so that modules don't # cause the build to fail try: import salt.utils.parsers from salt.utils.network import ip_bracket from salt.utils.verify import check_user, verify_env, verify_socket except ImportError as exc: if exc.args[0] != "No module named _msgpack": raise log = logging.getLogger(__name__) class DaemonsMixin: # pylint: disable=no-init """ Uses the same functions for all daemons """ def verify_hash_type(self): """ Verify and display a nag-messsage to the log if vulnerable hash-type is used. :return: """ if self.config["hash_type"].lower() in ["md5", "sha1"]: log.warning( "IMPORTANT: Do not use %s hashing algorithm! Please set " '"hash_type" to sha256 in Salt %s config!', self.config["hash_type"], self.__class__.__name__, ) def action_log_info(self, action): """ Say daemon starting. :param action :return: """ log.info("%s the Salt %s", action, self.__class__.__name__) def start_log_info(self): """ Say daemon starting. :return: """ log.info("The Salt %s is starting up", self.__class__.__name__) def shutdown_log_info(self): """ Say daemon shutting down. :return: """ log.info("The Salt %s is shut down", self.__class__.__name__) def environment_failure(self, error): """ Log environment failure for the daemon and exit with the error code. :param error: :return: """ log.exception( "Failed to create environment for %s: %s", self.__class__.__name__, get_error_message(error), ) self.shutdown(error) class Master( salt.utils.parsers.MasterOptionParser, DaemonsMixin ): # pylint: disable=no-init """ Creates a master server """ def _handle_signals(self, signum, sigframe): if hasattr(self.master, "process_manager"): # escalate signal to the process manager processes self.master.process_manager._handle_signals(signum, sigframe) super()._handle_signals(signum, sigframe) def verify_environment(self): if not self.config["verify_env"]: return v_dirs = [ self.config["pki_dir"], os.path.join(self.config["pki_dir"], "minions"), os.path.join(self.config["pki_dir"], "minions_pre"), os.path.join(self.config["pki_dir"], "minions_denied"), os.path.join(self.config["pki_dir"], "minions_autosign"), os.path.join(self.config["pki_dir"], "minions_rejected"), self.config["cachedir"], os.path.join(self.config["cachedir"], "jobs"), os.path.join(self.config["cachedir"], "proc"), self.config["sock_dir"], self.config["token_dir"], self.config["syndic_dir"], self.config["sqlite_queue_dir"], ] pki_dir = self.config["pki_dir"] if ( self.config["cluster_id"] and self.config["cluster_pki_dir"] and self.config["cluster_pki_dir"] != self.config["pki_dir"] ): v_dirs.extend( [ self.config["cluster_pki_dir"], os.path.join(self.config["cluster_pki_dir"], "peers"), os.path.join(self.config["cluster_pki_dir"], "minions"), os.path.join(self.config["cluster_pki_dir"], "minions_pre"), os.path.join(self.config["cluster_pki_dir"], "minions_denied"), os.path.join(self.config["cluster_pki_dir"], "minions_autosign"), os.path.join(self.config["cluster_pki_dir"], "minions_rejected"), ] ) pki_dir = [self.config["pki_dir"], self.config["cluster_pki_dir"]] verify_env( v_dirs, self.config["user"], permissive=self.config["permissive_pki_access"], root_dir=self.config["root_dir"], pki_dir=pki_dir, ) def prepare(self): """ Run the preparation sequence required to start a salt master server. If sub-classed, don't **ever** forget to run: super(YourSubClass, self).prepare() """ super().prepare() try: self.verify_environment() except OSError as error: self.environment_failure(error) self.action_log_info("Setting up") # TODO: AIO core is separate from transport if not verify_socket( self.config["interface"], self.config["publish_port"], self.config["ret_port"], ): self.shutdown(4, "The ports are not available to bind") self.config["interface"] = ip_bracket(self.config["interface"]) migrations.migrate_paths(self.config) # Late import so logging works correctly import salt.master self.master = salt.master.Master(self.config) self.daemonize_if_required() self.set_pidfile() salt.utils.process.notify_systemd() def start(self): """ Start the actual master. If sub-classed, don't **ever** forget to run: super(YourSubClass, self).start() NOTE: Run any required code before calling `super()`. """ super().start() if check_user(self.config["user"]): self.action_log_info("Starting up") self.verify_hash_type() self.master.start() def shutdown(self, exitcode=0, exitmsg=None): """ If sub-classed, run any shutdown operations on this method. """ self.shutdown_log_info() msg = "The salt master is shutdown. " if exitmsg is not None: exitmsg = msg + exitmsg else: exitmsg = msg.strip() super().shutdown(exitcode, exitmsg) class Minion( salt.utils.parsers.MinionOptionParser, DaemonsMixin ): # pylint: disable=no-init """ Create a minion server """ def _handle_signals(self, signum, sigframe): # pylint: disable=unused-argument # escalate signal to the process manager processes if hasattr(self.minion, "stop"): self.minion.stop(signum) super()._handle_signals(signum, sigframe) # pylint: disable=no-member def prepare(self): """ Run the preparation sequence required to start a salt minion. If sub-classed, don't **ever** forget to run: super(YourSubClass, self).prepare() """ super().prepare() try: if self.config["verify_env"]: confd = self.config.get("default_include") if confd: # If 'default_include' is specified in config, then use it if "*" in confd: # Value is of the form "minion.d/*.conf" confd = os.path.dirname(confd) if not os.path.isabs(confd): # If configured 'default_include' is not an absolute # path, consider it relative to folder of 'conf_file' # (/etc/salt by default) confd = os.path.join( os.path.dirname(self.config["conf_file"]), confd ) else: confd = os.path.join( os.path.dirname(self.config["conf_file"]), "minion.d" ) v_dirs = [ self.config["pki_dir"], self.config["cachedir"], self.config["sock_dir"], self.config["extension_modules"], confd, ] verify_env( v_dirs, self.config["user"], permissive=self.config["permissive_pki_access"], root_dir=self.config["root_dir"], pki_dir=self.config["pki_dir"], ) except OSError as error: self.environment_failure(error) log.info('Setting up the Salt Minion "%s"', self.config["id"]) migrations.migrate_paths(self.config) # Bail out if we find a process running and it matches out pidfile if (HAS_PSUTIL and not self.claim_process_responsibility()) or ( not HAS_PSUTIL and self.check_running() ): self.action_log_info("An instance is already running. Exiting") self.shutdown(1) transport = self.config.get("transport").lower() try: # Late import so logging works correctly import salt.minion # If the minion key has not been accepted, then Salt enters a loop # waiting for it, if we daemonize later then the minion could halt # the boot process waiting for a key to be accepted on the master. # This is the latest safe place to daemonize self.daemonize_if_required() self.set_pidfile() if self.config.get("master_type") == "func": salt.minion.eval_master_func(self.config) self.minion = salt.minion.MinionManager(self.config) except Exception: # pylint: disable=broad-except log.error( "An error occured while setting up the minion manager", exc_info=True ) self.shutdown(1) def start(self): """ Start the actual minion. If sub-classed, don't **ever** forget to run: super(YourSubClass, self).start() NOTE: Run any required code before calling `super()`. """ super().start() while True: try: self._real_start() except SaltClientError as exc: # Restart for multi_master failover when daemonized if self.options.daemon: continue break def _real_start(self): try: if check_user(self.config["user"]): self.action_log_info("Starting up") self.verify_hash_type() self.minion.tune_in() if self.minion.restart: raise SaltClientError("Minion could not connect to Master") except (KeyboardInterrupt, SaltSystemExit) as error: self.action_log_info("Stopping") if isinstance(error, KeyboardInterrupt): log.warning("Exiting on Ctrl-c") self.shutdown() else: log.error(error) self.shutdown(error.code) def call(self, cleanup_protecteds): """ Start the actual minion as a caller minion. cleanup_protecteds is list of yard host addresses that should not be cleaned up this is to fix race condition when salt-caller minion starts up If sub-classed, don't **ever** forget to run: super(YourSubClass, self).start() NOTE: Run any required code before calling `super()`. """ try: self.prepare() if check_user(self.config["user"]): self.minion.opts["__role"] = kinds.APPL_KIND_NAMES[ kinds.applKinds.caller ] self.minion.call_in() except (KeyboardInterrupt, SaltSystemExit) as exc: self.action_log_info("Stopping") if isinstance(exc, KeyboardInterrupt): log.warning("Exiting on Ctrl-c") self.shutdown() else: log.error(exc) self.shutdown(exc.code) def shutdown(self, exitcode=0, exitmsg=None): """ If sub-classed, run any shutdown operations on this method. :param exitcode :param exitmsg """ self.action_log_info("Shutting down") if hasattr(self, "minion") and hasattr(self.minion, "destroy"): self.minion.destroy() super().shutdown( exitcode, ( "The Salt {} is shutdown. {}".format( self.__class__.__name__, (exitmsg or "") ).strip() ), ) # pylint: enable=no-member class ProxyMinion( salt.utils.parsers.ProxyMinionOptionParser, DaemonsMixin ): # pylint: disable=no-init """ Create a proxy minion server """ def _handle_signals(self, signum, sigframe): # pylint: disable=unused-argument # escalate signal to the process manager processes self.minion.stop(signum) super()._handle_signals(signum, sigframe) # pylint: disable=no-member def prepare(self): """ Run the preparation sequence required to start a salt proxy minion. If sub-classed, don't **ever** forget to run: super(YourSubClass, self).prepare() """ super().prepare() ## allow for native minion if not is_junos(): if not self.values.proxyid: self.error("salt-proxy requires --proxyid") # Proxies get their ID from the command line. This may need to change in # the future. # We used to set this here. Now it is set in ProxyMinionOptionParser # by passing it via setup_config to config.minion_config # self.config['id'] = self.values.proxyid try: if self.config["verify_env"]: confd = self.config.get("default_include") if confd: # If 'default_include' is specified in config, then use it if "*" in confd: # Value is of the form "minion.d/*.conf" confd = os.path.dirname(confd) if not os.path.isabs(confd): # If configured 'default_include' is not an absolute # path, consider it relative to folder of 'conf_file' # (/etc/salt by default) confd = os.path.join( os.path.dirname(self.config["conf_file"]), confd ) else: confd = os.path.join( os.path.dirname(self.config["conf_file"]), "proxy.d" ) v_dirs = [ self.config["pki_dir"], self.config["cachedir"], self.config["sock_dir"], self.config["extension_modules"], confd, ] verify_env( v_dirs, self.config["user"], permissive=self.config["permissive_pki_access"], root_dir=self.config["root_dir"], pki_dir=self.config["pki_dir"], ) except OSError as error: self.environment_failure(error) self.action_log_info('Setting up "{}"'.format(self.config["id"])) migrations.migrate_paths(self.config) # Bail out if we find a process running and it matches out pidfile if self.check_running(): self.action_log_info("An instance is already running. Exiting") self.shutdown(1) # TODO: AIO core is separate from transport # Late import so logging works correctly import salt.minion # If the minion key has not been accepted, then Salt enters a loop # waiting for it, if we daemonize later then the minion could halt # the boot process waiting for a key to be accepted on the master. # This is the latest safe place to daemonize self.daemonize_if_required() self.set_pidfile() if self.config.get("master_type") == "func": salt.minion.eval_master_func(self.config) self.minion = salt.minion.ProxyMinionManager(self.config) def start(self): """ Start the actual proxy minion. If sub-classed, don't **ever** forget to run: super(YourSubClass, self).start() NOTE: Run any required code before calling `super()`. """ super().start() try: if check_user(self.config["user"]): self.action_log_info("The Proxy Minion is starting up") self.verify_hash_type() self.minion.tune_in() if self.minion.restart: raise SaltClientError("Proxy Minion could not connect to Master") except (KeyboardInterrupt, SaltSystemExit) as exc: self.action_log_info("Proxy Minion Stopping") if isinstance(exc, KeyboardInterrupt): log.warning("Exiting on Ctrl-c") self.shutdown() else: log.error(exc) self.shutdown(exc.code) def shutdown(self, exitcode=0, exitmsg=None): """ If sub-classed, run any shutdown operations on this method. :param exitcode :param exitmsg """ if hasattr(self, "minion") and "proxymodule" in self.minion.opts: proxy_fn = self.minion.opts["proxymodule"].loaded_base_name + ".shutdown" self.minion.opts["proxymodule"][proxy_fn](self.minion.opts) self.action_log_info("Shutting down") super().shutdown( exitcode, ( "The Salt {} is shutdown. {}".format( self.__class__.__name__, (exitmsg or "") ).strip() ), ) # pylint: enable=no-member class Syndic( salt.utils.parsers.SyndicOptionParser, DaemonsMixin ): # pylint: disable=no-init """ Create a syndic server """ def prepare(self): """ Run the preparation sequence required to start a salt syndic minion. If sub-classed, don't **ever** forget to run: super(YourSubClass, self).prepare() """ super().prepare() try: if self.config["verify_env"]: verify_env( [ self.config["pki_dir"], self.config["sock_dir"], self.config["extension_modules"], ], self.config["user"], permissive=self.config["permissive_pki_access"], root_dir=self.config["root_dir"], pki_dir=self.config["pki_dir"], ) except OSError as error: self.environment_failure(error) self.action_log_info('Setting up "{}"'.format(self.config["id"])) # Late import so logging works correctly import salt.minion self.daemonize_if_required() self.syndic = salt.minion.SyndicManager(self.config) self.set_pidfile() def start(self): """ Start the actual syndic. If sub-classed, don't **ever** forget to run: super(YourSubClass, self).start() NOTE: Run any required code before calling `super()`. """ super().start() if check_user(self.config["user"]): self.action_log_info("Starting up") self.verify_hash_type() try: self.syndic.tune_in() except KeyboardInterrupt: self.action_log_info("Stopping") self.shutdown() def shutdown(self, exitcode=0, exitmsg=None): """ If sub-classed, run any shutdown operations on this method. :param exitcode :param exitmsg """ self.action_log_info("Shutting down") super().shutdown( exitcode, ( "The Salt {} is shutdown. {}".format( self.__class__.__name__, (exitmsg or "") ).strip() ), )