Skip to content

Commit

Permalink
Merge pull request #16960 from bzwei/v2v_service_template
Browse files Browse the repository at this point in the history
Transformation Plan, Request, and Task for V2V
  • Loading branch information
gmcculloug authored Feb 19, 2018
2 parents fb9e78a + ee4b78b commit 02af759
Show file tree
Hide file tree
Showing 14 changed files with 337 additions and 20 deletions.
5 changes: 5 additions & 0 deletions app/models/miq_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ class MiqRequest < ApplicationRecord
:AutomationRequest => {
:automation => N_("Automation")
}
},
:Transformation => {
:ServiceTemplateTransformationPlanRequest => {
:transformation_plan => N_("Transformation Plan")
}
}
}.freeze

Expand Down
4 changes: 2 additions & 2 deletions app/models/resource_action_workflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def generate_request(state, values)
end

def validate_dialog
@dialog.validate_field_data
@dialog.try(:validate_field_data) || []
end

def create_values
Expand Down Expand Up @@ -86,7 +86,7 @@ def load_resource_action(values = nil)

def create_values_hash
{
:dialog => @dialog.automate_values_hash,
:dialog => @dialog.try(:automate_values_hash),
:workflow_settings => @settings,
:initiator => @initiator
}
Expand Down
6 changes: 1 addition & 5 deletions app/models/service_template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -416,11 +416,7 @@ def update_service_resources(config_info, auth_user = nil)
end

def build_resource_action(ae_endpoint, action)
fqname = if ae_endpoint.empty?
self.class.send(action[:method], *action[:args]) || ""
else
ae_endpoint[:fqname]
end
fqname = ae_endpoint[:fqname] || self.class.send(action[:method], *action[:args]) || ""

build_options = {:action => action[:name],
:fqname => fqname,
Expand Down
8 changes: 6 additions & 2 deletions app/models/service_template_provision_task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def deliver_to_automate(req_type = request_type, _zone = nil)
}

# Automate entry point overrides from the resource_action
ra = source.resource_actions.detect { |ra| ra.action == 'Provision' } if source.respond_to?(:resource_actions)
ra = resource_action

unless ra.nil?
args[:namespace] = ra.ae_namespace unless ra.ae_namespace.blank?
Expand All @@ -138,7 +138,7 @@ def deliver_to_automate(req_type = request_type, _zone = nil)
args[:attrs].merge!(ra.ae_attributes)
end

args[:attrs].merge!(MiqAeEngine.create_automation_attributes(destination.class.base_model.name => destination))
args[:attrs].merge!(MiqAeEngine.create_automation_attributes(destination.class.base_model.name => destination)) if destination.present?
args[:user_id] = get_user.id
args[:miq_group_id] = get_user.current_group.id
args[:tenant_id] = get_user.current_tenant.id
Expand All @@ -158,6 +158,10 @@ def deliver_to_automate(req_type = request_type, _zone = nil)
end
end

def resource_action
source.resource_actions.detect { |ra| ra.action == 'Provision' } if source.respond_to?(:resource_actions)
end

def service_resource
return nil if options[:service_resource_id].blank?
ServiceResource.find_by(:id => options[:service_resource_id])
Expand Down
90 changes: 90 additions & 0 deletions app/models/service_template_transformation_plan.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
class ServiceTemplateTransformationPlan < ServiceTemplate
def request_class
ServiceTemplateTransformationPlanRequest
end

def request_type
"transformation_plan"
end

def transformation_mapping
service_resources.find_by(:resource_type => 'TransformationMapping').resource
end

def vm_requests
service_resources.where(:resource_type => 'VmOrTemplate')
end

def validate_order
true
end

def self.default_provisioning_entry_point(_service_type)
'/Transformation/StateMachines/VMTransformation/Transformation'
end

def self.default_retirement_entry_point
nil
end

def self.default_reconfiguration_entry_point
nil
end

# create ServiceTemplate and supporting ServiceResources and ResourceActions
# options
# :name
# :description
# :config_info
# :transformation_mapping_id
# :vm_ids
#
def self.create_catalog_item(options, _auth_user = nil)
enhanced_config_info = validate_config_info(options)
default_options = {
:display => false,
:service_type => 'atomic',
:prov_type => 'transformation_plan'
}

transaction do
create_from_options(options.merge(default_options)).tap do |service_template|
service_template.add_resource(enhanced_config_info[:transformation_mapping])
enhanced_config_info[:vms].each { |vm| service_template.add_resource(vm, :status => 'Queued') }
service_template.create_resource_actions(enhanced_config_info)
end
end
end

private

def enforce_single_service_parent(_resource)
end

def self.validate_config_info(options)
config_info = options[:config_info]

