-
Notifications
You must be signed in to change notification settings - Fork 897
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add #raw_stdout_via_worker method #16441
Conversation
:priority => MiqQueue::HIGH_PRIORITY, | ||
:role => 'embedded_ansible'} | ||
taskid = MiqTask.generic_action_with_callback(options, queue_options) | ||
MiqTask.wait_for_taskid(taskid) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this would block the UI.
We have an initiate_wait_for_task
in ApplicationController... which causes the browser to poll a the task and call a specific action when done.
But you probably can't use it either because that would block the whole summary screen from appearing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can tell, the only safe way of doing that would be to implement the bit in JS - that is:
- render the summary screen, with the stdout field empty, and initiate that task
- replace the html of that field with a component which knows (as a parameter) which task it's waiting for
- that JS component would keep polling the API for the task to complete (needs Wait for task in JS manageiq-ui-classic#2218 -
API.wait_for_task
) - once done, it would display the result
That way, this can error nicely if the server is not available, but won't block all the other stuff from appearing.
(But note that caching the info on the server, same as everything else, would be much much cleaner from the perspective of UI changes involved.)
I can help with the component :) (or the UI bits in general :)).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(So whereas all the other fields come from the server as..
<tr class="no-hover" onclick="" title="">
<td class="label">
MAC Address
</td>
<td>
00:50:56:8c:8b:00
</td>
</tr>
this would come more as...
<tr class="no-hover" onclick="" title="">
<td class="label">
Raw Stdout</td>
<td>
<raw-stdout task-id="12345"></raw-stdout>
</td>
</tr>
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@himdel What I have is a replacement of current method. I agree a non-blocking method is better. Will a MiqTask sufficient for your proposed work in JS? Can UI simply call MiqTask.generic_action_with_callback
? If yes then this PR is not needed at all.
I don't understand the part of caching info on the server. Can you explain with more details?
Lastly, the output in general can be large. I think we want to destroy the MiqTask after UI gets the text.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aah, OK, I'll update the PR to do that, thanks :)
(Just to be sure .. you do mean any job, not any ansible job, right? Because .. in the UI, this is a job associated with the service.. so.. really potentially any job at all.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The context is embedded ansible playbook. The job is ansible tower job, not Miq Job.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point is .. this is a job belonging to a service.
Looking at a random service, I can't know the job will be an embedded ansible playbook job. All I know is, it will be a job.
But if you think using the supports mixin here is wrong, I can add an explicit @record.type == 'ServiceAnsiblePlaybook'
... iff you're sure that:
- any service of type ServiceAnsiblePlaybook will return a job which has the method whenever you call
.job
, regardless of the other argument. - no other type of service should show anything like that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This applies to ServiceAnsiblePlaybook
only, as already in https://github.com/ManageIQ/manageiq-ui-classic/pull/2708/files#diff-ef007b9d34027eeec429c666e2186d8eL37. A random service will not provide a job object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, both ServiceAnsiblePlaybook
and ServiceAnsibleTower
provide a job
method.
Disregardign the latter (because you're right, we do check that type already), ServiceAnsiblePlaybook
's job
method looks for any resource of the kind OrchestrationStack
.
Since OrchestrationStack#raw_stdout_via_worker
definitely fails, leaving only that type
check seems very brittle (sounds like a "this can't happen, but we'll it hit immediately after the next release" :)).
|
||
# Intend to be called by UI to display stdout. Therefore the error message directly returned | ||
# instead of raising an exception. | ||
def raw_stdout_via_worker(userid = User.current_user, format = 'txt') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the argument order could be reversed here - the UI will never need to provide a different userid, but does need to provide a format.
return "Cannot get standard output of this playbook because the embedded Ansible role is not enabled" | ||
end | ||
|
||
options = {:userid => userid, :action => 'ansible_stdout'} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be something wrong here.. the resulting task (accessed via the API) gives me...
userid: "#<User:0x00007fdd65fc6c38>"
@bzwei I created ManageIQ/manageiq-ui-classic#2708 depending on this PR (with some changes).. Looks like it gets as far as trying to query the task :). (I don't currently have an ansible working.. any chance you know how a sucessfully done task will look in the API output? (Currently the component in that PR just assumes it gets the right data, directly as a string, which is possibly wrong.)) |
@himdel If the UI takes only the task_id, what's the plan to destroy the task? |
@bzwei I'm hoping you know :). From what I can see, other UI code which needs to clean up tasks after itself does... def store_for_import(file_contents)
import_file_upload = ImportFileUpload.create
import_file_upload.store_binary_data_as_yml(file_contents, "Automation import")
import_file_upload
ensure
queue_deletion(import_file_upload.id)
end
def queue_deletion(import_file_upload_id)
MiqQueue.put(
:class_name => "ImportFileUpload",
:instance_id => import_file_upload_id,
:deliver_on => 1.day.from_now,
:method_name => "destroy"
)
end ... so, it immediately queues a removal, to happen a day from then. I'm not sure that's the best we could do though :). Another option would be to make the component explicitly delete that task once it finishes retrieving the data - but we would need API support for that. |
BTW another consideration is... if you run I'm asking because you seemed concerned about the task size - so possibly creating 2 such tasks whenever anyone views a service detail screen is not perfect. (But that brings us back to caching, so not sure if you want to go there.) |
The main consideration is the output size. All output are already stored in embedded tower, and they can be very big. It makes no sense to cache them another copy in VMDB. Embedded tower is local or within the zone, so the latency is expected to be minimal. |
We would need to cache the So yeah, I agree we should be removing the task immediately.. which means we'll need API support for that (already pinged the api room, and created ManageIQ/manageiq-api#203).
Agreed, if that becomes relevant, we can just make the component be able to trigger the task creation .. and this PR would be needed either way (+ one to trigger the task from the API) |
@himdel I pushed an update. I leave the argument as |
Thanks.. that should be all we need :). Can you add an example of the error and success task outputs? |
When a stdout exists, it can be retrieved through
When failed to get stdout, the error message can be retrieved through
The caller thus can check |
# Since the task_results may contain a large block of data, it is desired to remove the task upon receiving the data | ||
def raw_stdout_via_worker(userid, format = 'txt') | ||
unless MiqRegion.my_region.role_active?("embedded_ansible") | ||
msg = "Cannot get standard output of this playbook because the embedded Ansible role is not enabled" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing i18n? This needs to be at least N_
, if you think _(
would be wrong.
Checked commits bzwei/manageiq@be61127~...8946174 with ruby 2.3.3, rubocop 0.47.1, haml-lint 0.20.0, and yamllint 1.10.0 |
@bzwei sorry, I didn't express myself clearly :). I'm not asking how to retrieve the data, I am asking how the data actually looks when it is there (is task_results an object, or is it a string? If it's a hash, which field contains the string..) For example, when the role is not enabled, what I will see in the API is:
What I'm asking is the same thing for a sucessfully run task. |
The result is always a string. If you request html, it is a string in html format. |
...
Is this really that much to ask? I'm assuming you tested this, so it should be trivial for you to look at the task and provide the info I'm asking for, shouldn't it? If you're not willing to do that, please tell me, I'll take the time to get ansible working instead. But... just to be really clear... what I'm asking for is: |
@himdel I did not realize you wanted a sample of API call. Here is what I got. The results are like what has been described above
|
@bzwei Thanks, that really helps :) Updating the PR to match this.. |
Add #raw_stdout_via_worker method (cherry picked from commit 1c98131)
Gaprindashvili backport details:
|
@miq-bot add_label fine/yes |
@miq-bot remove_label gaprindashvili/yes |
@miq-bot remove_label fine/yes |
Add
Job#raw_stdout_via_worker
method mainly used by UI to get and display a standard output from an Ansible job. The implementation detects whether the embedded role is enabled and gets the output through the embedded ansible worker.An error message is returned when it fails to get the stdout, so the caller does not need to rescue an error.
Solves ManageIQ/manageiq-ui-classic#2470