Skip to content
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 support for pre/post-migration playbook #355

Merged

Conversation

ghost
Copy link

@ghost ghost commented Jul 10, 2018

This PR adds support to call playbooks in pre and post migration phases. The implementation is generic to allow calling playbooks for other hooks. The backend provides methods to get the service template associated to pre and post hooks. The LaunchPlaybookAsAService method call create_provision_request and stores the request id in the task options hash. The CheckPlaybookAsAService method checks the status of the request. It gracefully fails if the playbook fails in post migration.

The CheckPlaybookAsAService method also updates the Ansible Tower job status in the task options hash, so that the UI can display it and also collect the job output.

Unfortunately, the test to check whether the destination VM is on was introduced inconsistency. It used the oVirt SDK gem to get the information from the provider. It was meant to be faster than wait for refresh. However, with targeted refresh, the power state is reported fast. So I changed the test to use destination_vm.power_state == 'on'. Without it the post migration playbook could be skipped due to race condition.

This PR adds add the following attributes to task options hash (example):

"pre_ansible_playbook_service_request_id" => 3,
:playbooks => {
    "pre": {
      :job_state => "finished",
      :job_status => "Ok",
      :job_id => 4
    },
    "post": {
      :job_state => "pending"
    }
}

Associated RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1564250

@miq-bot miq-bot added the wip label Jul 10, 2018
@ghost
Copy link
Author

ghost commented Jul 10, 2018

@miq-bot add-label transformation

@miq-bot miq-bot added the v2v label Jul 10, 2018
@ghost
Copy link
Author

ghost commented Jul 10, 2018

@miq-bot add-label enhancement

service_request_task = service_request.miq_request_tasks.first
unless service_request_task.nil?
stack = service_request_task.destination.service_resources.first
job = stack.resource unless stack.nil?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stack is already the ansible job instance. There is no stack.resource method.

service_request_id = task.get_option("#{transformation_hook}_ansible_playbook_service_request_id")
service_request = @handle.vmdb(:miq_request).find_by(:id => service_request_id)

set_ansible_job(task, service_request, transformation_hook)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not drill down to examine the ansible job every time. You should rely on the service request_state. Only after the service completes you can fetch the ansible job status just one time.

@ghost
Copy link
Author

ghost commented Jul 11, 2018

@bzwei
Thanks for the advice. Indeed it can be lighter and the state and status can be those of the request. The job is only useful when the request is finished.

@mturley
Copy link

mturley commented Jul 13, 2018

Part of the front-end support (the Overview page parts) for this will be merged with ManageIQ/manageiq-v2v#467 within the next day or two. The rest is already merge-ready I believe, as soon as this merges we should be all set end-to-end!

@ghost
Copy link
Author

ghost commented Jul 13, 2018

@miq-bot add-label gaprindashvili/yes

@ghost ghost changed the title [WIP] Add support for pre/post-migration playbook Add support for pre/post-migration playbook Jul 13, 2018
@miq-bot miq-bot removed the wip label Jul 13, 2018
playbooks_status[transformation_hook][:job_status] = service_request.status
playbooks_status[transformation_hook][:job_id] = service_request.miq_request_tasks.first.destination.service_resources.first.resource.id
task.set_option(:playbooks, playbooks_status)
if service_request.status == 'Error' && transformation_hook == 'pre'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fdupont-redhat is it intentional to ignore the errors for post playbooks?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkanoor
Yes, it is. We consider that the migration has gone far enough to not cancel it for a post migration playbook failure. The playbook or any other problem can be fixed afterwards, with a warning message. The UI knows that the playbook has failed, and it can show the log to the user.

if service_request.request_state == 'finished'
@handle.log(:info, "Ansible playbook service request (id: #{service_request_id}) is finished.")
playbooks_status[transformation_hook][:job_status] = service_request.status
playbooks_status[transformation_hook][:job_id] = service_request.miq_request_tasks.first.destination.service_resources.first.resource.id
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fdupont-redhat This is a pretty long chain of commands where we could get a nil in the middle?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkanoor
Good catch. I had the same feeling, but aesthetics won over security. I'll add extra tests.