mapping = if config_info[:transformation_mapping_id]
TransformationMapping.find(config_info[:transformation_mapping_id])
else
config_info[:transformation_mapping]
end

raise _('Must provide an existing transformation mapping') if mapping.blank?

vms = if config_info[:vm_ids]
VmOrTemplate.find(config_info[:vm_ids])
else
config_info[:vms]
end

raise _('Must select a list of valid vms') if vms.blank?

{
:transformation_mapping => mapping,
:vms => vms,
:provision => config_info[:provision] || {}
}
end
private_class_method :validate_config_info
end
26 changes: 26 additions & 0 deletions app/models/service_template_transformation_plan_request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class ServiceTemplateTransformationPlanRequest < ServiceTemplateProvisionRequest
TASK_DESCRIPTION = 'VM Transformations'.freeze

delegate :transformation_mapping, :vm_requests, :to => :source

def requested_task_idx
vm_requests.where(:status => 'Approved')
end

def customize_request_task_attributes(req_task_attrs, vm_request)
req_task_attrs[:source] = vm_request.resource
end

def source_vms
vm_requests.where(:status => %w(Queued Failed)).pluck(:resource_id)
end

def validate_vm(_vm_id)
# TODO: enhance the logic to determine whether this VM can be included in this request
true
end

def approve_vm(vm_id)
vm_requests.find_by(:resource_id => vm_id).update_attributes!(:status => 'Approved')
end
end
22 changes: 22 additions & 0 deletions app/models/service_template_transformation_plan_task.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class ServiceTemplateTransformationPlanTask < ServiceTemplateProvisionTask
def self.base_model
ServiceTemplateTransformationPlanTask
end

def after_request_task_create
update_attributes(:description => "Transforming VM #{source.name}")
end

def resource_action
miq_request.source.resource_actions.detect { |ra| ra.action == 'Provision' }
end

def transformation_destination(source_obj)
miq_request.transformation_mapping.destination(source_obj)
end

def update_transformation_progress(progress)
options[:progress] = (options[:progress] || {}).merge(progress)
save
end
end
4 changes: 4 additions & 0 deletions spec/factories/miq_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
source { create(:miq_template) }
end

factory :service_template_transformation_plan_request, :class => "ServiceTemplateTransformationPlanRequest" do
source { create(:service_template_transformation_plan) }
end

trait :with_approval do
transient do
reason ""
Expand Down
2 changes: 2 additions & 0 deletions spec/factories/miq_request_task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@
state 'pending'
request_type 'clone_to_service'
end

factory :service_template_transformation_plan_task, :parent => :service_template_provision_task, :class => 'ServiceTemplateTransformationPlanTask'
end
1 change: 1 addition & 0 deletions spec/factories/service_template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
factory :service_template_orchestration, :class => 'ServiceTemplateOrchestration', :parent => :service_template
factory :service_template_ansible_playbook, :class => 'ServiceTemplateAnsiblePlaybook', :parent => :service_template
factory :service_template_container_template, :class => 'ServiceTemplateContainerTemplate', :parent => :service_template
factory :service_template_transformation_plan, :class => 'ServiceTemplateTransformationPlan', :parent => :service_template
end
23 changes: 12 additions & 11 deletions spec/models/miq_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@
context "CONSTANTS" do
it "REQUEST_TYPES" do
expected_request_types = {
:MiqProvisionRequest => {:template => "VM Provision", :clone_to_vm => "VM Clone", :clone_to_template => "VM Publish"},
:MiqProvisionRequestTemplate => {:template => "VM Provision Template"},
:MiqHostProvisionRequest => {:host_pxe_install => "Host Provision"},
:MiqProvisionConfiguredSystemRequest => {:provision_via_foreman => "#{ui_lookup(:ui_title => 'foreman')} Provision"},
:VmReconfigureRequest => {:vm_reconfigure => "VM Reconfigure"},
:VmCloudReconfigureRequest => {:vm_cloud_reconfigure => "VM Cloud Reconfigure"},
:VmMigrateRequest => {:vm_migrate => "VM Migrate"},
:AutomationRequest => {:automation => "Automation"},
:ServiceTemplateProvisionRequest => {:clone_to_service => "Service Provision"},
:ServiceReconfigureRequest => {:service_reconfigure => "Service Reconfigure"},
:PhysicalServerProvisionRequest => {:provision_physical_server => "Physical Server Provision"}
:MiqProvisionRequest => {:template => "VM Provision", :clone_to_vm => "VM Clone", :clone_to_template => "VM Publish"},
:MiqProvisionRequestTemplate => {:template => "VM Provision Template"},
:MiqHostProvisionRequest => {:host_pxe_install => "Host Provision"},
:MiqProvisionConfiguredSystemRequest => {:provision_via_foreman => "#{ui_lookup(:ui_title => 'foreman')} Provision"},
:VmReconfigureRequest => {:vm_reconfigure => "VM Reconfigure"},
:VmCloudReconfigureRequest => {:vm_cloud_reconfigure => "VM Cloud Reconfigure"},
:VmMigrateRequest => {:vm_migrate => "VM Migrate"},
:AutomationRequest => {:automation => "Automation"},
:ServiceTemplateProvisionRequest => {:clone_to_service => "Service Provision"},
:ServiceReconfigureRequest => {:service_reconfigure => "Service Reconfigure"},
:PhysicalServerProvisionRequest => {:provision_physical_server => "Physical Server Provision"},
:ServiceTemplateTransformationPlanRequest => {:transformation_plan => "Transformation Plan"}
}

