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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +18 -6
  3. data/app/controllers/api/v2/dlmlock_events_controller.rb +42 -0
  4. data/app/controllers/api/v2/dlmlocks_controller.rb +31 -16
  5. data/app/controllers/concerns/foreman_dlm/find_host_by_client_cert.rb +7 -13
  6. data/app/controllers/concerns/foreman_dlm/find_host_by_ip.rb +1 -1
  7. data/app/controllers/concerns/foreman_dlm/update_checkin_time.rb +22 -0
  8. data/app/controllers/foreman_dlm/application_controller.rb +19 -0
  9. data/app/controllers/foreman_dlm/dlmlocks_controller.rb +82 -0
  10. data/app/helpers/foreman_dlm/dlmlock_helper.rb +33 -0
  11. data/app/jobs/foreman_dlm/refresh_dlmlock_status.rb +17 -0
  12. data/app/models/concerns/foreman_dlm/dlm_facet_host_extensions.rb +13 -0
  13. data/app/models/concerns/foreman_dlm/expirable.rb +36 -0
  14. data/app/models/concerns/foreman_dlm/host_extensions.rb +21 -2
  15. data/app/models/concerns/foreman_dlm/host_monitoring_extensions.rb +2 -0
  16. data/app/models/concerns/foreman_dlm/user_extensions.rb +13 -0
  17. data/app/models/foreman_dlm/dlm_facet.rb +7 -0
  18. data/app/models/foreman_dlm/dlmlock/update.rb +9 -0
  19. data/app/models/foreman_dlm/dlmlock.rb +137 -0
  20. data/app/models/foreman_dlm/dlmlock_event.rb +23 -0
  21. data/app/models/host_status/dlmlock_status.rb +44 -0
  22. data/app/views/api/v2/dlmlock_events/index.json.rabl +2 -0
  23. data/app/views/api/v2/dlmlocks/show.json.rabl +1 -1
  24. data/app/views/api/v2/errors/precondition_failed.json.rabl +1 -1
  25. data/app/views/foreman_dlm/api/v2/dlm_facets/base.json.rabl +1 -0
  26. data/app/views/foreman_dlm/api/v2/dlm_facets/base_with_root.json.rabl +3 -0
  27. data/app/views/foreman_dlm/api/v2/dlm_facets/show.json.rabl +3 -0
  28. data/app/views/foreman_dlm/dlmlocks/_details.html.erb +42 -0
  29. data/app/views/{dlmlocks → foreman_dlm/dlmlocks}/_list.html.erb +3 -1
  30. data/app/views/foreman_dlm/dlmlocks/index.html.erb +2 -0
  31. data/app/views/foreman_dlm/dlmlocks/show.html.erb +10 -0
  32. data/app/views/{dlmlocks → foreman_dlm/dlmlocks}/welcome.html.erb +2 -2
  33. data/app/views/hosts/_dlmlocks_tab.html.erb +39 -0
  34. data/config/routes.rb +20 -13
  35. data/contrib/systemd/foreman-dlm-expire-events.service +10 -0
  36. data/contrib/systemd/foreman-dlm-expire-events.timer +8 -0
  37. data/db/migrate/20170824084100_add_dlmlock.foreman_dlm.rb +1 -1
  38. data/db/migrate/20180627150003_rename_dlmlock_sti_models.rb +9 -0
  39. data/db/migrate/20180704162345_add_dlmlock_events.rb +11 -0
  40. data/db/migrate/20180711090022_add_hosts_fk_to_dlmlocks.rb +5 -0
  41. data/db/migrate/20180711111903_create_dlm_facets.foreman_dlm.rb +10 -0
  42. data/db/migrate/20180713113208_update_permissions_for_scoped_models.rb +13 -0
  43. data/lib/foreman_dlm/engine.rb +58 -19
  44. data/lib/foreman_dlm/version.rb +1 -1
  45. data/lib/tasks/dlmlock_events.rake +19 -0
  46. data/lib/tasks/foreman_dlm_tasks.rake +2 -4
  47. data/test/controllers/api/v2/dlmlocks_controller_test.rb +73 -52
  48. data/test/controllers/api/v2/dlmlocks_dlmlock_events_controller_test.rb +81 -0
  49. data/test/controllers/api/v2/hosts_controller_test.rb +28 -0
  50. data/test/controllers/find_host_by_client_cert_test.rb +2 -2
  51. data/test/controllers/foreman_dlm/dlmlocks_test.rb +55 -0
  52. data/test/controllers/hosts_controller_test.rb +12 -0
  53. data/test/factories/dlm_facets.rb +6 -0
  54. data/test/factories/dlmlock.rb +6 -2
  55. data/test/factories/dlmlock_events.rb +13 -0
  56. data/test/factories/host.rb +7 -0
  57. data/test/integration/foreman_dlm/dlmlocks_test.rb +28 -0
  58. data/test/jobs/refresh_dlmlock_status_test.rb +10 -0
  59. data/test/models/foreman_dlm/dlm_facet_test.rb +13 -0
  60. data/test/models/foreman_dlm/dlmlock_event_test.rb +19 -0
  61. data/test/models/foreman_dlm/dlmlock_test.rb +307 -0
  62. data/test/models/host_managed_test.rb +41 -0
  63. data/test/models/host_monitoring_test.rb +1 -1
  64. data/test/models/host_status/dlmlock_status_test.rb +45 -0
  65. data/test/models/user_test.rb +5 -0
  66. data/test/test_plugin_helper.rb +5 -3
  67. metadata +108 -30
  68. data/app/controllers/dlmlocks_controller.rb +0 -13
  69. data/app/models/dlmlock/update.rb +0 -5
  70. data/app/models/dlmlock.rb +0 -79
  71. data/app/views/dlmlocks/_details.html.erb +0 -35
  72. data/app/views/dlmlocks/index.html.erb +0 -2
  73. data/app/views/dlmlocks/show.html.erb +0 -7
  74. data/test/controllers/dlmlocks_test.rb +0 -24
  75. data/test/models/dlmlock_test.rb +0 -201
