{"action":"created","issue":{"url":"https://api.github.com/repos/theforeman/foreman_remote_execution/issues/249","repository_url":"https://api.github.com/repos/theforeman/foreman_remote_execution","labels_url":"https://api.github.com/repos/theforeman/foreman_remote_execution/issues/249/labels{/name}","comments_url":"https://api.github.com/repos/theforeman/foreman_remote_execution/issues/249/comments","events_url":"https://api.github.com/repos/theforeman/foreman_remote_execution/issues/249/events","html_url":"https://github.com/theforeman/foreman_remote_execution/pull/249","id":230412973,"number":249,"title":"Fixes #17514 - Provide asynchronous variant of ssh provider","user":{"login":"adamruzicka","id":7326770,"avatar_url":"https://avatars0.githubusercontent.com/u/7326770?v=4","gravatar_id":"","url":"https://api.github.com/users/adamruzicka","html_url":"https://github.com/adamruzicka","followers_url":"https://api.github.com/users/adamruzicka/followers","following_url":"https://api.github.com/users/adamruzicka/following{/other_user}","gists_url":"https://api.github.com/users/adamruzicka/gists{/gist_id}","starred_url":"https://api.github.com/users/adamruzicka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adamruzicka/subscriptions","organizations_url":"https://api.github.com/users/adamruzicka/orgs","repos_url":"https://api.github.com/users/adamruzicka/repos","events_url":"https://api.github.com/users/adamruzicka/events{/privacy}","received_events_url":"https://api.github.com/users/adamruzicka/received_events","type":"User","site_admin":false},"labels":[{"id":257776738,"url":"https://api.github.com/repos/theforeman/foreman_remote_execution/labels/Needs%20re-review","name":"Needs re-review","color":"0052cc","default":false},{"id":230713075,"url":"https://api.github.com/repos/theforeman/foreman_remote_execution/labels/Needs%20testing","name":"Needs testing","color":"fbca04","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2017-05-22T14:24:47Z","updated_at":"2017-09-06T19:31:44Z","closed_at":null,"author_association":"CONTRIBUTOR","pull_request":{"url":"https://api.github.com/repos/theforeman/foreman_remote_execution/pulls/249","html_url":"https://github.com/theforeman/foreman_remote_execution/pull/249","diff_url":"https://github.com/theforeman/foreman_remote_execution/pull/249.diff","patch_url":"https://github.com/theforeman/foreman_remote_execution/pull/249.patch"},"body":"requires https://github.com/theforeman/foreman-tasks/pull/250 and https://github.com/theforeman/smart_proxy_dynflow/pull/33\r\n\r\n## How does it work?\r\nTODO: Extract to manual later\r\nTODO: Maybe some sequence diagrams?\r\n\r\nWith regular script runner the ssh connection is kept open and data is periodically (every second) read from it. The polling script runner takes a different approach. It copies over to the remote machine the user's script (just `SCRIPT` from now on) and two additional helper scripts (`callback` and `retrieve`). Over the same connection it runs the so-called `control` script, runs the `retrieve` script (to check the command started successfully) and closes the SSH connection. This way, the `SCRIPT` runs on the remote server unsupervised and no persistent connection is maintained. This also means for each run (except the first one) of the `retrieve` a new connection has to be established.\r\n\r\n### so-called `control`\r\nSpawns a new `shell` in background which basically just runs `SCRIPT; callback`, redirecting `SCRIPT`'s output into `output_file` and writing `shell`'s pid into a `pid_file`.\r\n\r\n### `callback`\r\nIt tries to do a POST request using curl to `smart_proxy_dynflow_core`'s API, authenticating with the task's uuid as username and token as password using HTTP basic authentication. This tells the `smart_proxy_dynflow_core` to check on a task using the `retrieve` script.\r\n\r\n### `retrieve`\r\nChecks the status of `shell` using its' pid from `pid_file`, reads new parts of `SCRIPT`'s output from `output_file` and updates `position` file (keeps track of number of bytes read from `output_file`). Outputs information whether script is running or not and the new parts of output.\r\n\r\n### about token\r\n`PollingScriptRunner` requests an one-time password from `ForemanTasksCore::OtpManager` when it initializes. Similarly `smart_proxy_dynflow_core`'s API asks the `OtpManager` if a task_uuid x token combination is valid.\r\n\r\n### dependencies on remote hosts\r\nTo work properly, this needs some utilities to reside on the remote host. Those are mostly common tools, but they may be missing in containers.\r\n- GNU coreutils (tail, expr) - doesn't work with busybox tail\r\n- pgrep\r\n- which\r\n- curl\r\n\r\n## Configuration\r\nThis feature can be enabled on a per-proxy basis by setting `:async_ssh` to `true` in `/etc/smart_proxy_dynflow_core/settings.d/remote_execution_ssh.yml` (TODO: Check if the path is correct). The interval for checking on the remote jobs can be set in the same file under the `runner_refresh_interval` key.\r\n"},"comment":{"url":"https://api.github.com/repos/theforeman/foreman_remote_execution/issues/comments/327589620","html_url":"https://github.com/theforeman/foreman_remote_execution/pull/249#issuecomment-327589620","issue_url":"https://api.github.com/repos/theforeman/foreman_remote_execution/issues/249","id":327589620,"user":{"login":"iNecas","id":190443,"avatar_url":"https://avatars3.githubusercontent.com/u/190443?v=4","gravatar_id":"","url":"https://api.github.com/users/iNecas","html_url":"https://github.com/iNecas","followers_url":"https://api.github.com/users/iNecas/followers","following_url":"https://api.github.com/users/iNecas/following{/other_user}","gists_url":"https://api.github.com/users/iNecas/gists{/gist_id}","starred_url":"https://api.github.com/users/iNecas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iNecas/subscriptions","organizations_url":"https://api.github.com/users/iNecas/orgs","repos_url":"https://api.github.com/users/iNecas/repos","events_url":"https://api.github.com/users/iNecas/events{/privacy}","received_events_url":"https://api.github.com/users/iNecas/received_events","type":"User","site_admin":false},"created_at":"2017-09-06T19:31:44Z","updated_at":"2017-09-06T19:31:44Z","author_association":"MEMBER","body":"One last comment about comment, let's get it in after that"}}
{"actor":{"display_login":"iNecas"}}