foreman_virt_who_configure 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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