OrchestraRequestClass.php 6.16 KB
<?php 
/**
 * @class OrchestraRequestClass
 * @brief Implementation of a Orchestra request
 
 */
class OrchestraRequestClass extends ProcessRequestClass
{
	private $host = "";
	private $port = "";

	/*
	 * @brief Init a process request of type "run"
	 */
	public function init()
	{	
		if (!isset($this->requestData))
			return false;

		$this->host = OrchestraConfigClass::getHost();
		$this->port = OrchestraConfigClass::getPort();
		if (empty($this->host)) {
			$this->requestData->setLastErrorMessage('Missing orchestra host definition');
			return false;
		}
		$orchestraEntryPoint = $this->host;
		if (!empty($this->port)) {
			$orchestraEntryPoint .= ":".$this->port;
		}

		$orchestraClient = new OrchestraClient($orchestraEntryPoint);

		$params = $this->requestData->getParams();
		switch ($this->requestData->getRequestType()) {
			case OrchestraRequestTypeEnum::CONFIGINFO:
				if (in_array(getenv("REMOTE_ADDR"), OrchestraConfigClass::getAdminIps())) {
					$result = array(
						'success' => TRUE,
						'entrypoint' => $orchestraEntryPoint
					);
				}
				else {
					$result = array(
						'success' => FALSE,
						'message' => 'Forbidden'
					);
				}
				$this->requestData->setOrchestraResult($result);
				break;
			case OrchestraRequestTypeEnum::MODULESLIST:
				$result = $orchestraClient->getModules();
				$this->requestData->setOrchestraResult($result);
				break;
			case OrchestraRequestTypeEnum::MODULEINFO:
				if (!array_key_exists('id', $params)) {
					$this->requestData->setLastErrorMessage('Missing module ID definition');
					return false;
				}
				$result = $orchestraClient->getModuleInfo($params['id']);
				$this->requestData->setOrchestraResult($result);
				break;
			case OrchestraRequestTypeEnum::GETRESULT:
				// Nothing to do
				return true;
			case OrchestraRequestTypeEnum::PREDICTION:
			case OrchestraRequestTypeEnum::FITTING:
				if (!array_key_exists('moduleId', $params)) {
					$this->requestData->setLastErrorMessage('Missing moduleId definition');
					return false;
				}
				if (!array_key_exists('start', $params) || empty($params['start'])) {
					$this->requestData->setLastErrorMessage('Missing start time definition');
					return false;
				}
				if (!array_key_exists('stop', $params) || empty($params['stop'])) {
					$this->requestData->setLastErrorMessage('Missing stop time definition');
					return false;
				}
				return $this->initOrchestraProcess();
			default:
				$this->requestData->setLastErrorMessage('Unknown request type');
				return false;
		}

		return true;
	}

	protected function initOrchestraProcess()
	{
		try {
			$client = new ReflectionClass('OrchestraClient');
			$clientPath = $client->getFileName();
		}
		catch (Exception $e) {
			$this->requestData->setLastErrorMessage('Cannot retrieve OrchestraClient class');
			return false;
		}

		$this->requestData->setCmd("php orchestra_cmd.php");
		if (!parent::init()) {
			return false;
		}

		$params = $this->requestData->getParams();

		// Generate a PHP script to run request (to be able to "detach" process for the batch mode)
		$php_script  = '<?php'.PHP_EOL;
		$php_script .= 'require_once("'.$clientPath.'");'.PHP_EOL;
		$php_script .= '$client = new OrchestraClient("'.$this->host.':'.$this->port.'");'.PHP_EOL;
		$php_script .= '$params = array(';
		$first_param = TRUE;
		foreach ($params as $key => $value) {
			if ($key == 'moduleId')
				continue;
			if (!$first_param)
				$php_script .= ',';
			$first_param = false;
			$php_script .= '"'.$key.'"=>"'.$value.'"';
		}
		$php_script .= ');'.PHP_EOL;
		$php_script .= '$result = $client->runModule("'.$params['moduleId'].'",$params);'.PHP_EOL;
		$php_script .= 'if ($result["success"]) {'.PHP_EOL;
		$php_script .= '        $taskId = $result["result"]->task;'.PHP_EOL;
		$php_script .= '        $result = $client->getTaskInfo($taskId);'.PHP_EOL;
		$php_script .= '        while ($result["success"] && ($result["result"]->status == "running")) {'.PHP_EOL;
		$php_script .= '                sleep(5);'.PHP_EOL;
		$php_script .= '                $result = $client->getTaskInfo($taskId);'.PHP_EOL;
		$php_script .= '        }'.PHP_EOL;
		$php_script .= '}'.PHP_EOL;
		$php_script .= 'file_put_contents("'.$this->requestData->getWorkingPath().'/'.$this->requestData->getOrchestraResult().'", json_encode($result));'.PHP_EOL;
		$php_script .= 'if ($result["success"] && ($result["result"]->status == "done") && !empty($result["result"]->output)) {'.PHP_EOL;
		$php_script .= '        $compressed_output = (count($result["result"]->output) > 1);'.PHP_EOL;
		$php_script .= '        $output_file_path = "'.$this->requestData->getWorkingPath().'/";'.PHP_EOL;
		$php_script .= '        $output_file_path .= $compressed_output ? "outputs.zip" : $result["result"]->output[0];'.PHP_EOL;
		$php_script .= '        $result = $client->getTaskOutput($taskId, $output_file_path);'.PHP_EOL;
		$php_script .= '        if ($result["success"]) {'.PHP_EOL;
		$php_script .= '            if ($compressed_output) {'.PHP_EOL;
		$php_script .= '                exec("cd '.$this->requestData->getWorkingPath().' && unzip outputs.zip");'.PHP_EOL;
		$php_script .= '            }'.PHP_EOL;
		$php_script .= '        }'.PHP_EOL;
		$php_script .= '}'.PHP_EOL;
		$php_script .= '?>';

		file_put_contents($this->requestData->getWorkingPath() . "/orchestra_cmd.php", $php_script);

		return true;
	}
	
	/*
	 * @brief Run a process request
	*/
	
	public function run()
	{
		if (!isset($this->requestData))
			return false;

		$this->requestData->setSuccess(false);
		$this->requestData->setLastErrorMessage('Cannot run Orchestra request');

		if (($this->requestData->getRequestType() == OrchestraRequestTypeEnum::PREDICTION) || ($this->requestData->getRequestType() == OrchestraRequestTypeEnum::FITTING)) {
			$this->requestData->setType(ProcessTypeEnumClass::RUN);
			return parent::run();
		}
		else if ($this->requestData->getRequestType() == OrchestraRequestTypeEnum::GETRESULT) {
			// Nothing to do
			$this->requestData->setSuccess(true);
			return true;
		}
		else {
			$result = $this->requestData->getOrchestraResult();
		}
			 	 
		$this->requestData->setSuccess($result['success']);

		if (!$result['success'])
			$this->requestData->setLastErrorMessage($result['message']);

		return ($result['success']);
	}
	  
}
?>