forked from ManageIQ/manageiq
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathems_cluster.rb
296 lines (228 loc) · 8.74 KB
/
ems_cluster.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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
class EmsCluster < ApplicationRecord
include SupportsFeatureMixin
include NewWithTypeStiMixin
include EventMixin
include TenantIdentityMixin
include CustomActionsMixin
acts_as_miq_taggable
belongs_to :ext_management_system, :foreign_key => "ems_id"
has_many :hosts, :dependent => :nullify
has_many :vms_and_templates, :dependent => :nullify
has_many :miq_templates, :inverse_of => :ems_cluster
has_many :vms, :inverse_of => :ems_cluster
has_many :metrics, :as => :resource # Destroy will be handled by purger
has_many :metric_rollups, :as => :resource # Destroy will be handled by purger
has_many :vim_performance_states, :as => :resource # Destroy will be handled by purger
has_many :policy_events, -> { order("timestamp") }
has_many :miq_events, :as => :target, :dependent => :destroy
has_many :miq_alert_statuses, :as => :resource, :dependent => :destroy
has_many :host_hardwares, :class_name => 'Hardware', :through => :hosts, :source => :hardware
has_many :vm_hardwares, :class_name => 'Hardware', :through => :vms_and_templates, :source => :hardware
has_many :storages, -> { distinct }, :through => :hosts
has_many :lans, -> { distinct }, :through => :hosts
has_many :switches, -> { distinct }, :through => :hosts
virtual_column :v_ram_vr_ratio, :type => :float, :uses => [:aggregate_memory, :aggregate_vm_memory]
virtual_column :v_cpu_vr_ratio, :type => :float, :uses => [:aggregate_cpu_total_cores, :aggregate_vm_cpus]
virtual_column :v_parent_datacenter, :type => :string, :uses => :all_relationships
virtual_column :v_qualified_desc, :type => :string, :uses => :all_relationships
virtual_total :total_vms, :vms
virtual_total :total_miq_templates, :miq_templates
virtual_total :total_vms_and_templates, :vms_and_templates
virtual_total :total_hosts, :hosts
virtual_has_many :storages, :uses => {:hosts => :storages}
virtual_has_many :resource_pools, :uses => :all_relationships
virtual_has_many :lans, :uses => {:hosts => :lans}
has_many :failover_hosts, -> { failover }, :class_name => "Host"
delegate :queue_name_for_ems_operations, :to => :ext_management_system, :allow_nil => true
include ProviderObjectMixin
include FilterableMixin
include DriftStateMixin
virtual_delegate :last_scan_on, :to => "last_drift_state_timestamp_rec.timestamp", :allow_nil => true, :type => :datetime
include RelationshipMixin
self.default_relationship_type = "ems_metadata"
include AggregationMixin
include Metric::CiMixin
include MiqPolicyMixin
include AsyncDeleteMixin
#
# Provider Object methods - to be overwritten by Provider authors
#
def provider_object(_connection)
raise NotImplementedError, _("provider_object must be implemented by a subclass")
end
def provider_object_release(_handle)
raise NotImplementedError, _("provider_object_release must be implemented by a subclass")
end
def register_host(_host)
raise NotImplementedError, _("register_host must be implemented by a subclass")
end
#
# Virtual Column methods
#
def v_ram_vr_ratio
total_memory = aggregate_memory.to_f
total_memory == 0 ? 0 : (aggregate_vm_memory / total_memory * 10).round * 0.1
end
def v_cpu_vr_ratio
total_cpus = aggregate_cpu_total_cores.to_f
total_cpus == 0 ? 0 : (aggregate_vm_cpus / total_cpus * 10).round * 0.1
end
def v_parent_datacenter
dc = parent_datacenter
dc.nil? ? "" : dc.name
end
def v_qualified_desc
dc = parent_datacenter
dc.nil? ? name : "#{name} in #{dc.name}"
end
delegate :my_zone, :to => :ext_management_system
def total_vcpus
hosts.inject(0) { |c, h| c + (h.total_vcpus || 0) }
end
#
# Relationship methods
#
# Direct Vm relationship methods
def direct_vm_rels
# Look for only the Vms at the second depth (default RP + 1)
grandchild_rels(:of_type => 'VmOrTemplate')
end
def direct_vms
Relationship.resources(direct_vm_rels).sort_by { |v| v.name.downcase }
end
alias direct_miq_templates miq_templates
def direct_vms_and_templates
(direct_vms + direct_miq_templates).sort_by { |v| v.name.downcase }
end
def direct_vm_ids
Relationship.resource_ids(direct_vm_rels)
end
alias direct_miq_template_ids miq_template_ids
def direct_vm_or_template_ids
direct_vm_ids + direct_miq_template_ids
end
virtual_total :total_direct_vms, :direct_vm_rels
virtual_total :total_direct_miq_templates, :miq_templates
def total_direct_vms_and_templates
total_direct_vms + total_direct_miq_templates
end
# Resource Pool relationship methods
def default_resource_pool
Relationship.resource(child_rels(:of_type => 'ResourcePool').first)
end
def resource_pools
Relationship.resources(grandchild_rels(:of_type => 'ResourcePool'))
end
def resource_pools_with_default
Relationship.resources(child_and_grandchild_rels(:of_type => 'ResourcePool'))
end
alias add_resource_pool set_child
alias remove_resource_pool remove_child
def remove_all_resource_pools
remove_all_children(:of_type => 'ResourcePool')
end
# All RPs under this Cluster and all child RPs
def all_resource_pools
# descendants typically returns the default_rp first but sporadically it
# will not due to a bug in the ancestry gem, this means we cannot simply
# drop the first value and need to check is_default
descendants(:of_type => 'ResourcePool').select { |r| !r.is_default }.sort_by { |r| r.name.downcase }
end
def all_resource_pools_with_default
descendants(:of_type => 'ResourcePool').sort_by { |r| r.name.downcase }
end
# Parent relationship methods
def parent_folder
detect_ancestor(:of_type => "EmsFolder") { |a| !a.kind_of?(Datacenter) && !%w[host vm].include?(a.name) } # TODO: Fix this to use EmsFolder#hidden?
end
def parent_datacenter
detect_ancestor(:of_type => 'EmsFolder') { |a| a.kind_of?(Datacenter) }
end
def event_where_clause(assoc = :ems_events)
return ["ems_cluster_id = ?", id] if assoc.to_sym == :policy_events
cond = ["ems_cluster_id = ?"]
cond_params = [id]
ids = host_ids
unless ids.empty?
cond << "host_id IN (?) OR dest_host_id IN (?)"
cond_params += [ids, ids]
end
ids = vm_or_template_ids
unless ids.empty?
cond << "vm_or_template_id IN (?) OR dest_vm_or_template_id IN (?)"
cond_params += [ids, ids]
end
cond_params.unshift(cond.join(" OR ")) unless cond.empty?
cond_params
end
def ems_events
ewc = event_where_clause
return [] if ewc.blank?
EmsEvent.where(ewc).order("timestamp").to_a
end
supports :smartstate_analysis
def scan(_userid = "system")
MiqQueue.submit_job(
:service => "smartstate",
:affinity => ext_management_system,
:class_name => self.class.to_s,
:method_name => "save_drift_state",
:instance_id => id
)
end
def get_reserve(field)
rp = default_resource_pool
rp && rp.send(field)
end
def cpu_reserve
get_reserve(:cpu_reserve)
end
def memory_reserve
get_reserve(:memory_reserve)
end
def effective_resource(resource)
resource = resource.to_s
unless %w[cpu vcpu memory].include?(resource)
raise ArgumentError, _("Unknown resource %{name}") % {:name => resource.inspect}
end
resource = "cpu" if resource == "vcpu"
send(:"effective_#{resource}")
end
#
# Metric methods
#
PERF_ROLLUP_CHILDREN = [:hosts]
def perf_rollup_parents(interval_name = nil)
[ext_management_system].compact unless interval_name == 'realtime'
end
def self.get_perf_collection_object_list
cl_hash = in_my_region.includes(:tags, :taggings).select(:id, :name).each_with_object({}) do |c, h|
h[c.id] = {:cl_rec => c, :ho_ids => c.host_ids}
end
hids = cl_hash.values.flat_map { |v| v[:ho_ids] }.compact.uniq
hosts_by_id = Host.where(:id => hids).includes(:tags, :taggings).select(:id, :name, :vmm_vendor, :ems_cluster_id).index_by(&:id)
cl_hash.each do |_k, v|
hosts = hosts_by_id.values_at(*v[:ho_ids]).compact
if hosts.empty?
v[:ho_enabled] = v[:ho_disabled] = []
else
v[:ho_enabled], v[:ho_disabled] = hosts.partition(&:perf_capture_enabled?)
end
end
cl_hash
end
def get_perf_collection_object_list
hosts = hosts_enabled_for_perf_capture
perf_capture_enabled? ? [self] + hosts : hosts
end
def perf_capture_enabled_host_ids=(ids)
self.perf_capture_enabled = ids.any?
hosts.each { |h| h.perf_capture_enabled = ids.include?(h.id) }
end
def hosts_enabled_for_perf_capture
hosts(:include => [:taggings, :tags]).select(&:perf_capture_enabled?)
end
def self.display_name(number = 1)
n_('Cluster', 'Clusters', number)
end
end