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
@@ -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,2 @@
1
+ collection @events
2
+ attributes :id, :event_type, :created_at, :updated_at
@@ -3,6 +3,6 @@ object @dlmlock
3
3
  extends 'api/v2/dlmlocks/main'
4
4
 
5
5
  child :host do
6
- node(:name) { |host| host.name }
6
+ node(:name, &:name)
7
7
  node(:self) { |host| host == @detected_host } if @detected_host
8
8
  end
@@ -1,4 +1,4 @@
1
- object resource = controller.get_resource
1
+ object controller.get_resource
2
2
 
3
3
  attributes :id
4
4
 
@@ -0,0 +1 @@
1
+ attributes :id, :last_checkin_at
@@ -0,0 +1,3 @@
1
+ child :dlm_facet => :dlm_facet_attributes do |_dlm_facet|
2
+ extends 'foreman_dlm/api/v2/dlm_facets/base'
3
+ end
@@ -0,0 +1,3 @@
1
+ child :dlm_facet => :dlm_facet_attributes do
2
+ extends 'foreman_dlm/api/v2/dlm_facets/base'
3
+ end
@@ -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, hash_for_dlmlock_path(:id => lock)),
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,2 @@
1
+ <% title _('Distributed Locks') %>
2
+ <%= render :partial => 'list' %>
@@ -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/timogoebel/foreman_dlm', :rel => "external" %>.
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/timogoebel/foreman_dlm', :rel => 'external', :class => 'btn btn-primary btn-lg' %>
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
- :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
- get :lock, on: :member, action: :show, controller: 'dlmlocks'
10
- put :lock, on: :member, action: :acquire, controller: 'dlmlocks'
11
- delete :lock, on: :member, action: :release, controller: 'dlmlocks'
12
- end
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
- scope '/foreman_dlm' do
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 'auto_complete_search'
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,8 @@
1
+ [Unit]
2
+ Description=Run foreman-dlm-expire-events.service nightly
3
+
4
+ [Timer]
5
+ OnCalendar=*-*-* 02:00:00
6
+
7
+ [Install]
8
+ WantedBy=timers.target
@@ -1,4 +1,4 @@
1
- class AddDlmlock < ActiveRecord::Migration
1
+ class AddDlmlock < ActiveRecord::Migration[4.2]
2
2
  def change
3
3
  create_table :dlmlocks do |t|
4
4
  t.string :name, null: false, unique: true
@@ -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,5 @@
1
+ class AddHostsFkToDlmlocks < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_foreign_key :dlmlocks, :hosts
4
+ end
5
+ 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
@@ -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 '>= 1.15'
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, :create_dlmlocks, :edit_dlmlocks, :destroy_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, :distributed_locks,
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
- begin
56
- Host::Managed.send(:include, ForemanDlm::HostExtensions)
93
+ Host::Managed.include ForemanDlm::HostExtensions
94
+ User.include ForemanDlm::UserExtensions
95
+ Host::Managed.include ForemanDlm::DlmFacetHostExtensions
57
96
 
58
- if ForemanDlm.with_monitoring?
59
- Host::Managed.send(:include, ForemanDlm::HostMonitoringExtensions)
60
- end
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('../../..', __FILE__), 'locale')
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
- (ForemanMonitoring rescue false) ? true : false
110
+ ForemanMonitoring # rubocop:disable Lint/Void
111
+ true
112
+ rescue StandardError
113
+ false
75
114
  end
76
115
  end
@@ -1,3 +1,3 @@
1
1
  module ForemanDlm
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '2.0.0'.freeze
3
3
  end
@@ -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