forked from ManageIQ/manageiq
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrole_management.rb
301 lines (241 loc) · 9.2 KB
/
role_management.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
297
298
299
300
301
module MiqServer::RoleManagement
extend ActiveSupport::Concern
included do
has_many :assigned_server_roles, :dependent => :destroy
has_many :server_roles, :through => :assigned_server_roles
has_many :active_roles, -> { where('assigned_server_roles.active' => true) }, :through => :assigned_server_roles, :source => :server_role
has_many :inactive_roles, -> { where('assigned_server_roles.active' => false) }, :through => :assigned_server_roles, :source => :server_role
alias_method :assigned_roles, :server_roles
before_save :check_server_roles
end
def role_changes
o = @active_role_names
n = active_role_names
adds = (n - o)
deletes = (o - n)
unchanged = (o & n)
return adds, deletes, unchanged
end
def log_role_changes
_log.info("Server's roles have changed:")
adds, deletes, unchanged = role_changes
_log.info(" Old roles: #{@active_role_names.inspect}")
_log.info(" New roles: #{active_role_names.inspect}")
_log.info(" Roles removed: #{deletes.inspect}")
_log.info(" Roles added: #{adds.inspect}")
_log.info(" Roles unchanged: #{unchanged.inspect}")
end
def active_roles_changed?
@active_role_names != active_role_names
end
def sync_active_roles
@active_role_names = active_role_names
end
def set_active_role_flags
self.has_active_userinterface = has_active_role?("user_interface")
self.has_active_remote_console = has_active_role?("remote_console")
self.has_active_webservices = has_active_role?("web_services")
save
end
def sync_assigned_roles
self.role = ::Settings.server.role
end
def ensure_default_roles
MiqServer.my_server.add_settings_for_resource(:server => {:role => ENV.fetch("MIQ_SERVER_DEFAULT_ROLES", nil)}) if role.blank? && ENV["MIQ_SERVER_DEFAULT_ROLES"].present?
sync_assigned_roles
end
def deactivate_all_roles
deactivate_roles("*")
end
def activate_roles(*roles)
set_role_activation(true, *roles)
end
def activate_all_roles
activate_roles("*")
end
def deactivate_roles(*roles)
set_role_activation(false, *roles)
end
def set_role_activation(active, *roles)
roles = roles.first if roles.length == 1 && roles[0].kind_of?(Array)
return if roles.empty?
ids = roles == ["*"] ? server_roles.pluck(:id) : ServerRole.where(:name => roles).pluck(:id)
assigned_server_roles.where(:server_role_id => ids).each do |a|
next if a.server_role == ServerRole.database_owner
next if a.active == active
active ? a.activate : a.deactivate
end
end
def set_database_owner_role(active)
dbowner = ServerRole.database_owner
assigned = assigned_server_roles.find_by(:server_role_id => dbowner.id)
assigned ||= assigned_server_roles.create(:server_role => dbowner, :priority => AssignedServerRole::DEFAULT_PRIORITY, :active => active)
active ? assigned.activate : assigned.deactivate
end
def is_master_for_role?(server_role)
assigned = assigned_server_roles.find_by(:server_role_id => server_role.id)
return false if assigned.nil?
assigned.priority == 1
end
def set_master_for_role(server_role)
if server_role.master_supported?
zone.miq_servers.reject { |s| s.id == id }.each do |server|
assigned = server.assigned_server_roles.find_by(:server_role_id => server_role.id)
next if assigned.nil?
server.assign_role(server_role, 2) if assigned.priority == 1
end
end
assign_role(server_role, 1)
end
def remove_master_for_role(server_role)
assign_role(server_role, 2)
end
def check_server_roles
assigned_server_roles.each { |asr| asr.deactivate if asr.server_role.role_scope == 'zone' } if zone_id_changed?
end
def server_role_names
server_roles.pluck(:name).sort
end
alias my_roles server_role_names
alias assigned_role_names server_role_names
def server_role_names=(roles)
zone.lock do
if roles.blank?
server_roles.delete_all
else
all_roles = ServerRole.all_names
desired = (roles == "*" ? all_roles : roles.map { |role| role.strip.downcase }.sort)
invalid = desired - all_roles
raise ArgumentError, _("Roles <%{names}> not defined") % {:names => invalid.join(", ")} if invalid.any?
current = server_role_names
# MiqServer#server_role_names may include database scoped roles, which are managed elsewhere,
# so ignore them when determining added and removed roles.
current -= ServerRole.database_roles.pluck(:name)
# TODO: Change this to use replace method under Rails 2.x
removes = ServerRole.where(:name => (current - desired))
server_roles.delete(removes) unless removes.empty?
adds = ServerRole.where(:name => (desired - current))
unless adds.empty?
adds.each do |r|
assign_role(r)
deactivate_roles(r.name)
end
end
end
end
end
def role
server_role_names.join(',')
end
alias my_role role
alias assigned_role role
def role=(val)
self.server_role_names = val == "*" ? val : val.split(",")
role
end
def assign_role(server_role, priority = nil)
assigned_server_role = assigned_server_roles.find_or_create_by(:server_role_id => server_role.id)
if assigned_server_role.priority.nil? || (priority.kind_of?(Numeric) && assigned_server_role.priority != priority)
priority ||= AssignedServerRole::DEFAULT_PRIORITY
assigned_server_role.update(:priority => priority)
end
reload
assigned_server_role
end
def inactive_role_names
inactive_roles.pluck(:name).sort
end
def active_role_names
active_roles.pluck(:name).sort
end
def active_role
active_role_names.join(",")
end
def licensed_roles
ServerRole.all.to_a # TODO: The UI calls delete_if on this method, so it needs to be an Array
end
def licensed_role_names
licensed_roles.collect(&:name).sort
end
def licensed_role
licensed_role_names.join(",")
end
def has_assigned_role?(role)
assigned_role_names.include?(role.to_s.strip.downcase)
end
alias has_role? has_assigned_role?
def has_active_role?(role)
active_role_names.include?(role.to_s.strip.downcase)
end
def synchronize_active_roles(servers, roles_to_sync)
current = Hash.new { |h, k| h[k] = {:active => [], :inactive => []} }
servers.each do |s|
s.assigned_server_roles.each do |a|
next unless roles_to_sync.include?(a.server_role)
# Priority 1 has more weight than Priority 2
priority = a.priority || AssignedServerRole::DEFAULT_PRIORITY
current[a.server_role.name][:active] << [s, priority] if a.active?
current[a.server_role.name][:inactive] << [s, priority] unless a.active?
end
end
assigned_roles = servers.collect(&:assigned_roles).flatten.uniq.compact
assigned_roles.each do |r|
next unless roles_to_sync.include?(r)
role_name = r.name
if r.unlimited?
current[role_name][:inactive].each { |s, _p| s.activate_roles(role_name) }
else
active = current[role_name][:active].sort_by(&:last).reverse
inactive = current[role_name][:inactive].sort_by(&:last)
delta = r.max_concurrent - active.length
if delta < 0
delta.abs.times do
next if active.empty?
s, p = active.shift
s.deactivate_roles(role_name)
inactive << [s, p]
end
inactive = inactive.sort_by(&:last) # Sort again, since we may have added to array
elsif delta > 0
delta.times do
next if inactive.empty?
s, p = inactive.shift
s.activate_roles(role_name)
active << [s, p]
end
active = active.sort_by(&:last).reverse # Sort again, since we may have added to array
end
active.each do |s, p|
next unless (inactive.length > 0) && (p > inactive.first.last)
s2, p2 = inactive.shift
_log.info("Migrating Role <#{role_name}> Active on Server <#{s.name}> with Priority <#{p}> to Server <#{s2.name}> with Priority <#{p2}>")
s.deactivate_roles(role_name)
s2.activate_roles(role_name)
active << [s2, p2]
end
end
end
end
def monitor_server_roles_timeout
::Settings.server.monitor_server_roles_timeout.to_i_with_method
end
def monitor_server_roles
MiqRegion.my_region.lock(:exclusive, monitor_server_roles_timeout) do |region|
region.zones.each do |zone|
synchronize_active_roles(zone.active_miq_servers.includes([:active_roles, :inactive_roles]), ServerRole.zone_scoped_roles)
end
synchronize_active_roles(region.active_miq_servers.includes([:active_roles, :inactive_roles]), ServerRole.region_scoped_roles)
end
end
def monitor_active_roles
return unless active_roles_changed?
roles_added, roles_deleted, _roles_unchanged = role_changes
roles_changed = roles_added | roles_deleted
log_role_changes
sync_active_roles
set_active_role_flags
EvmDatabase.restart_failover_monitor_service if roles_changed.include?("database_operations")
worker_manager.reset_queue_messages
worker_manager.notify_workers_of_config_change(Time.now.utc)
end
end