expect(described_class::REQUEST_TYPES).to eq(expected_request_types)
Expand Down
41 changes: 41 additions & 0 deletions spec/models/service_template_transformation_plan_request_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
describe ServiceTemplateTransformationPlanRequest do
let(:vms) { Array.new(3) { FactoryGirl.create(:vm_or_template) } }
let(:vm_requests) do
%w(Queued Failed Approved).zip(vms).collect do |status, vm|
ServiceResource.new(:resource => vm, :status => status)
end
end
let(:plan) { FactoryGirl.create(:service_template_transformation_plan, :service_resources => vm_requests) }
let(:request) { FactoryGirl.create(:service_template_transformation_plan_request, :source => plan) }

describe '#requested_task_idx' do
it 'selects approved vm requests' do
expect(request.requested_task_idx.first).to have_attributes(:resource => vms[2], :status => 'Approved')
end
end

describe 'customize_request_task_attributes' do
it 'sets the source option to be the vm in the vm_request' do
req_task_attrs = {}
request.customize_request_task_attributes(req_task_attrs, vm_requests[0])
expect(req_task_attrs[:source]).to eq(vms[0])
end
end

describe '#source_vms' do
it 'selects queued and failed vm in the request' do
expect(request.source_vms).to match_array([vms[0].id, vms[1].id])
end
end

describe '#validate_vm' do
it { expect(request.validate_vm(vms[0].id)).to be_truthy }
end

describe '#approve_vm' do
it 'turns the status to Approved' do
request.approve_vm(vms[0].id)
expect(ServiceResource.find_by(:resource => vms[0]).status).to eq('Approved')
end
end
end
64 changes: 64 additions & 0 deletions spec/models/service_template_transformation_plan_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
describe ServiceTemplateTransformationPlan do
subject { FactoryGirl.create(:service_template_transformation_plan) }

describe '#request_class' do
it { expect(subject.request_class).to eq(ServiceTemplateTransformationPlanRequest) }
end

describe '#request_type' do
it { expect(subject.request_type).to eq("transformation_plan") }
end

describe '#validate_order' do
it 'always allows a plan to be ordered' do
expect(subject.validate_order).to be_truthy
end
end

let(:transformation_mapping) { FactoryGirl.create(:transformation_mapping) }
let(:vm1) { FactoryGirl.create(:vm_or_template) }
let(:vm2) { FactoryGirl.create(:vm_or_template) }

let(:catalog_item_options) do
{
:name => 'Transformation Plan',
:description => 'a description',
:config_info => {
:transformation_mapping_id => transformation_mapping.id,
:vm_ids => [vm1.id, vm2.id],
}
}
end

describe '.create_catalog_item' do
it 'creates and returns a transformation plan' do
service_template = described_class.create_catalog_item(catalog_item_options)

expect(service_template.name).to eq('Transformation Plan')
expect(service_template.transformation_mapping).to eq(transformation_mapping)
expect(service_template.vm_requests.collect(&:resource)).to match_array([vm1, vm2])
expect(service_template.vm_requests.collect(&:status)).to eq(%w(Queued Queued))
expect(service_template.config_info).to eq(catalog_item_options[:config_info])
expect(service_template.resource_actions.first).to have_attributes(
:action => 'Provision',
:fqname => described_class.default_provisioning_entry_point(nil)
)
end

it 'requires a transformation mapping' do
catalog_item_options[:config_info].delete(:transformation_mapping_id)

expect do
described_class.create_catalog_item(catalog_item_options)
end.to raise_error(StandardError, 'Must provide an existing transformation mapping')
end

it 'requires selected vms' do
catalog_item_options[:config_info].delete(:vm_ids)

expect do
described_class.create_catalog_item(catalog_item_options)
end.to raise_error(StandardError, 'Must select a list of valid vms')
end
end
end
Loading

0 comments on commit 02af759

Please sign in to comment.