task.set_option(:playbooks, playbooks_status)
end
rescue => e
@handle.set_state_var(:ae_state_progress, 'message' => e.message)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fdupont-redhat do you want to report progress only when an error happens or should that also happen on success?
Does :ae_state_progress only mean error messages, if it does we should change it to something like :ae_state_error

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkanoor
It's a default behavior to catch the error and log it in :ae_state_progress, so that it can be used by WeightedUpdateStatus. Here, we don't plan to add additional information because the description argument set in the state machine is explicit enough.

@handle.log(:info, "Service Template Id: #{service_template.id}")
unless service_template.nil?
target_host = target_host(task, transformation_hook)
unless target_host.nil?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fdupont-redhat
Can this be a positive case with an 'if' statement instead of an unless, it makes it easier to read

 if service_template
.....
   target_host = target_host(task, transformation_hook)
   if target_host
       ......
   end
end

Also what happens if you can't find a target_host or service_template should we report on that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rubocop actually prefer earlier termination. In this example you can code this way

return if service_template.nil?
...
return if target_host.nil?
...
return unless target_host.power_state == 'on'
...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bzwei @mkanoor
Good idea. It's better to be positive ;) And it makes the code shorter.
If service template is nil, it simply means that no playbook is expected to be run.
If target host is nil, it means that transformation_hook is neither pre, nor post. As we don't currently support any other hook, we can skip it. BTW, I don't know if we'll ever support other hooks, but the implementation is generic and could be reused for another use case.

if service_request_id.present?
service_request = @handle.vmdb(:miq_request).find_by(:id => service_request_id)

playbooks_status = task.get_option(:playbooks) || {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't mix string and symbol as keys at the same level. Here the examples are :playbooks and "pre_ansible_playbook_service_request_id" (BTW, the key is very long)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bzwei
Code changed to use to_sym with the substituted string.
I know the key is very long, but it makes it really explicit.

@handle.log(:info, "Service Template Id: #{service_template.id}")
unless service_template.nil?
target_host = target_host(task, transformation_hook)
unless target_host.nil?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rubocop actually prefer earlier termination. In this example you can code this way

return if service_template.nil?
...
return if target_host.nil?
...
return unless target_host.power_state == 'on'
...

task = @handle.root['service_template_transformation_plan_task']
transformation_hook = @handle.inputs['transformation_hook']

unless transformation_hook == '_'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return if transformation_hook == '_'

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

return if service_template.nil?
target_host = target_host(task, transformation_hook)
return if target_host.nil?
return unless target_host.power_state == 'on'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

combine into return if target_host.nil? || target_host.power_state != 'on'

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

unless transformation_hook == '_'
service_template = task.send("#{transformation_hook}_ansible_playbook_service_template")
@handle.log(:info, "Service Template Id: #{service_template.id}")
return if service_template.nil?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if service_template.nil? then the previous line service_template.id will blow up. A simple fix is #{service_template.try(:id)}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the @handle.log as it is mainly used for debug.

@miq-bot
Copy link
Member

miq-bot commented Jul 18, 2018

Checked commits fabiendupont/manageiq-content@5c55d63~...6db4635 with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0
3 files checked, 2 offenses detected

content/automate/ManageIQ/Transformation/Ansible.class/methods/checkplaybookasaservice.rb

content/automate/ManageIQ/Transformation/Ansible.class/methods/launchplaybookasaservice.rb

@gmcculloug gmcculloug self-assigned this Jul 18, 2018
@gmcculloug gmcculloug added this to the Sprint 91 Ending Jul 30, 2018 milestone Jul 19, 2018
@gmcculloug gmcculloug merged commit f5fdc82 into ManageIQ:master Jul 19, 2018
simaishi pushed a commit that referenced this pull request Jul 25, 2018
…aybook_support

Add support for pre/post-migration playbook
(cherry picked from commit f5fdc82)

https://bugzilla.redhat.com/show_bug.cgi?id=1608420
@simaishi
Copy link
Contributor

Gaprindashvili backport details:

$ git log -1
commit fb6f12ceff23a21bbdb891431ff31b43820bc8ca
Author: Greg McCullough <gmccullo@redhat.com>
Date:   Thu Jul 19 08:06:54 2018 -0400

    Merge pull request #355 from fdupont-redhat/v2v_pre_post_migration_playbook_support
    
    Add support for pre/post-migration playbook
    (cherry picked from commit f5fdc8293ac754a37674920607d7743392d94fcd)
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1608420

@ghost ghost deleted the v2v_pre_post_migration_playbook_support branch July 31, 2018 07:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants