forked from ManageIQ/manageiq
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvm_migration_validator.rb
144 lines (114 loc) · 4.84 KB
/
vm_migration_validator.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
class TransformationMapping::VmMigrationValidator
require 'miq-hash_struct'
VM_CONFLICT = "conflict".freeze
VM_EMPTY_NAME = "empty_name".freeze
VM_IN_OTHER_PLAN = "in_other_plan".freeze
VM_INACTIVE = "inactive".freeze
VM_INVALID = "invalid".freeze
VM_MIGRATED = "migrated".freeze
VM_NOT_EXIST = "not_exist".freeze
VM_VALID = "ok".freeze
def initialize(mapping, vm_list = nil, service_template_id = nil)
@mapping = mapping
@vm_list = vm_list
@service_template_id = service_template_id.try(:to_i)
end
def validate
@vm_list.present? ? identify_vms : select_vms
end
def select_vms
valid_list = []
Vm.where(:ems_cluster => mapped_clusters).includes(:lans, :storages).each do |vm|
reason = validate_vm(vm, true)
valid_list << VmMigrateStruct.new(vm.name, vm, VM_VALID, reason) if reason == VM_VALID
end
{"valid" => valid_list}
end
def identify_vms
valid_list = []
invalid_list = []
conflict_list = []
vm_names = @vm_list.collect { |row| row['name'] }
vm_objects = Vm.where(:name => vm_names, :ems_cluster => mapped_clusters).includes(:lans, :storages, :host, :ext_management_system)
@vm_list.each do |row|
vm_name = row['name']
if vm_name.blank?
invalid_list << VmMigrateStruct.new('', nil, VM_INVALID, VM_EMPTY_NAME)
next
end
vms = vm_objects.select { |vm| vm.name == vm_name }
vms = vms.select { |vm| vm.uid_ems == row['uid_ems'] } if row['uid_ems'].present?
vms = vms.select { |vm| vm.host.name == row['host'] } if row['host'].present?
vms = vms.select { |vm| vm.ext_management_system.name == row['provider'] } if row['provider'].present?
if vms.empty?
invalid_list << VmMigrateStruct.new(vm_name, nil, VM_INVALID, VM_NOT_EXIST)
elsif vms.size == 1
vm = vms.first
reason = validate_vm(vm, false)
if reason == VM_VALID
valid_list << VmMigrateStruct.new(vm.name, vm, VM_VALID, reason)
else
invalid_list << VmMigrateStruct.new(vm.name, vm, VM_INVALID, reason)
end
else
vms.each { |v| conflict_list << VmMigrateStruct.new(v.name, v, VM_CONFLICT, VM_CONFLICT) }
end
end
{
"valid" => valid_list,
"invalid" => invalid_list,
"conflicted" => conflict_list
}
end
def validate_vm(vm, quick = true)
validate_result = vm_migration_status(vm)
return validate_result unless validate_result == VM_VALID
# a valid vm must find all resources in the mapping and has never been migrated
invalid_list = []
issue = no_mapping_list(invalid_list, "storages", vm.datastores - mapped_storages)
return no_mapping_msg(invalid_list) if issue && quick
no_mapping_list(invalid_list, "lans", vm.lans - mapped_lans)
invalid_list.present? ? no_mapping_msg(invalid_list) : VM_VALID
end
def vm_migration_status(vm)
return VM_INACTIVE unless vm.active?
vm_as_resources = ServiceResource.joins(:service_template).where(:resource => vm, :service_templates => {:type => 'ServiceTemplateTransformationPlan'})
# VM has not been migrated before
return VM_VALID if vm_as_resources.empty?
return VM_MIGRATED unless vm_as_resources.where(:status => ServiceResource::STATUS_COMPLETED).empty?
# VM failed in previous migration
vm_as_resources.all? { |rsc| rsc.status == ServiceResource::STATUS_FAILED || rsc.service_template_id == @service_template_id } ? VM_VALID : VM_IN_OTHER_PLAN
end
def no_mapping_list(invalid_list, data_type, new_records)
return false if new_records.blank?
invalid_list << "#{data_type}: %{list}" % {:list => new_records.collect(&:name).join(", ")}
true
end
def no_mapping_msg(list)
"Mapping source not found - %{list}" % {:list => list.join('. ')}
end
def mapped_clusters
@mapped_clusters ||= EmsCluster.where(:id => @mapping.transformation_mapping_items.where(:source_type => 'EmsCluster').select(:source_id))
end
def mapped_storages
@mapped_storages ||= Storage.where(:id => @mapping.transformation_mapping_items.where(:source_type => 'Storage').select(:source_id))
end
def mapped_lans
@mapped_lans ||= Lan.where(:id => @mapping.transformation_mapping_items.where(:source_type => 'Lan').select(:source_id))
end
class VmMigrateStruct < MiqHashStruct
def initialize(vm_name, vm, status, reason)
options = {"name" => vm_name, "status" => status, "reason" => reason}
if vm.present?
options.merge!(
"cluster" => vm.ems_cluster.try(:name) || '',
"path" => vm.ext_management_system ? "#{vm.ext_management_system.name}/#{vm.v_parent_blue_folder_display_path}" : '',
"allocated_size" => vm.allocated_disk_storage,
"id" => vm.id.to_s,
"ems_cluster_id" => vm.ems_cluster_id.to_s
)
end
super(options)
end
end
end