PageRenderTime 38ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/scale/lib/action.php

https://gitlab.com/alexprowars/bitrix
PHP | 283 lines | 229 code | 27 blank | 27 comment | 29 complexity | a58b62a4dc30b112fddcfd0abbb9acc1 MD5 | raw file
  1. <?php
  2. namespace Bitrix\Scale;
  3. use Bitrix\Main\IO\File;
  4. use \Bitrix\Main\Localization\Loc;
  5. Loc::loadMessages(__FILE__);
  6. /**
  7. * Class Action
  8. * @package Bitrix\Scale
  9. */
  10. class Action
  11. {
  12. protected $id = "";
  13. protected $userParams = array();
  14. protected $freeParams = array();
  15. protected $actionParams = array();
  16. protected $serverHostname = "";
  17. protected $shellAdapter = null;
  18. protected $result = array();
  19. protected $logLevel = Logger::LOG_LEVEL_INFO;
  20. /**
  21. * @param string $actionId
  22. * @param array $actionParams
  23. * @param string $serverHostname
  24. * @param array $userParams
  25. * @param array $freeParams
  26. * @throws \Bitrix\Main\ArgumentNullException
  27. * @throws \Bitrix\Main\ArgumentTypeException
  28. * @throws \Exception
  29. */
  30. public function __construct($actionId, $actionParams, $serverHostname="", $userParams = array(), $freeParams = array())
  31. {
  32. if($actionId == '')
  33. throw new \Bitrix\Main\ArgumentNullException("actionId");
  34. if(!is_array($actionParams) || empty($actionParams))
  35. throw new \Exception("Params of action ".$actionId." are not defined correctly!");
  36. if(!isset($actionParams["START_COMMAND_TEMPLATE"]) || $actionParams["START_COMMAND_TEMPLATE"] == '')
  37. throw new \Exception("Required param START_COMMAND_TEMPLATE of action ".$actionId." are not defined!");
  38. if(!is_array($userParams))
  39. throw new \Bitrix\Main\ArgumentTypeException("userParams", "array");
  40. if(!is_array($freeParams))
  41. throw new \Bitrix\Main\ArgumentTypeException("freeParams", "array");
  42. $this->id = $actionId;
  43. $this->userParams = $userParams;
  44. $this->freeParams = $freeParams;
  45. $this->actionParams = $actionParams;
  46. $this->serverHostname = $serverHostname;
  47. $this->shellAdapter = new ShellAdapter;
  48. if(isset($actionParams["LOG_LEVEL"]))
  49. $this->logLevel = $actionParams["LOG_LEVEL"];
  50. }
  51. protected function getServerParams()
  52. {
  53. return ServersData::getServer($this->serverHostname);
  54. }
  55. /**
  56. * Makes command for shell action execution
  57. * @param array $inputParams
  58. * @return string - command to execute
  59. * @throws \Bitrix\Main\ArgumentTypeException
  60. */
  61. protected function makeStartCommand($inputParams = array())
  62. {
  63. if(!is_array($inputParams))
  64. throw new \Bitrix\Main\ArgumentTypeException("inputParams", "array");
  65. $retStr = $this->actionParams["START_COMMAND_TEMPLATE"];
  66. foreach ($this->userParams as $key => $paramValue)
  67. {
  68. if($this->actionParams['USER_PARAMS'][$key]['THROUGH_FILE'] == 'Y')
  69. {
  70. if($paramValue <> '')
  71. {
  72. $tmpDir = Helper::getTmpDir();
  73. $tmpFile = $tmpDir.'/.'.randString();
  74. $res = File::putFileContents($tmpFile, $paramValue);
  75. if($res === false)
  76. return '';
  77. $paramValue = $tmpFile;
  78. }
  79. }
  80. $retStr = str_replace('##USER_PARAMS:'.$key.'##', $paramValue, $retStr);
  81. }
  82. if($this->serverHostname <> '' && $this->serverHostname != "global")
  83. {
  84. $serverParams = $this->getServerParams();
  85. $serverParams["hostname"] = $this->serverHostname;
  86. if(is_array($serverParams))
  87. {
  88. foreach ($serverParams as $key => $paramValue)
  89. {
  90. if(is_string($paramValue))
  91. {
  92. $retStr = str_replace('##SERVER_PARAMS:' . $key . '##', $paramValue, $retStr);
  93. }
  94. }
  95. }
  96. }
  97. if(!empty($inputParams))
  98. foreach ($inputParams as $key => $paramValue)
  99. $retStr = str_replace('##INPUT_PARAMS:'.$key.'##', $paramValue, $retStr);
  100. if(isset($this->actionParams["CODE_PARAMS"]) && is_array($this->actionParams["CODE_PARAMS"]))
  101. {
  102. foreach($this->actionParams["CODE_PARAMS"] as $paramId => $paramCode)
  103. {
  104. $res = eval($paramCode);
  105. $retStr = str_replace('##CODE_PARAMS:'.$paramId.'##', $res, $retStr);
  106. }
  107. }
  108. foreach ($this->freeParams as $key => $paramValue)
  109. $retStr = str_replace('##'.$key.'##', $paramValue, $retStr);
  110. return $retStr;
  111. }
  112. /**
  113. * Starts the action execution
  114. * @param array $inputParams - params from previously started actions
  115. * @return int code returned by shell
  116. * @throws \Bitrix\Main\ArgumentTypeException
  117. * @throws \Exception
  118. */
  119. public function start(array $inputParams = array())
  120. {
  121. if(!is_array($inputParams))
  122. throw new \Bitrix\Main\ArgumentTypeException("inputParams", "array");
  123. if(isset($this->actionParams["MODIFYERS"]) && is_array($this->actionParams["MODIFYERS"]))
  124. {
  125. $needMoreUserInfo = false;
  126. foreach($this->actionParams["MODIFYERS"] as $modifyerFunction)
  127. {
  128. if(is_callable($modifyerFunction))
  129. {
  130. try
  131. {
  132. $this->actionParams = call_user_func($modifyerFunction, $this->id, $this->actionParams, $this->serverHostname, $this->userParams);
  133. }
  134. catch(NeedMoreUserInfoException $e)
  135. {
  136. $this->actionParams = $e->getActionParams();
  137. $needMoreUserInfo = true;
  138. }
  139. }
  140. }
  141. if($needMoreUserInfo)
  142. throw new NeedMoreUserInfoException("Need more user's info", $this->actionParams);
  143. }
  144. $result = null;
  145. $output = '';
  146. $arOutput = array();
  147. $command = $this->makeStartCommand($inputParams);
  148. if($command <> '')
  149. {
  150. $result = $this->shellAdapter->syncExec($command);
  151. $output = $this->shellAdapter->getLastOutput();
  152. $arOutput = array();
  153. if($output <> '')
  154. {
  155. $arOut = json_decode($output, true);
  156. if(is_array($arOut) && !empty($arOut))
  157. $arOutput = $arOut;
  158. }
  159. //error returned by shell
  160. $error = $this->shellAdapter->getLastError();
  161. //error returned by bitrix-env
  162. if(isset($arOutput["error"]) && intval($arOutput["error"]) > 0 && isset($arOutput["message"]) && $arOutput["message"] <> '')
  163. $error .= " ".$arOutput["message"];
  164. $this->makeLogRecords($command, $result, $output, $error);
  165. }
  166. else //$command == ''
  167. {
  168. $result = false;
  169. $error = 'Cant\'t create command for action execution';
  170. }
  171. $this->result = array(
  172. $this->id => array(
  173. "NAME" => isset($this->actionParams["NAME"]) ? $this->actionParams["NAME"] : "[".$this->id."]",
  174. "RESULT" => $result ? "OK" : "ERROR",
  175. "OUTPUT" => array(
  176. "TEXT" => $output,
  177. "DATA" => $arOutput
  178. ),
  179. "ERROR" => $error
  180. )
  181. );
  182. return $result;
  183. }
  184. /**
  185. * @return array Last command execution results
  186. */
  187. public function getResult()
  188. {
  189. return $this->result;
  190. }
  191. protected function makeLogRecords($command = "", $result = null, $output = "", $error = "")
  192. {
  193. if($command <> '')
  194. {
  195. //cut password data from log records
  196. $preg = "/(-p.*\s+|--mysql_password=.*\s+|--cluster_password=.*\s+|--replica_password=.*\s+|--password=.*\s+)/is";
  197. $command = preg_replace($preg, ' PASS_PARAMS ', $command);
  198. $this->log(
  199. ($result ? Logger::LOG_LEVEL_INFO : Logger::LOG_LEVEL_ERROR),
  200. "SCALE_ACTION_STARTED",
  201. $this->actionParams["NAME"],
  202. $command
  203. );
  204. }
  205. if($result !== null)
  206. {
  207. $this->log(
  208. ($result ? Logger::LOG_LEVEL_INFO : Logger::LOG_LEVEL_ERROR),
  209. "SCALE_ACTION_RESULT",
  210. $this->actionParams["NAME"],
  211. $result ? Loc::getMessage("SCALE_ACTION_RESULT_SUCCESS") : Loc::getMessage("SCALE_ACTION_RESULT_ERROR")
  212. );
  213. }
  214. if($output <> '')
  215. {
  216. $this->log(
  217. Logger::LOG_LEVEL_DEBUG,
  218. "SCALE_ACTION_OUTPUT",
  219. $this->actionParams["NAME"],
  220. $output
  221. );
  222. }
  223. if($error <> '')
  224. {
  225. $this->log(
  226. Logger::LOG_LEVEL_ERROR,
  227. "SCALE_ACTION_ERROR",
  228. $this->actionParams["NAME"],
  229. $error
  230. );
  231. }
  232. }
  233. protected function log($level, $auditType, $actionId, $description)
  234. {
  235. if($this->logLevel < $level)
  236. return false;
  237. return Logger::addRecord($level, $auditType, $actionId, $description);
  238. }
  239. }