defexec_lowstate(self, client=None, token=None): # 主要执行函数 """ Pull a Low State data structure from request and execute the low-data chunks through Salt. The low-data chunks will be updated to include the authorization token for the current session. """ lowstate = cherrypy.request.lowstate
# Release the session lock before executing any potentially # long-running Salt commands. This allows different threads to execute # Salt commands concurrently without blocking. if cherrypy.request.config.get("tools.sessions.on", False): cherrypy.session.release_lock()
# if the lowstate loaded isn't a list, lets notify the client ifnotisinstance(lowstate, list): raise cherrypy.HTTPError(400, "Lowstates must be a list")
# Make any requested additions or modifications to each lowstate, then # execute each one and yield the result. for chunk in lowstate: # 是否存在token if token: chunk["token"] = token
if"token"in chunk: # 验证token合法性 # Make sure that auth token is hex try: int(chunk["token"], 16) except (TypeError, ValueError): raise cherrypy.HTTPError(401, "Invalid token")
if client: # 赋值client, chunk["client"] = client
# Make any 'arg' params a list if not already. # This is largely to fix a deficiency in the urlencoded format. if"arg"in chunk andnotisinstance(chunk["arg"], list): chunk["arg"] = [chunk["arg"]]
ret = self.api.run(chunk) # 调用NetapiClient类run函数
# Sometimes Salt gives us a return and sometimes an iterator ifisinstance(ret, Iterator): # 协程 yieldfrom ret else: yield ret
defrun(self, low): """ Execute the specified function in the specified client by passing the lowstate """ # Eauth currently requires a running daemon and commands run through # this method require eauth so perform a quick check to raise a # more meaningful error. ifnot self._is_master_running(): # 查看主守护进程是否正在运行 raise salt.exceptions.SaltDaemonNotRunning("Salt Master is not available.")
classSSH: def__init__(self, opts): """ 大部分初始化省略 """ # If we're in a wfunc, we need to get the ssh key location from the # top level opts, stored in __master_opts__ if"__master_opts__"in self.opts: if self.opts["__master_opts__"].get("ssh_use_home_key") and os.path.isfile( os.path.expanduser("~/.ssh/id_rsa") ): priv = os.path.expanduser("~/.ssh/id_rsa") else: priv = self.opts["__master_opts__"].get( "ssh_priv", os.path.join( self.opts["__master_opts__"]["pki_dir"], "ssh", "salt-ssh.rsa" ), ) else: priv = self.opts.get( "ssh_priv", os.path.join(self.opts["pki_dir"], "ssh", "salt-ssh.rsa") ) # 从opts中获取ssh_priv,opts为输入参数,ssh_priv可控 if priv != "agent-forwarding": ifnot os.path.isfile(priv): # 如果priv变量不是文件就用gen_key函数生成。 try: salt.client.ssh.shell.gen_key(priv) # 命令执行点 except OSError: raise salt.exceptions.SaltClientError( "salt-ssh could not be run because it could not generate keys.\n\n" "You can probably resolve this by executing this script with " "increased permissions via sudo or by running as root.\n" "You could also use the '-c' option to supply a configuration " "directory that you have permissions to read and write to." )