foreman_dlm 0.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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