foreman_virt_who_configure 0.0.1

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 (46) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +619 -0
  3. data/README.md +35 -0
  4. data/Rakefile +47 -0
  5. data/app/assets/javascripts/foreman_virt_who_configure/config_edit.js +31 -0
  6. data/app/assets/stylesheets/foreman_virt_who_configure/config.css.scss +13 -0
  7. data/app/controllers/foreman_virt_who_configure/application_controller.rb +11 -0
  8. data/app/controllers/foreman_virt_who_configure/concerns/config_parameters.rb +22 -0
  9. data/app/controllers/foreman_virt_who_configure/configs_controller.rb +94 -0
  10. data/app/helpers/foreman_virt_who_configure/compatibility_helper.rb +22 -0
  11. data/app/helpers/foreman_virt_who_configure/configs_helper.rb +25 -0
  12. data/app/models/foreman_virt_who_configure/auth_source_hidden_with_authentication.rb +13 -0
  13. data/app/models/foreman_virt_who_configure/config.rb +157 -0
  14. data/app/models/foreman_virt_who_configure/output_generator.rb +152 -0
  15. data/app/models/foreman_virt_who_configure/service_user.rb +21 -0
  16. data/app/services/sso/basic_with_hidden.rb +11 -0
  17. data/app/views/dashboard/_foreman_virt_who_configure_widget.html.erb +2 -0
  18. data/app/views/foreman_virt_who_configure/configs/_form.html.erb +20 -0
  19. data/app/views/foreman_virt_who_configure/configs/edit.html.erb +3 -0
  20. data/app/views/foreman_virt_who_configure/configs/index.html.erb +27 -0
  21. data/app/views/foreman_virt_who_configure/configs/new.html.erb +3 -0
  22. data/app/views/foreman_virt_who_configure/configs/show.html.erb +24 -0
  23. data/app/views/foreman_virt_who_configure/configs/steps/_connection_form.erb +16 -0
  24. data/app/views/foreman_virt_who_configure/configs/steps/_general_information_form.erb +12 -0
  25. data/app/views/foreman_virt_who_configure/configs/steps/_schedule_form.erb +4 -0
  26. data/app/views/foreman_virt_who_configure/configs/welcome.html.erb +14 -0
  27. data/config/routes.rb +9 -0
  28. data/db/migrate/20170102152649_create_service_users.rb +12 -0
  29. data/db/migrate/20170102152650_create_configs.rb +22 -0
  30. data/db/migrate/20170102152751_add_lab_attrs_to_config.rb +9 -0
  31. data/db/migrate/20170102152851_add_satellite_url_to_config.rb +5 -0
  32. data/db/migrate/20170215152851_change_default_interval.rb +9 -0
  33. data/db/migrate/20170309161551_add_proxy_and_no_proxy_to_config.rb +11 -0
  34. data/lib/foreman_virt_who_configure/engine.rb +108 -0
  35. data/lib/foreman_virt_who_configure/version.rb +3 -0
  36. data/lib/foreman_virt_who_configure.rb +4 -0
  37. data/lib/tasks/foreman_virt_who_configure_tasks.rake +47 -0
  38. data/locale/Makefile +60 -0
  39. data/locale/en/foreman_virt_who_configure.po +19 -0
  40. data/locale/foreman_virt_who_configure.pot +19 -0
  41. data/locale/gemspec.rb +2 -0
  42. data/test/factories/foreman_virt_who_configure_factories.rb +13 -0
  43. data/test/test_plugin_helper.rb +6 -0
  44. data/test/unit/config_test.rb +65 -0
  45. data/test/unit/output_generator_test.rb +89 -0
  46. metadata +134 -0
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # ForemanVirtWhoConfigure
2
+
3
+ A foreman plugin to make virt-who configuration easier.
4
+
5
+ ## Installation
6
+
7
+ See [How_to_Install_a_Plugin](http://projects.theforeman.org/projects/foreman/wiki/How_to_Install_a_Plugin)
8
+ for how to install Foreman plugins
9
+
10
+ ## Usage
11
+
12
+ After installation you should see Virt-who configurations menu item in Infrastructure menu. Create a new configuration
13
+ and see the generated script for virt-who deployment.
14
+
15
+ ## Contributing
16
+
17
+ Fork and send a Pull Request. Thanks!
18
+
19
+ ## Copyright
20
+
21
+ Copyright (c) 2017 - Foreman team
22
+
23
+ This program is free software: you can redistribute it and/or modify
24
+ it under the terms of the GNU General Public License as published by
25
+ the Free Software Foundation, either version 3 of the License, or
26
+ (at your option) any later version.
27
+
28
+ This program is distributed in the hope that it will be useful,
29
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
30
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31
+ GNU General Public License for more details.
32
+
33
+ You should have received a copy of the GNU General Public License
34
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
35
+
data/Rakefile ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'ForemanVirtWhoConfigure'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
24
+
25
+ Bundler::GemHelper.install_tasks
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+ task default: :test
37
+
38
+ begin
39
+ require 'rubocop/rake_task'
40
+ RuboCop::RakeTask.new
41
+ rescue => _
42
+ puts 'Rubocop not loaded.'
43
+ end
44
+
45
+ task :default do
46
+ Rake::Task['rubocop'].execute
47
+ end
@@ -0,0 +1,31 @@
1
+ function virt_who_update_listing_mode() {
2
+ var filtering_mode = $('#foreman_virt_who_configure_config_listing_mode').val();
3
+ var whitelist = $('#foreman_virt_who_configure_config_whitelist').parents('div.form-group');
4
+ var blacklist = $('#foreman_virt_who_configure_config_blacklist').parents('div.form-group');
5
+
6
+ // UNLIMITED = 0, WHITELIST = 1, BLACKLIST = 2, see config.rb model for the definition
7
+ if (filtering_mode == '0') {
8
+ whitelist.hide();
9
+ blacklist.hide();
10
+ } else if (filtering_mode == '1') {
11
+ whitelist.show();
12
+ blacklist.hide();
13
+ } else if (filtering_mode == '2') {
14
+ whitelist.hide();
15
+ blacklist.show();
16
+ }
17
+ }
18
+
19
+ $(document).ready(function () {
20
+ $('#foreman_virt_who_configure_config_hypervisor_type').change(function () {
21
+ selected_type = $(this).val();
22
+ $.each(['hypervisor_server', 'hypervisor_username'], function(index, value) {
23
+ var element = $('#foreman_virt_who_configure_config_' + value)
24
+ var help = element.data("help")[selected_type];
25
+ element.parent().siblings('span.help-block.help-inline').children('a[rel=popover]').attr('data-content', help);
26
+ });
27
+ });
28
+
29
+ virt_who_update_listing_mode();
30
+ $('#foreman_virt_who_configure_config_listing_mode').change(virt_who_update_listing_mode);
31
+ });
@@ -0,0 +1,13 @@
1
+ pre.terminal {
2
+ display: block;
3
+ padding: 9.5px;
4
+ margin: 0 0 10px;
5
+ font-size: 12px;
6
+ word-break: break-all;
7
+ word-wrap: break-word;
8
+ color: rgba(255, 255, 255, 1);
9
+ background-color: rgba(47, 47, 47, 1);
10
+ border: 1px solid #000000;
11
+ border-radius: 0px;
12
+ font-family: Menlo, Monaco, Consolas, monospace;
13
+ }
@@ -0,0 +1,11 @@
1
+ module ForemanVirtWhoConfigure
2
+ class ApplicationController < ::ApplicationController
3
+ def resource_class
4
+ self.class.to_s.sub(/Controller$/, '').singularize.constantize
5
+ end
6
+
7
+ def resource_name
8
+ 'config'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,22 @@
1
+ module ForemanVirtWhoConfigure
2
+ module Concerns
3
+ module ConfigParameters
4
+ extend ActiveSupport::Concern
5
+
6
+ # 6.2 compatibility layer
7
+ if respond_to?(:class_methods)
8
+ class_methods do
9
+ def config_params_filter
10
+ Foreman::ParameterFilter.new(::ForemanVirtWhoConfigure::Config).tap do |filter|
11
+ filter.permit(*ForemanVirtWhoConfigure::Config::PERMITTED_PARAMS)
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ def config_params
18
+ self.class.config_params_filter.filter_params(params, parameter_filter_context, 'foreman_virt_who_configure_config')
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,94 @@
1
+ module ForemanVirtWhoConfigure
2
+ class ConfigsController < ::ForemanVirtWhoConfigure::ApplicationController
3
+ include Foreman::Controller::AutoCompleteSearch
4
+ include ForemanVirtWhoConfigure::Concerns::ConfigParameters if Foreman::Version.new.short >= '1.13'
5
+ before_action :find_resource, :only => [:edit, :update, :destroy, :show]
6
+
7
+ # in 1.11 we can't use welcome from application controller since it does not work with namespaces
8
+ def welcome
9
+ scope = apply_organization_filter(model_of_controller)
10
+ if scope.first.nil?
11
+ @welcome = true
12
+ render :action => :welcome
13
+ end
14
+ end
15
+
16
+ def index
17
+ if respond_to?(:resource_base_search_and_page)
18
+ @configs = resource_base_search_and_page
19
+ else
20
+ base = resource_base.search_for(params[:search], :order => params[:order])
21
+ @configs = base.paginate(:page => params[:page], :per_page => params[:per_page])
22
+ end
23
+ @configs = apply_organization_filter(@configs)
24
+ end
25
+
26
+ def new
27
+ @config = Config.new
28
+ if params.key?(:organization_id)
29
+ @config.organization = Organization.authorized(:view_organizations).where(:id => params[:organization_id]).first
30
+ end
31
+ @config.hypervisor_type ||= Config::HYPERVISOR_DEFAULT_TYPE
32
+ @config.organization ||= Organization.current
33
+ @config.satellite_url ||= URI.parse(Setting.foreman_url).host
34
+ end
35
+
36
+ def create
37
+ @config = Config.new(config_params)
38
+ if @config.save
39
+ process_success :success_redirect => foreman_virt_who_configure_config_path(@config)
40
+ else
41
+ render 'new'
42
+ end
43
+ end
44
+
45
+ def show
46
+ end
47
+
48
+ def edit
49
+ end
50
+
51
+ def update
52
+ if @config.update_attributes(config_params)
53
+ process_success :object => @config
54
+ else
55
+ process_error :object => @config
56
+ end
57
+ end
58
+
59
+ def destroy
60
+ if @config.destroy
61
+ process_success :object => @config
62
+ else
63
+ process_error :object => @config
64
+ end
65
+ end
66
+
67
+ def auto_complete_controller_name
68
+ 'foreman_virt_who_configure_configs'
69
+ end
70
+
71
+ def controller_name
72
+ 'foreman_virt_who_configure_configs'
73
+ end
74
+
75
+ # compatibility layer for 1.11 - pre strong params patch
76
+ def config_params
77
+ if defined?(super)
78
+ super
79
+ else
80
+ params[:foreman_virt_who_configure_config]
81
+ end
82
+ end
83
+
84
+ private
85
+
86
+ def apply_organization_filter(scope)
87
+ Organization.current ? scope.where(:organization_id => Organization.current) : scope
88
+ end
89
+
90
+ def resource_scope(*args)
91
+ apply_organization_filter(super)
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,22 @@
1
+ module ForemanVirtWhoConfigure
2
+ module CompatibilityHelper
3
+ extend ActiveSupport::Concern
4
+
5
+ def new_config_link(options = {}, html_options = {})
6
+ if ApplicationHelper.instance_methods.include?(:new_link)
7
+ new_link(_("Create Config"), options, html_options)
8
+ else
9
+ display_link_if_authorized(_("New Config"), hash_for_new_foreman_virt_who_configure_config_path, html_options)
10
+ end
11
+ end
12
+
13
+ def help_button_or_path
14
+ if ApplicationHelper.instance_methods.include?(:help_button)
15
+ # help_button does not support plugins
16
+ link_to(_("Help"), { :action => "welcome" }, { :class => 'btn btn-default' })
17
+ else
18
+ help_path
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ module ForemanVirtWhoConfigure
2
+ module ConfigsHelper
3
+ def hypervisor_server_help_data
4
+ {
5
+ 'esx' => _('VMware vCenter server’s fully qualified host name or IP address.'),
6
+ 'rhevm' => _('Red Hat Virtualization Manager’s fully qualified host name or IP address. For example, <code>https://hostname:443/ovirt-engine/</code> for v4, <code>https://hostname_or_IP:443</code> for v3'),
7
+ # 'vdsm' => 'Red Hat Enterprise Linux Hypervisor (vdsm)',
8
+ 'hyperv' => _('Microsoft Hyper-V fully qualified host name or IP address.'),
9
+ 'xen' => _('XenServer server’s fully qualified host name or IP address.'),
10
+ 'libvirt' => _('Libvirt server’s fully qualified host name or IP address. You can also specify preferred schema, for example: <code>qemu+ssh://libvirt.example.com/system</code>. If you use SSH, make sure you setup root\'s SSH key on target host for a user specified at hypervisor username field')
11
+ }
12
+ end
13
+
14
+ def hypervisor_username_help_data
15
+ {
16
+ 'esx' => _('Account name by which virt-who is to connect to the hypervisor, in the format <code>domain_name\account_name</code>. Note that only a single backslash separates the values for domain_name and account_name. If you are using a domain account, and the global configuration file <code>/etc/sysconfig/virt-who</code>, then <b>two</b> backslashes are required. For further details, see <a href="https://access.redhat.com/solutions/1270223">Red Hat Knowledgebase solution How to use a windows domain account with virt-who</a> for more information.'),
17
+ 'rhevm' => _('Account name by which virt-who is to connect to the Red Hat Enterprise Virtualization Manager instance. The username option requires input in the format username@domain.'),
18
+ # 'vdsm' => '',
19
+ 'hyperv' => _('Account name by which virt-who is to connect to the hypervisor. By default this is <code>Administrator</code>. To use an alternate account, create a user account and assign that account to the following groups (Windows 2012 Server): Hyper-V Administrators and Remote Management Users.'),
20
+ 'xen' => _('Account name by which virt-who is to connect to the hypervisor.'),
21
+ 'libvirt' => _('Account name by which virt-who is to connect to the hypervisor.')
22
+ }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ module ForemanVirtWhoConfigure
2
+ class AuthSourceHiddenWithAuthentication < ::AuthSourceHidden
3
+ def self.default
4
+ AuthSource.without_auditing do
5
+ where(:name => 'HiddenWithAuthentication').first_or_create!
6
+ end
7
+ end
8
+
9
+ def authenticate(login, password)
10
+ AuthSourceInternal.new.authenticate(login, password)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,157 @@
1
+ module ForemanVirtWhoConfigure
2
+ class Config < ActiveRecord::Base
3
+ PERMITTED_PARAMS = [
4
+ :interval, :organization_id, :compute_resource_id, :whitelist, :blacklist, :listing_mode, :hypervisor_id,
5
+ :hypervisor_type, :hypervisor_server, :hypervisor_username, :hypervisor_password, :debug,
6
+ :satellite_url, :proxy, :no_proxy
7
+ ]
8
+ include Authorizable
9
+ audited
10
+ validates_lengths_from_database
11
+
12
+ UNLIMITED = 0
13
+ WHITELIST = 1
14
+ BLACKLIST = 2
15
+ FILTERING_MODES = {
16
+ UNLIMITED.to_s => _('Unlimited'),
17
+ WHITELIST.to_s => _('Whitelist'),
18
+ BLACKLIST.to_s => _('Blacklist'),
19
+ }
20
+
21
+ WIZARD_STEPS = {
22
+ 'general_information' => _('General information'),
23
+ 'schedule' => _('Schedule'),
24
+ 'connection' => _('Connection')
25
+ }
26
+
27
+ HYPERVISOR_IDS = [ 'hostname', 'uuid', 'hwuuid' ]
28
+
29
+ HYPERVISOR_TYPES = {
30
+ 'esx' => 'VMware vSphere / vCenter (esx)',
31
+ 'rhevm' => 'Red Hat Virtualization Hypervisor (rhevm)',
32
+ # 'vdsm' => 'Red Hat Enterprise Linux Hypervisor (vdsm)',
33
+ 'hyperv' => 'Microsoft Hyper-V (hyperv)',
34
+ 'xen' => 'XenServer (xen)',
35
+ 'libvirt' => 'libvirt'
36
+ }
37
+
38
+ HYPERVISOR_DEFAULT_TYPE = 'esx'
39
+
40
+ AVAILABLE_INTERVALS = {
41
+ '60' => _('Every hour'),
42
+ '120' => _('Every 2 hours'),
43
+ '240' => _('Every 4 hours'),
44
+ '480' => _('Every 8 hours'),
45
+ '720' => _('Every 12 hours'),
46
+ }
47
+
48
+ DEFAULT_INTERVAL = 120
49
+
50
+ include Encryptable
51
+ encrypts :hypervisor_password
52
+
53
+ belongs_to :compute_resource
54
+ belongs_to :organization
55
+
56
+ # service user used by virt-who to report back
57
+ belongs_to :service_user
58
+
59
+ scoped_search :on => :interval, :complete_value => true
60
+ # TODO add more related objects and attributes
61
+
62
+ # compatibility layer for 1.11 - pre strong params patch
63
+ if self.respond_to?(:attr_accessible)
64
+ attr_accessible(*PERMITTED_PARAMS)
65
+ end
66
+
67
+ after_create :create_service_user
68
+ after_destroy :destroy_service_user
69
+
70
+ validates :interval, :hypervisor_type, :hypervisor_server, :hypervisor_username, :hypervisor_password,
71
+ :satellite_url, :hypervisor_id, :organization_id,
72
+ :presence => true
73
+ validates :hypervisor_type, :inclusion => HYPERVISOR_TYPES.keys
74
+ validates :hypervisor_id, :inclusion => HYPERVISOR_IDS
75
+ validates :interval, :inclusion => AVAILABLE_INTERVALS.keys.map(&:to_i)
76
+ validates :listing_mode, :inclusion => FILTERING_MODES.keys.map(&:to_i)
77
+ validates :whitelist, :presence => true, :if => Proc.new { |c| c.listing_mode.to_i == WHITELIST }
78
+ validates :blacklist, :presence => true, :if => Proc.new { |c| c.listing_mode.to_i == BLACKLIST }
79
+ validates_lengths_from_database
80
+
81
+ before_validation :remove_whitespaces
82
+
83
+ def create_service_user
84
+ password = User.random_password
85
+ service_user = self.build_service_user
86
+ user = service_user.build_user
87
+ user.auth_source = AuthSourceHiddenWithAuthentication.default
88
+ user.password = password
89
+ user.login = "virt_who_reporter_#{self.id}"
90
+ user.organizations = [ self.organization ]
91
+ user.roles = [ Role.where(:name => 'Virt-who Reporter').first ]
92
+ user.valid? # to trigger password hashing
93
+ user.save!(:validate => false)
94
+
95
+ service_user.encrypted_password = password
96
+ service_user.save!
97
+
98
+ self.update_attribute :service_user_id, service_user.id
99
+ end
100
+
101
+ def destroy_service_user
102
+ # skip validation that prevents hidden user deletion
103
+ user = service_user.user
104
+ service_user.destroy
105
+ user.delete
106
+ end
107
+
108
+ # mapping of supported CR types
109
+ # case config.compute_resource
110
+ # when Foreman::Model::Libvirt
111
+ # 'libvirt'
112
+ # when Foreman::Model::Vmware
113
+ # 'esx'
114
+ # when Foreman::Model::Ovirt
115
+ # 'rhevm'
116
+ # else
117
+ # raise 'unsupported compute resource type'
118
+ # end
119
+
120
+ # Foreman 1.11 specifics, can be removed later, otherwise when string does not start with "encrypts" prefix
121
+ # we get 500 when we try to create log message that relies on name method
122
+ def name
123
+ title
124
+ end
125
+
126
+ def title
127
+ compute_resource ? compute_resource.name : hypervisor_server
128
+ end
129
+
130
+ def humanized_interval
131
+ _("every %s hours") % (self.interval / 60)
132
+ end
133
+
134
+ def step_name(step_key)
135
+ WIZARD_STEPS[step_key]
136
+ end
137
+
138
+ def steps
139
+ WIZARD_STEPS.keys
140
+ end
141
+
142
+ def virt_who_config_file
143
+ generator = OutputGenerator.new(self)
144
+ if generator.ready_for_virt_who_output?
145
+ generator.virt_who_output
146
+ else
147
+ generator.missing_virt_who_input_messages.join("\n")
148
+ end
149
+ end
150
+
151
+ private
152
+
153
+ def remove_whitespaces
154
+ satellite_url.strip! if satellite_url.present?
155
+ end
156
+ end
157
+ end