foreman_dlm 0.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +18 -6
- data/app/controllers/api/v2/dlmlock_events_controller.rb +42 -0
- data/app/controllers/api/v2/dlmlocks_controller.rb +31 -16
- data/app/controllers/concerns/foreman_dlm/find_host_by_client_cert.rb +7 -13
- data/app/controllers/concerns/foreman_dlm/find_host_by_ip.rb +1 -1
- data/app/controllers/concerns/foreman_dlm/update_checkin_time.rb +22 -0
- data/app/controllers/foreman_dlm/application_controller.rb +19 -0
- data/app/controllers/foreman_dlm/dlmlocks_controller.rb +82 -0
- data/app/helpers/foreman_dlm/dlmlock_helper.rb +33 -0
- data/app/jobs/foreman_dlm/refresh_dlmlock_status.rb +17 -0
- data/app/models/concerns/foreman_dlm/dlm_facet_host_extensions.rb +13 -0
- data/app/models/concerns/foreman_dlm/expirable.rb +36 -0
- data/app/models/concerns/foreman_dlm/host_extensions.rb +21 -2
- data/app/models/concerns/foreman_dlm/host_monitoring_extensions.rb +2 -0
- data/app/models/concerns/foreman_dlm/user_extensions.rb +13 -0
- data/app/models/foreman_dlm/dlm_facet.rb +7 -0
- data/app/models/foreman_dlm/dlmlock/update.rb +9 -0
- data/app/models/foreman_dlm/dlmlock.rb +137 -0
- data/app/models/foreman_dlm/dlmlock_event.rb +23 -0
- data/app/models/host_status/dlmlock_status.rb +44 -0
- data/app/views/api/v2/dlmlock_events/index.json.rabl +2 -0
- data/app/views/api/v2/dlmlocks/show.json.rabl +1 -1
- data/app/views/api/v2/errors/precondition_failed.json.rabl +1 -1
- data/app/views/foreman_dlm/api/v2/dlm_facets/base.json.rabl +1 -0
- data/app/views/foreman_dlm/api/v2/dlm_facets/base_with_root.json.rabl +3 -0
- data/app/views/foreman_dlm/api/v2/dlm_facets/show.json.rabl +3 -0
- data/app/views/foreman_dlm/dlmlocks/_details.html.erb +42 -0
- data/app/views/{dlmlocks → foreman_dlm/dlmlocks}/_list.html.erb +3 -1
- data/app/views/foreman_dlm/dlmlocks/index.html.erb +2 -0
- data/app/views/foreman_dlm/dlmlocks/show.html.erb +10 -0
- data/app/views/{dlmlocks → foreman_dlm/dlmlocks}/welcome.html.erb +2 -2
- data/app/views/hosts/_dlmlocks_tab.html.erb +39 -0
- data/config/routes.rb +20 -13
- data/contrib/systemd/foreman-dlm-expire-events.service +10 -0
- data/contrib/systemd/foreman-dlm-expire-events.timer +8 -0
- data/db/migrate/20170824084100_add_dlmlock.foreman_dlm.rb +1 -1
- data/db/migrate/20180627150003_rename_dlmlock_sti_models.rb +9 -0
- data/db/migrate/20180704162345_add_dlmlock_events.rb +11 -0
- data/db/migrate/20180711090022_add_hosts_fk_to_dlmlocks.rb +5 -0
- data/db/migrate/20180711111903_create_dlm_facets.foreman_dlm.rb +10 -0
- data/db/migrate/20180713113208_update_permissions_for_scoped_models.rb +13 -0
- data/lib/foreman_dlm/engine.rb +58 -19
- data/lib/foreman_dlm/version.rb +1 -1
- data/lib/tasks/dlmlock_events.rake +19 -0
- data/lib/tasks/foreman_dlm_tasks.rake +2 -4
- data/test/controllers/api/v2/dlmlocks_controller_test.rb +73 -52
- data/test/controllers/api/v2/dlmlocks_dlmlock_events_controller_test.rb +81 -0
- data/test/controllers/api/v2/hosts_controller_test.rb +28 -0
- data/test/controllers/find_host_by_client_cert_test.rb +2 -2
- data/test/controllers/foreman_dlm/dlmlocks_test.rb +55 -0
- data/test/controllers/hosts_controller_test.rb +12 -0
- data/test/factories/dlm_facets.rb +6 -0
- data/test/factories/dlmlock.rb +6 -2
- data/test/factories/dlmlock_events.rb +13 -0
- data/test/factories/host.rb +7 -0
- data/test/integration/foreman_dlm/dlmlocks_test.rb +28 -0
- data/test/jobs/refresh_dlmlock_status_test.rb +10 -0
- data/test/models/foreman_dlm/dlm_facet_test.rb +13 -0
- data/test/models/foreman_dlm/dlmlock_event_test.rb +19 -0
- data/test/models/foreman_dlm/dlmlock_test.rb +307 -0
- data/test/models/host_managed_test.rb +41 -0
- data/test/models/host_monitoring_test.rb +1 -1
- data/test/models/host_status/dlmlock_status_test.rb +45 -0
- data/test/models/user_test.rb +5 -0
- data/test/test_plugin_helper.rb +5 -3
- metadata +108 -30
- data/app/controllers/dlmlocks_controller.rb +0 -13
- data/app/models/dlmlock/update.rb +0 -5
- data/app/models/dlmlock.rb +0 -79
- data/app/views/dlmlocks/_details.html.erb +0 -35
- data/app/views/dlmlocks/index.html.erb +0 -2
- data/app/views/dlmlocks/show.html.erb +0 -7
- data/test/controllers/dlmlocks_test.rb +0 -24
- data/test/models/dlmlock_test.rb +0 -201
@@ -0,0 +1,137 @@
|
|
1
|
+
module ForemanDlm
|
2
|
+
class Dlmlock < ApplicationRecord
|
3
|
+
include Authorizable
|
4
|
+
|
5
|
+
def self.humanize_class_name
|
6
|
+
N_('Distributed Lock')
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.dlm_stale_time
|
10
|
+
(Setting[:dlm_stale_time] || 4).hours
|
11
|
+
end
|
12
|
+
|
13
|
+
belongs_to_host
|
14
|
+
|
15
|
+
has_many :dlmlock_events,
|
16
|
+
class_name: '::ForemanDlm::DlmlockEvent',
|
17
|
+
dependent: :destroy,
|
18
|
+
inverse_of: :dlmlock
|
19
|
+
|
20
|
+
validates :name, presence: true, uniqueness: true
|
21
|
+
|
22
|
+
after_save :log_enable_or_disable_event, if: -> { saved_change_to_enabled? }
|
23
|
+
after_save :log_release_and_acquire_events, if: -> { saved_change_to_host_id? }
|
24
|
+
|
25
|
+
def log_enable_or_disable_event
|
26
|
+
event_type = enabled ? :enable : :disable
|
27
|
+
log_event(host, event_type)
|
28
|
+
end
|
29
|
+
|
30
|
+
def log_release_and_acquire_events
|
31
|
+
old_host_id = saved_changes[:host_id].first
|
32
|
+
old_host = Host.find_by(id: old_host_id) if old_host_id
|
33
|
+
log_event(old_host, :release) if old_host
|
34
|
+
log_event(host, :acquire) if host
|
35
|
+
end
|
36
|
+
|
37
|
+
scope :locked, -> { where.not(host_id: nil) }
|
38
|
+
scope :stale, -> { locked.where('updated_at < ?', Time.now.utc - dlm_stale_time) }
|
39
|
+
|
40
|
+
scoped_search :on => :name, :complete_value => true, :default_order => true
|
41
|
+
scoped_search :relation => :host, :on => :name, :complete_value => true, :rename => :host
|
42
|
+
scoped_search :on => :type, :complete_value => true, :default_order => true
|
43
|
+
scoped_search :on => :enabled, :complete_value => { :true => true, :false => false }, :only_explicit => true
|
44
|
+
|
45
|
+
attr_accessor :old
|
46
|
+
|
47
|
+
def acquire!(host)
|
48
|
+
return false unless host.can_acquire_update_locks?
|
49
|
+
|
50
|
+
result = atomic_update(nil, host)
|
51
|
+
ForemanDlm::RefreshDlmlockStatus.set(wait: self.class.dlm_stale_time).perform_later([host.id]) if result
|
52
|
+
result
|
53
|
+
end
|
54
|
+
|
55
|
+
def release!(host)
|
56
|
+
atomic_update(host, nil)
|
57
|
+
end
|
58
|
+
|
59
|
+
def enable!
|
60
|
+
update(enabled: true)
|
61
|
+
end
|
62
|
+
|
63
|
+
def disable!
|
64
|
+
update(enabled: false)
|
65
|
+
end
|
66
|
+
|
67
|
+
def locked_by?(host)
|
68
|
+
self.host == host
|
69
|
+
end
|
70
|
+
alias acquired_by? locked_by?
|
71
|
+
|
72
|
+
def disabled?
|
73
|
+
!enabled?
|
74
|
+
end
|
75
|
+
|
76
|
+
def locked?
|
77
|
+
host.present?
|
78
|
+
end
|
79
|
+
alias taken? locked?
|
80
|
+
|
81
|
+
def humanized_type
|
82
|
+
_('Generic Lock')
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def atomic_update(old_host, new_host)
|
88
|
+
changes = { host_id: new_host.try(:id) }
|
89
|
+
self.old = dup
|
90
|
+
|
91
|
+
query = {
|
92
|
+
id: id,
|
93
|
+
host_id: [new_host.try(:id), old_host.try(:id)],
|
94
|
+
enabled: true
|
95
|
+
}
|
96
|
+
|
97
|
+
updated = self.class.where(query).update(changes.merge(updated_at: Time.now.utc))
|
98
|
+
|
99
|
+
unless updated.count.zero?
|
100
|
+
reload
|
101
|
+
process_host_change(old_host, new_host)
|
102
|
+
[old_host, new_host].compact.each(&:refresh_dlmlock_status)
|
103
|
+
return true
|
104
|
+
end
|
105
|
+
|
106
|
+
log_event(host, :fail)
|
107
|
+
|
108
|
+
false
|
109
|
+
end
|
110
|
+
|
111
|
+
def process_host_change(old_host, new_host)
|
112
|
+
return if host.try(:id) == old.host.try(:id)
|
113
|
+
|
114
|
+
run_callback(old_host, :unlock) if old.host
|
115
|
+
|
116
|
+
return unless host
|
117
|
+
|
118
|
+
run_callback(new_host, :lock)
|
119
|
+
end
|
120
|
+
|
121
|
+
def log_event(host, event_type)
|
122
|
+
DlmlockEvent.create!(
|
123
|
+
dlmlock: self,
|
124
|
+
event_type: event_type,
|
125
|
+
host: host,
|
126
|
+
user: User.current
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
def run_callback(h, callback)
|
131
|
+
h.run_callbacks callback do
|
132
|
+
logger.debug { "custom hook after_#{callback} on #{h} will be executed if defined." }
|
133
|
+
true
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ForemanDlm
|
2
|
+
class DlmlockEvent < ApplicationRecord
|
3
|
+
include Authorizable
|
4
|
+
include Expirable
|
5
|
+
|
6
|
+
TYPES = %w[release acquire enable disable fail].freeze
|
7
|
+
validates :event_type, inclusion: { in: TYPES }
|
8
|
+
|
9
|
+
def self.humanize_class_name
|
10
|
+
N_('Distributed Lock Event')
|
11
|
+
end
|
12
|
+
|
13
|
+
belongs_to_host
|
14
|
+
belongs_to :dlmlock, inverse_of: :dlmlock_events, class_name: 'ForemanDlm::Dlmlock'
|
15
|
+
belongs_to :user, inverse_of: :dlmlock_events
|
16
|
+
|
17
|
+
scoped_search on: :event_type, complete_value: true
|
18
|
+
|
19
|
+
def humanized_type
|
20
|
+
_('Dlmlock Event')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module HostStatus
|
2
|
+
class DlmlockStatus < Status
|
3
|
+
OK = 0
|
4
|
+
STALE = 1
|
5
|
+
|
6
|
+
def self.status_name
|
7
|
+
N_('Distributed Lock')
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_label(_options = {})
|
11
|
+
case to_status
|
12
|
+
when OK
|
13
|
+
N_('Ok')
|
14
|
+
when STALE
|
15
|
+
N_('Stale')
|
16
|
+
else
|
17
|
+
N_('Unknown')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_global(_options = {})
|
22
|
+
case to_status
|
23
|
+
when OK
|
24
|
+
HostStatus::Global::OK
|
25
|
+
else
|
26
|
+
HostStatus::Global::ERROR
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_status(_options = {})
|
31
|
+
ok? ? OK : STALE
|
32
|
+
end
|
33
|
+
|
34
|
+
def relevant?(_options = {})
|
35
|
+
host.dlmlocks.any?
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def ok?
|
41
|
+
host.dlmlocks.stale.empty?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
attributes :id, :last_checkin_at
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<% if authorizer.can?(:view_dlmlock_events) %>
|
2
|
+
<table class="<%= table_css_classes('table-fixed') %>">
|
3
|
+
<thead>
|
4
|
+
<tr>
|
5
|
+
<th><%= _("Host") %></th>
|
6
|
+
<th><%= _("User") %></th>
|
7
|
+
<th><%= _("Type") %></th>
|
8
|
+
<th><%= _("Timestamp") %></th>
|
9
|
+
</tr>
|
10
|
+
</thead>
|
11
|
+
<tbody>
|
12
|
+
<% @dlmlock.dlmlock_events.includes(:user).reorder(created_at: :desc).each do |event| %>
|
13
|
+
|
14
|
+
<tr>
|
15
|
+
<td>
|
16
|
+
<% if event.host %>
|
17
|
+
<%= link_to_if_authorized(event.host.name, hash_for_host_path(:id => event.host)) %>
|
18
|
+
<% end %>
|
19
|
+
</td>
|
20
|
+
|
21
|
+
<td>
|
22
|
+
<% if event.user %>
|
23
|
+
<% if event.user.hidden? %>
|
24
|
+
<em><%= event.user.name %></em>
|
25
|
+
<% else %>
|
26
|
+
<%= link_to_if_authorized(event.user.name, hash_for_edit_user_path(event.user)) %>
|
27
|
+
<% end %>
|
28
|
+
<% end %>
|
29
|
+
</td>
|
30
|
+
|
31
|
+
<td>
|
32
|
+
<%= _(event.event_type.humanize) %>
|
33
|
+
</td>
|
34
|
+
|
35
|
+
<td>
|
36
|
+
<%= event.created_at %>
|
37
|
+
</td>
|
38
|
+
</tr>
|
39
|
+
<% end %>
|
40
|
+
</tbody>
|
41
|
+
</table>
|
42
|
+
<% end %>
|
@@ -5,6 +5,7 @@
|
|
5
5
|
<th><%= sort :host, :as => _("Owner") %></th>
|
6
6
|
<th><%= sort :type, :as => _("Type") %></th>
|
7
7
|
<th><%= sort :enabled, :as => _("Enabled") %></th>
|
8
|
+
<th class="col-md-2"><%= _('Actions') %></th>
|
8
9
|
</tr>
|
9
10
|
</thead>
|
10
11
|
<tbody>
|
@@ -12,7 +13,7 @@
|
|
12
13
|
<tr class="<%= lock.enabled? ? '' : 'warning' %>">
|
13
14
|
<td>
|
14
15
|
<%= icon_text(dlmlock_status_icon_class(lock),
|
15
|
-
link_to_if_authorized(lock.name,
|
16
|
+
link_to_if_authorized(lock.name, hash_for_foreman_dlm_dlmlock_path(:id => lock)),
|
16
17
|
kind: 'fa',
|
17
18
|
class: "#{dlmlock_status_icon_color_class(lock)} fa-lg")
|
18
19
|
%>
|
@@ -38,6 +39,7 @@
|
|
38
39
|
<%= icon_text('toggle-off', 'Disabled', {kind: 'fa', class: 'center fa-lg', title: _('Disabled')}) %>
|
39
40
|
<% end %>
|
40
41
|
</td>
|
42
|
+
<td><%= action_buttons(*dlmlock_actions(lock, authorizer)) %></td>
|
41
43
|
</tr>
|
42
44
|
<% end %>
|
43
45
|
</tbody>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% title @dlmlock.name %>
|
2
|
+
<% breadcrumbs(
|
3
|
+
resource_url: api_dlmlocks_path
|
4
|
+
) if respond_to?(:breadcrumbs) # Requires Foreman >= 1.18 %>
|
5
|
+
|
6
|
+
<%= title_actions link_to(_('Back'), foreman_dlm_dlmlocks_path, :class => 'btn btn-default'),
|
7
|
+
((link_to(_("Host details"), @dlmlock.host, :class => 'btn btn-default') if @dlmlock.host.present?))
|
8
|
+
%>
|
9
|
+
|
10
|
+
<%= render 'details' %>
|
@@ -6,9 +6,9 @@
|
|
6
6
|
<p>
|
7
7
|
<%= _('You don\'t seem to have any locks.') %></br>
|
8
8
|
<%= _('The distributed lock manager allows you to automatically schedule system updates across a cluster of hosts.') %>
|
9
|
-
<%= link_to _('Learn more about this in the documentation.'), 'https://github.com/
|
9
|
+
<%= link_to _('Learn more about this in the documentation.'), 'https://github.com/dm-drogeriemarkt/foreman_dlm', :rel => "external" %>.
|
10
10
|
</p>
|
11
11
|
<div class="blank-slate-pf-main-action">
|
12
|
-
<%= link_to _('Documentation'), 'https://github.com/
|
12
|
+
<%= link_to _('Documentation'), 'https://github.com/dm-drogeriemarkt/foreman_dlm', :rel => 'external', :class => 'btn btn-primary btn-lg' %>
|
13
13
|
</div>
|
14
14
|
</div>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<% if @host.dlmlocks.any? %>
|
2
|
+
<%= alert class: 'alert-info',
|
3
|
+
header: '',
|
4
|
+
text: n_(
|
5
|
+
'This host holds one lock.',
|
6
|
+
'This host holds %s locks.',
|
7
|
+
@host.dlmlocks.count
|
8
|
+
) % @host.dlmlocks.count
|
9
|
+
%>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<table class="<%= table_css_classes %>">
|
13
|
+
<thead>
|
14
|
+
<tr>
|
15
|
+
<th colspan="2"><%= _('Locks') %></th>
|
16
|
+
</tr>
|
17
|
+
</thead>
|
18
|
+
<tbody>
|
19
|
+
<tr>
|
20
|
+
<td class="text-nowrap"><%= _('Last check-in') %></td>
|
21
|
+
<td><%= @host.dlm_facet && @host.dlm_facet.last_checkin_at ? date_time_relative(@host.dlm_facet.last_checkin_at) : _('N/A') %></td>
|
22
|
+
</tr>
|
23
|
+
<tr>
|
24
|
+
<td><%= _('Holds Locks') %></td>
|
25
|
+
<td>
|
26
|
+
<% if @host.dlmlocks.any? %>
|
27
|
+
<% @host.dlmlocks.authorized(:view_dlmlocks).each do |lock| %>
|
28
|
+
<%= link_to_if_authorized(lock.name, hash_for_foreman_dlm_dlmlock_path(lock)) %>
|
29
|
+
<span class="label label-<%= lock.updated_at > 6.hours.ago ? 'info' : 'warning' %>">
|
30
|
+
<%= _('acquired') %> <%= date_time_relative_value(lock.updated_at) %>
|
31
|
+
</span>
|
32
|
+
<% end %>
|
33
|
+
<% else %>
|
34
|
+
<%= _('None') %>
|
35
|
+
<% end %>
|
36
|
+
</td>
|
37
|
+
</tr>
|
38
|
+
</tbody>
|
39
|
+
</table>
|
data/config/routes.rb
CHANGED
@@ -1,24 +1,31 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
2
|
namespace :api, :defaults => { :format => 'json' } do
|
3
3
|
scope '(:apiv)', :module => :v2,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
4
|
+
:defaults => { :apiv => 'v2' },
|
5
|
+
:apiv => /v1|v2/,
|
6
|
+
:constraints => ApiConstraints.new(:version => 2, :default => true) do
|
7
|
+
constraints(id: /[^\/]+/) do
|
8
|
+
resources :dlmlocks, only: [:index, :show, :update, :destroy] do
|
9
|
+
resources :dlmlock_events, only: [:index]
|
10
|
+
|
11
|
+
get :lock, on: :member, action: :show, controller: 'dlmlocks'
|
12
|
+
put :lock, on: :member, action: :acquire, controller: 'dlmlocks'
|
13
|
+
delete :lock, on: :member, action: :release, controller: 'dlmlocks'
|
13
14
|
end
|
14
|
-
resources :dlmlocks, only: [:create]
|
15
15
|
end
|
16
|
+
resources :dlmlocks, only: [:create]
|
17
|
+
end
|
16
18
|
end
|
17
19
|
|
18
|
-
|
19
|
-
resources :dlmlocks, only: [:index, :show] do
|
20
|
+
namespace :foreman_dlm do
|
21
|
+
resources :dlmlocks, only: [:index, :show, :destroy] do
|
20
22
|
collection do
|
21
|
-
get
|
23
|
+
get :auto_complete_search
|
24
|
+
end
|
25
|
+
member do
|
26
|
+
put :enable
|
27
|
+
put :disable
|
28
|
+
put :release
|
22
29
|
end
|
23
30
|
end
|
24
31
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
[Unit]
|
2
|
+
Description=Clean up expired Foreman DLM events
|
3
|
+
Documentation=https://github.com/dm-drogeriemarkt/foreman_dlm/blob/master/README.md
|
4
|
+
Requires=network.target
|
5
|
+
|
6
|
+
[Service]
|
7
|
+
Type=oneshot
|
8
|
+
EnvironmentFile=-/etc/sysconfig/foreman_dlm
|
9
|
+
ExecStart=/sbin/foreman-rake dlmlocks:expire
|
10
|
+
TimeoutSec=30m
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class RenameDlmlockStiModels < ActiveRecord::Migration[5.1]
|
2
|
+
def up
|
3
|
+
execute "UPDATE dlmlocks set type='ForemanDlm::Dlmlock::Update' where type='Dlmlock::Update';"
|
4
|
+
end
|
5
|
+
|
6
|
+
def down
|
7
|
+
execute "UPDATE dlmlocks set type='Dlmlock::Update' where type='ForemanDlm::Dlmlock::Update';"
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class AddDlmlockEvents < ActiveRecord::Migration[5.1]
|
2
|
+
def change
|
3
|
+
create_table :dlmlock_events do |t|
|
4
|
+
t.integer :dlmlock_id, index: true, null: false
|
5
|
+
t.string :event_type, index: true
|
6
|
+
t.integer :host_id, index: true
|
7
|
+
t.integer :user_id
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class CreateDlmFacets < ActiveRecord::Migration[5.1]
|
2
|
+
def change
|
3
|
+
create_table :dlm_facets do |t|
|
4
|
+
t.references :host, null: false, foreign_key: true, index: true, unique: true
|
5
|
+
t.column :last_checkin_at, :datetime
|
6
|
+
|
7
|
+
t.timestamps null: false
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class UpdatePermissionsForScopedModels < ActiveRecord::Migration[5.1]
|
2
|
+
class FakePermission < ApplicationRecord
|
3
|
+
self.table_name = 'permissions'
|
4
|
+
end
|
5
|
+
|
6
|
+
def up
|
7
|
+
FakePermission.where(resource_type: 'Dlmlock').update_all(resource_type: 'ForemanDlm::Dlmlock')
|
8
|
+
end
|
9
|
+
|
10
|
+
def down
|
11
|
+
FakePermission.where(resource_type: 'ForemanDlm::Dlmlock').update_all(resource_type: 'Dlmlock')
|
12
|
+
end
|
13
|
+
end
|
data/lib/foreman_dlm/engine.rb
CHANGED
@@ -4,6 +4,7 @@ module ForemanDlm
|
|
4
4
|
|
5
5
|
config.autoload_paths += Dir["#{config.root}/app/controllers/concerns"]
|
6
6
|
config.autoload_paths += Dir["#{config.root}/app/models/concerns"]
|
7
|
+
config.autoload_paths += Dir["#{config.root}/app/jobs"]
|
7
8
|
|
8
9
|
# Add any db migrations
|
9
10
|
initializer 'foreman_dlm.load_app_instance_data' do |app|
|
@@ -14,63 +15,101 @@ module ForemanDlm
|
|
14
15
|
|
15
16
|
initializer 'foreman_dlm.register_plugin', :before => :finisher_hook do |_app|
|
16
17
|
Foreman::Plugin.register :foreman_dlm do
|
17
|
-
requires_foreman '>=
|
18
|
+
requires_foreman '>= 3.0'
|
18
19
|
|
19
20
|
apipie_documented_controllers ["#{ForemanDlm::Engine.root}/app/controllers/api/v2/*.rb"]
|
20
21
|
|
22
|
+
settings do
|
23
|
+
category(:general) do
|
24
|
+
setting('dlm_stale_time',
|
25
|
+
type: :integer,
|
26
|
+
default: 4,
|
27
|
+
description: N_('Number of hours after which locked Distributed Lock is stale'),
|
28
|
+
full_name: N_('Distributed Lock stale time'),
|
29
|
+
validate: { numericality: { greater_than: 0 } })
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
21
33
|
# Add permissions
|
22
34
|
security_block :foreman_dlm do
|
23
35
|
permission :view_dlmlocks, {
|
24
|
-
:dlmlocks => [:index, :show, :auto_complete_search],
|
36
|
+
:'foreman_dlm/dlmlocks' => [:index, :show, :auto_complete_search],
|
25
37
|
:'api/v2/dlmlocks' => [:index, :show]
|
26
|
-
}, :resource_type => 'Dlmlock'
|
38
|
+
}, :resource_type => 'ForemanDlm::Dlmlock'
|
27
39
|
|
28
40
|
permission :create_dlmlocks, {
|
29
41
|
:'api/v2/dlmlocks' => [:create]
|
30
|
-
}, :resource_type => 'Dlmlock'
|
42
|
+
}, :resource_type => 'ForemanDlm::Dlmlock'
|
31
43
|
|
32
44
|
permission :edit_dlmlocks, {
|
45
|
+
:'foreman_dlm/dlmlocks' => [:release, :enable, :disable],
|
33
46
|
:'api/v2/dlmlocks' => [:update, :acquire, :release]
|
34
|
-
}, :resource_type => 'Dlmlock'
|
47
|
+
}, :resource_type => 'ForemanDlm::Dlmlock'
|
35
48
|
|
36
49
|
permission :destroy_dlmlocks, {
|
50
|
+
:'foreman_dlm/dlmlocks' => [:destroy],
|
37
51
|
:'api/v2/dlmlocks' => [:destroy]
|
38
|
-
}, :resource_type => 'Dlmlock'
|
52
|
+
}, :resource_type => 'ForemanDlm::Dlmlock'
|
53
|
+
|
54
|
+
permission :view_dlmlock_events, {
|
55
|
+
:'api/v2/dlmlock_events' => [:index]
|
56
|
+
}, :resource_type => 'ForemanDlm::DlmlockEvent'
|
39
57
|
end
|
40
58
|
|
41
59
|
# Add a new role called 'Distributed Lock Manager' if it doesn't exist
|
42
|
-
role 'Distributed Lock Manager', [:view_dlmlocks,
|
60
|
+
role 'Distributed Lock Manager', [:view_dlmlocks,
|
61
|
+
:create_dlmlocks,
|
62
|
+
:edit_dlmlocks,
|
63
|
+
:destroy_dlmlocks,
|
64
|
+
:view_dlmlock_events],
|
65
|
+
'Role granting full access permissions to distributed locks'
|
43
66
|
|
44
67
|
# add menu entry
|
45
|
-
menu :top_menu, :
|
46
|
-
url_hash: { controller: :'dlmlocks', action: :index },
|
68
|
+
menu :top_menu, :foreman_dlm_dlmlocks,
|
69
|
+
url_hash: { controller: :'foreman_dlm/dlmlocks', action: :index },
|
47
70
|
caption: N_('Distributed Locks'),
|
48
71
|
parent: :monitor_menu,
|
49
72
|
after: :audits
|
73
|
+
|
74
|
+
# Dlm Facet
|
75
|
+
register_facet(ForemanDlm::DlmFacet, :dlm_facet) do
|
76
|
+
api_view list: 'foreman_dlm/api/v2/dlm_facets/base_with_root', single: 'foreman_dlm/api/v2/dlm_facets/show'
|
77
|
+
end
|
78
|
+
|
79
|
+
register_custom_status HostStatus::DlmlockStatus
|
80
|
+
|
81
|
+
# extend host show page
|
82
|
+
extend_page('hosts/show') do |context|
|
83
|
+
context.add_pagelet :main_tabs,
|
84
|
+
:name => N_('Locks'),
|
85
|
+
:partial => 'hosts/dlmlocks_tab',
|
86
|
+
:onlyif => proc { |host| host.dlm_facet }
|
87
|
+
end
|
50
88
|
end
|
51
89
|
end
|
52
90
|
|
53
91
|
# Include concerns in this config.to_prepare block
|
54
92
|
config.to_prepare do
|
55
|
-
|
56
|
-
|
93
|
+
Host::Managed.include ForemanDlm::HostExtensions
|
94
|
+
User.include ForemanDlm::UserExtensions
|
95
|
+
Host::Managed.include ForemanDlm::DlmFacetHostExtensions
|
57
96
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
rescue => e
|
62
|
-
Rails.logger.warn "ForemanDlm: skipping engine hook (#{e})"
|
63
|
-
end
|
97
|
+
Host::Managed.include ForemanDlm::HostMonitoringExtensions if ForemanDlm.with_monitoring?
|
98
|
+
rescue StandardError => e
|
99
|
+
Rails.logger.warn "ForemanDlm: skipping engine hook (#{e})"
|
64
100
|
end
|
65
101
|
|
66
102
|
initializer 'foreman_dlm.register_gettext', after: :load_config_initializers do |_app|
|
67
|
-
locale_dir = File.join(File.expand_path('
|
103
|
+
locale_dir = File.join(File.expand_path('../..', __dir__), 'locale')
|
68
104
|
locale_domain = 'foreman_dlm'
|
69
105
|
Foreman::Gettext::Support.add_text_domain locale_domain, locale_dir
|
70
106
|
end
|
71
107
|
end
|
72
108
|
|
73
109
|
def self.with_monitoring?
|
74
|
-
|
110
|
+
ForemanMonitoring # rubocop:disable Lint/Void
|
111
|
+
true
|
112
|
+
rescue StandardError
|
113
|
+
false
|
75
114
|
end
|
76
115
|
end
|
data/lib/foreman_dlm/version.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
desc <<-TASK_DESCRIPTION
|
2
|
+
Expire lock events automatically
|
3
|
+
|
4
|
+
Available conditions:
|
5
|
+
* days => number of days to keep reports (defaults to 14)
|
6
|
+
* batch_size => number of records deleted in single SQL transaction (defaults to 1k)
|
7
|
+
* sleep_time => delay in seconds between batches (defaults to 0.2)
|
8
|
+
|
9
|
+
TASK_DESCRIPTION
|
10
|
+
|
11
|
+
namespace :dlmlocks do
|
12
|
+
task expire: :environment do
|
13
|
+
created_before = ENV['days'].to_i.days if ENV['days']
|
14
|
+
batch_size = ENV['batch_size'].to_i if ENV['batch_size']
|
15
|
+
sleep_time = ENV['sleep_time'].to_f if ENV['sleep_time']
|
16
|
+
|
17
|
+
ForemanDlm::DlmlockEvent.expire(created_before: created_before, batch_size: batch_size, sleep_time: sleep_time)
|
18
|
+
end
|
19
|
+
end
|