@@ -1,79 +0,0 @@
1
- class Dlmlock < ActiveRecord::Base
2
- include Authorizable
3
-
4
- def self.humanize_class_name
5
- N_('Distributed Lock')
6
- end
7
-
8
- belongs_to_host
9
- audited
10
-
11
- validates :name, presence: true, uniqueness: true
12
-
13
- scoped_search :on => :name, :complete_value => true, :default_order => true
14
- scoped_search :relation => :host, :on => :name, :complete_value => true, :rename => :host
15
- scoped_search :on => :type, :complete_value => true, :default_order => true
16
- scoped_search :on => :enabled, :complete_value => { :true => true, :false => false }, :only_explicit => true
17
-
18
- attr_accessor :old
19
-
20
- def acquire!(host)
21
- atomic_update(nil, host)
22
- end
23
-
24
- def release!(host)
25
- atomic_update(host, nil)
26
- end
27
-
28
- def locked_by?(host)
29
- self.host == host
30
- end
31
- alias_method :acquired_by?, :locked_by?
32
-
33
- def disabled?
34
- !enabled?
35
- end
36
-
37
- def locked?
38
- host.present?
39
- end
40
- alias_method :taken?, :locked?
41
-
42
- def humanized_type
43
- _('Generic Lock')
44
- end
45
-
46
- private
47
-
48
- def atomic_update(old_host, new_host)
49
- changes = {
50
- host_id: new_host.try(:id)
51
- }
52
- self.old = dup
53
- num_updated = self.class.where(
54
- id: id,
55
- host_id: [new_host.try(:id), old_host.try(:id)],
56
- enabled: true
57
- ).update_all(changes.merge(updated_at: DateTime.now))
58
- if num_updated > 0
59
- reload
60
- process_host_change(old_host, new_host, changes)
61
- return self
62
- end
63
- false
64
- end
65
-
66
- def process_host_change(old_host, new_host, changes)
67
- return if host.try(:id) == old.host.try(:id)
68
- write_audit(action: 'update', audited_changes: changes)
69
- run_callback(old_host, :unlock) if old.host
70
- run_callback(new_host, :lock) if host
71
- end
72
-
73
- def run_callback(h, callback)
74
- h.run_callbacks callback do
75
- logger.debug { "custom hook after_#{callback} on #{h} will be executed if defined." }
76
- true
77
- end
78
- end
79
- end
@@ -1,35 +0,0 @@
1
- <table class="<%= table_css_classes('table-fixed') %>">
2
- <thead>
3
- <tr>
4
- <th><%= _("Owner") %></th>
5
- <th><%= _("Initiator") %></th>
6
- <th><%= _("Timestamp") %></th>
7
- <th><%= _("Enabled") %></th>
8
- </tr>
9
- </thead>
10
- <tbody>
11
- <% @dlmlock.audits.includes(:user).reorder(created_at: :desc).each do |audit| %>
12
- <% revision = audit.revision %>
13
- <tr>
14
- <td>
15
- <% if revision.host.present? %>
16
- <%= link_to_if_authorized(revision.host.name, hash_for_host_path(:id => revision.host)) %>
17
- <% end %>
18
- </td>
19
- <td>
20
- <% if audit.user.hidden? %>
21
- <em><%= audit.user.name %></em>
22
- <% else %>
23
- <%= link_to_if_authorized(audit.user.name, hash_for_edit_user_path(audit.user)) %>
24
- <% end %>
25
- </td>
26
- <td>
27
- <%= audit.created_at %>
28
- </td>
29
- <td>
30
- <%= revision.enabled? %>
31
- </td>
32
- </tr>
33
- <% end %>
34
- </tbody>
35
- </table>
@@ -1,2 +0,0 @@
1
- <% title _("Locks") %>
2
- <%= render :partial => 'list' %>
@@ -1,7 +0,0 @@
1
- <% title "#{@dlmlock.name} "%>
2
-
3
- <%= title_actions link_to(_('Back'), :back, :class => 'btn btn-default'),
4
- ((link_to(_("Host details"), @dlmlock.host, :class => 'btn btn-default') if @dlmlock.host.present?))
5
- %>
6
-
7
- <%= render 'details' %>
@@ -1,24 +0,0 @@
1
- require 'test_plugin_helper'
2
-
3
- class DlmlocksControllerTest < ActionController::TestCase
4
- test '#index' do
5
- FactoryBot.create(:dlmlock)
6
- get :index, {}, set_session_user
7
- assert_response :success
8
- assert_not_nil assigns('dlmlocks')
9
- assert_template 'index'
10
- end
11
-
12
- test '#index with no lock shows welcome page' do
13
- get :index, {}, set_session_user
14
- assert_response :success
15
- assert_template 'welcome'
16
- end
17
-
18
- test '#show' do
19
- dlmlock = FactoryBot.create(:dlmlock)
20
- get :show, { :id => dlmlock.id }, set_session_user
21
- assert_response :success
22
- assert_template 'show'
23
- end
24
- end
@@ -1,201 +0,0 @@
1
- require 'test_plugin_helper'
2
-
3
- class DlmlockTest < ActiveSupport::TestCase
4
- setup do
5
- User.current = users(:admin)
6
- end
7
-
8
- subject { FactoryBot.create(:dlmlock) }
9
- should validate_presence_of(:name)
10
- should validate_uniqueness_of(:name)
11
-
12
- let(:host1) { FactoryBot.create(:host, :managed) }
13
- let(:host2) { FactoryBot.create(:host, :managed) }
14
-
15
- class HostWithCallbacks < ::Host::Managed
16
- attr_accessor :callbacks
17
-
18
- def initialize(*attributes, &block)
19
- super
20
- @callbacks = []
21
- end
22
-
23
- after_lock :callback1
24
- after_unlock :callback2
25
-
26
- def callback1
27
- Rails.logger.debug "callback1 executed for #{self} (#{self.class})"
28
- callbacks << 'callback1'
29
- end
30
-
31
- def callback2
32
- Rails.logger.debug "callback2 executed for #{self} (#{self.class})"
33
- callbacks << 'callback2'
34
- end
35
- end
36
-
37
- let(:host1_with_callbacks) { HostWithCallbacks.create(:name => 'test1.example.com') }
38
- let(:host2_with_callbacks) { HostWithCallbacks.create(:name => 'test2.example.com') }
39
-
40
- context 'a free and enabled DLM lock' do
41
- let(:dlmlock) { FactoryBot.create(:dlmlock) }
42
-
43
- test 'should be enabled and unlocked' do
44
- assert_equal true, dlmlock.enabled?
45
- assert_equal false, dlmlock.disabled?
46
- assert_equal false, dlmlock.locked?
47
- assert_equal false, dlmlock.taken?
48
- end
49
-
50
- test 'can be acquired' do
51
- assert_nil dlmlock.host
52
- assert dlmlock.acquire!(host1)
53
- assert_equal host1, dlmlock.reload.host
54
- end
55
-
56
- test 'can be released' do
57
- assert_nil dlmlock.host
58
- assert dlmlock.release!(host1)
59
- assert_nil dlmlock.reload.host
60
- end
61
-
62
- test 'records audit change on acquisition by owner' do
63
- assert_difference "Audit.where(auditable_type: 'Dlmlock').count" do
64
- assert dlmlock.acquire!(host1)
65
- end
66
- audit_record = dlmlock.audits.last
67
- assert_equal 'update', audit_record.action
68
- assert_equal({:host_id => host1.id}, audit_record.audited_changes)
69
- end
70
-
71
- test 'records no audit change on release' do
72
- assert_no_difference "Audit.where(auditable_type: 'Dlmlock').count" do
73
- assert dlmlock.release!(host1)
74
- end
75
- end
76
-
77
- test 'triggers after_lock callback' do
78
- host = HostWithCallbacks.new
79
- host.name = 'test.example.com'
80
- host.save
81
- assert dlmlock.acquire!(host)
82
- assert_equal ['callback1'], host.callbacks
83
- end
84
- end
85
-
86
- context 'a free and disabled DLM lock' do
87
- let(:dlmlock) { FactoryBot.create(:dlmlock, :enabled => false) }
88
-
89
- test 'should be disabled and unlocked' do
90
- assert_equal false, dlmlock.enabled?
91
- assert_equal true, dlmlock.disabled?
92
- assert_equal false, dlmlock.locked?
93
- assert_equal false, dlmlock.taken?
94
- end
95
-
96
- test 'can not be acquired' do
97
- assert_nil dlmlock.host
98
- assert_equal false, dlmlock.acquire!(host1)
99
- assert_nil dlmlock.reload.host
100
- end
101
-
102
- test 'can not be released' do
103
- assert_nil dlmlock.host
104
- assert_equal false, dlmlock.release!(host1)
105
- assert_nil dlmlock.reload.host
106
- end
107
-
108
- test 'triggers no callbacks' do
109
- host = HostWithCallbacks.new
110
- host.name = 'test.example.com'
111
- host.save
112
- assert_equal false, dlmlock.release!(host)
113
- assert_equal [], host.callbacks
114
- end
115
- end
116
-
117
- context 'an acquired DLM lock' do
118
- let(:dlmlock) { FactoryBot.create(:dlmlock, :host => host1) }
119
-
120
- test 'should be enabled and locked' do
121
- assert_equal true, dlmlock.enabled?
122
- assert_equal false, dlmlock.disabled?
123
- assert_equal true, dlmlock.locked?
124
- assert_equal true, dlmlock.taken?
125
- assert_equal true, dlmlock.locked_by?(host1)
126
- assert_equal true, dlmlock.acquired_by?(host1)
127
- end
128
-
129
- test 'can be acquired by owner' do
130
- assert_equal host1, dlmlock.host
131
- assert dlmlock.acquire!(host1)
132
- assert_equal host1, dlmlock.reload.host
133
- end
134
-
135
- test 'can not be acquired by other host' do
136
- assert_equal host1, dlmlock.host
137
- assert_equal false, dlmlock.acquire!(host2)
138
- assert_equal host1, dlmlock.reload.host
139
- end
140
-
141
- test 'can be released by owner' do
142
- assert_equal host1, dlmlock.host
143
- assert dlmlock.release!(host1)
144
- assert_nil dlmlock.reload.host
145
- end
146
-
147
- test 'can not be released by other host' do
148
- assert_equal host1, dlmlock.host
149
- assert_equal false, dlmlock.release!(host2)
150
- assert_equal host1, dlmlock.reload.host
151
- end
152
-
153
- test 'records audit change on release by owner' do
154
- assert_difference "Audit.where(auditable_type: 'Dlmlock').count" do
155
- assert dlmlock.release!(host1)
156
- end
157
- audit_record = dlmlock.audits.last
158
- assert_equal 'update', audit_record.action
159
- assert_equal({:host_id => nil}, audit_record.audited_changes)
160
- end
161
-
162
- test 'records no audit change on acquisition by owner' do
163
- assert_no_difference "Audit.where(auditable_type: 'Dlmlock').count" do
164
- assert dlmlock.acquire!(host1)
165
- end
166
- end
167
-
168
- test 'triggers after_unlock callback on release by owner' do
169
- host = HostWithCallbacks.new
170
- host.name = 'test.example.com'
171
- host.save
172
- dlmlock.host = host
173
- dlmlock.save
174
- assert dlmlock.release!(host)
175
- assert_equal ['callback2'], host.callbacks
176
- end
177
-
178
- test 'triggers no callbacks on release attempt by other host' do
179
- assert host1_with_callbacks
180
- assert host2_with_callbacks
181
- dlmlock.update(:host => host1_with_callbacks)
182
- assert_equal false, dlmlock.release!(host2_with_callbacks)
183
- assert_equal [], host1_with_callbacks.callbacks
184
- assert_equal [], host2_with_callbacks.callbacks
185
- end
186
-
187
- test 'triggers no callbacks on acquiry attempt by owner' do
188
- assert host1_with_callbacks
189
- dlmlock.update(:host => host1_with_callbacks)
190
- assert dlmlock.acquire!(host1_with_callbacks)
191
- assert_equal [], host1_with_callbacks.callbacks
192
- end
193
- end
194
-
195
- context 'scoped search' do
196
- test 'can be searched by name' do
197
- dlmlock = FactoryBot.create(:dlmlock)
198
- assert_equal Dlmlock::Update.find(dlmlock.id), Dlmlock.search_for("name ~ #{dlmlock.name}").first
199
- end
200
- end
201
- end