foreman_monitoring 0.1.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +16 -7
- data/Rakefile +0 -0
- data/app/controllers/api/v2/downtime_controller.rb +63 -0
- data/app/controllers/api/v2/monitoring_results_controller.rb +5 -4
- data/app/controllers/concerns/foreman_monitoring/find_host_by_client_cert.rb +60 -0
- data/app/controllers/concerns/foreman_monitoring/hosts_controller_extensions.rb +21 -20
- data/app/helpers/concerns/foreman_monitoring/hosts_helper_ext.rb +16 -19
- data/app/lib/proxy_api/monitoring.rb +9 -6
- data/app/models/concerns/foreman_monitoring/host_extensions.rb +15 -14
- data/app/models/concerns/foreman_monitoring/hostgroup_extensions.rb +7 -3
- data/app/models/concerns/orchestration/monitoring.rb +22 -15
- data/app/models/host_status/monitoring_status.rb +7 -4
- data/app/models/monitoring_result.rb +13 -6
- data/app/models/setting/monitoring.rb +4 -2
- data/app/overrides/add_host_monitoring_result_tab.rb +8 -6
- data/app/overrides/add_host_multiple_power_set_downtime_checkbox.rb +5 -3
- data/app/overrides/add_host_set_downtime_modal.rb +4 -2
- data/app/services/monitoring.rb +3 -0
- data/app/views/hosts/_downtime_fields.html.erb +2 -2
- data/app/views/monitoring_results/_host_tab_pane.html.erb +2 -2
- data/config/routes.rb +3 -0
- data/db/migrate/20160817135723_create_monitoring_results.rb +5 -1
- data/db/migrate/20161220201510_add_monitoring_proxy_id_to_host_and_hostgroup.rb +3 -1
- data/db/migrate/201910180900_rename_downtime_host_permission.rb +15 -0
- data/db/seeds.d/60-monitoring_proxy_feature.rb +2 -0
- data/lib/foreman_monitoring.rb +2 -0
- data/lib/foreman_monitoring/engine.rb +32 -28
- data/lib/foreman_monitoring/version.rb +3 -1
- data/lib/tasks/foreman_monitoring_tasks.rake +5 -5
- data/locale/gemspec.rb +2 -0
- data/test/controllers/api/v2/downtime_controller_test.rb +73 -0
- data/test/factories/feature.rb +4 -2
- data/test/factories/host.rb +6 -4
- data/test/factories/monitoring_results.rb +9 -7
- data/test/factories/smart_proxy.rb +3 -1
- data/test/functional/hosts_controller_test.rb +65 -52
- data/test/lib/proxy_api/monitoring_test.rb +16 -14
- data/test/test_plugin_helper.rb +5 -3
- data/test/unit/host_status/monitoring_status_test.rb +18 -16
- data/test/unit/host_test.rb +6 -4
- data/test/unit/monitoring_result_test.rb +75 -0
- data/test/unit/monitoring_test.rb +5 -3
- metadata +62 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6bc195afe4c0af30313894eaf37dcf99c36625fe510998783df94932111c9891
|
4
|
+
data.tar.gz: 8d37c47d99c8d48163242ce490159c59a6a4e6c2588709daac0bac841a450c5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf715511ef2835a64702b2f865c6380c178dd8c70b2038428ea3a0c9a72fefcef4715ec4c2bcca82fbf687c9ea5a463c5e041009fe7e795cb6aab6484020d6f3
|
7
|
+
data.tar.gz: 8c4c4cbaad0dffa2f7d338d19e116cc58c05272b262d36d5bf221137391577a414dcd3ba83c34d78c46207bf8298675529a988d42fd736961751687325b615b1
|
data/README.md
CHANGED
@@ -17,7 +17,7 @@ The gem name is `foreman_monitoring`.
|
|
17
17
|
|
18
18
|
RPM users can install the `tfm-rubygem-foreman_monitoring` package.
|
19
19
|
|
20
|
-
Deb users can install the `ruby-
|
20
|
+
Deb users can install the `ruby-foreman-monitoring` package.
|
21
21
|
|
22
22
|
If using the gem as installation source database enhancement and service restart must
|
23
23
|
be done manually.
|
@@ -28,6 +28,15 @@ foreman-rake db:seed
|
|
28
28
|
touch ~foreman/tmp/restart.txt
|
29
29
|
```
|
30
30
|
|
31
|
+
## Compatibility
|
32
|
+
|
33
|
+
| Foreman Version | Plugin Version |
|
34
|
+
| --------------- | --------------:|
|
35
|
+
| >= 1.15 | ~> 0.1 |
|
36
|
+
| >= 1.17 | ~> 1.0 |
|
37
|
+
| >= 2.0 | ~> 2.0 |
|
38
|
+
| >= 2.2 | ~> 2.1 |
|
39
|
+
|
31
40
|
# Usage
|
32
41
|
|
33
42
|
For managing a host in the monitoring solution a Smart Proxy providing
|
@@ -35,15 +44,15 @@ the `monitoring` feature has to be assigned. This can be done during
|
|
35
44
|
provisioning or as a bulk action from the host overview.
|
36
45
|
|
37
46
|
You can configure the default action which will be done during host
|
38
|
-
provisioning and
|
39
|
-
object or take no action while
|
40
|
-
object, set a downtime or take no action. For rebuild it will by default
|
47
|
+
provisioning and de-provisioning. Provisioning allows to create a monitoring
|
48
|
+
object or take no action while de-provisoning allows deleting the monitoring
|
49
|
+
object, set a downtime or take no action. For rebuild, it will by default
|
41
50
|
set a downtime.
|
42
51
|
|
43
52
|
The plugin will show you the monitoring status as a sub-status and a detail
|
44
53
|
panel. You can configure if the sub-status should affect the global status.
|
45
54
|
|
46
|
-
Furthermore it allows to individually set a downtime at the host detail view
|
55
|
+
Furthermore, it allows to individually set a downtime at the host detail view
|
47
56
|
or as a bulk action from the host overview.
|
48
57
|
|
49
58
|
# Troubleshooting
|
@@ -51,8 +60,8 @@ or as a bulk action from the host overview.
|
|
51
60
|
Logging entries relevant to the plug-in will be located in the Foreman's log
|
52
61
|
which is by default `/var/log/foreman/production.log`.
|
53
62
|
|
54
|
-
Also check the troubleshooting section of the Smart Proxy plug-in if problems
|
55
|
-
|
63
|
+
Also, check the troubleshooting section of the Smart Proxy plug-in if problems
|
64
|
+
occur in the underlying communication.
|
56
65
|
|
57
66
|
## Contributing
|
58
67
|
|
data/Rakefile
CHANGED
File without changes
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Api
|
4
|
+
module V2
|
5
|
+
class DowntimeController < V2::BaseController
|
6
|
+
include Api::Version2
|
7
|
+
include ::ForemanMonitoring::FindHostByClientCert
|
8
|
+
|
9
|
+
authorize_host_by_client_cert %i[create]
|
10
|
+
before_action :find_host, :only => [:create]
|
11
|
+
|
12
|
+
api :POST, '/downtime', N_('Schedule host downtime')
|
13
|
+
param :duration, :number, :desc => N_('Downtime duration (seconds)'), :required => false
|
14
|
+
param :reason, String, :desc => N_('Downtime reason'), :required => false
|
15
|
+
|
16
|
+
def create
|
17
|
+
begin
|
18
|
+
options = {
|
19
|
+
:comment => downtime_params[:reason] || _('Host requested downtime')
|
20
|
+
}
|
21
|
+
if downtime_params.key? :duration
|
22
|
+
options[:start_time] = Time.now.to_i
|
23
|
+
options[:end_time] = Time.now.to_i + downtime_params[:duration].to_i
|
24
|
+
end
|
25
|
+
@host.downtime_host(options)
|
26
|
+
rescue StandardError => e
|
27
|
+
Foreman::Logging.exception('Failed to request downtime', e)
|
28
|
+
render :json => { 'message' => e.message }, :status => :unprocessable_entity
|
29
|
+
return
|
30
|
+
end
|
31
|
+
|
32
|
+
render :json => { 'message' => 'OK' }
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def downtime_params
|
38
|
+
params.permit(:duration, :reason)
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_host
|
42
|
+
@host = detected_host
|
43
|
+
|
44
|
+
return true if @host
|
45
|
+
|
46
|
+
logger.info 'Denying access because no host could be detected.'
|
47
|
+
if User.current
|
48
|
+
render_error 'access_denied',
|
49
|
+
:status => :forbidden,
|
50
|
+
:locals => {
|
51
|
+
:details => 'You need to authenticate with a valid client cert. The DN has to match a known host.'
|
52
|
+
}
|
53
|
+
else
|
54
|
+
render_error 'unauthorized',
|
55
|
+
:status => :unauthorized,
|
56
|
+
:locals => {
|
57
|
+
:user_login => get_client_cert_hostname
|
58
|
+
}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Api
|
2
4
|
module V2
|
3
5
|
class MonitoringResultsController < V2::BaseController
|
@@ -17,10 +19,9 @@ module Api
|
|
17
19
|
|
18
20
|
def create
|
19
21
|
begin
|
20
|
-
MonitoringResult.import(monitoring_result_params.with_indifferent_access)
|
21
|
-
rescue => e
|
22
|
-
|
23
|
-
logger.debug e.backtrace.join("\n")
|
22
|
+
MonitoringResult.import(monitoring_result_params.to_h.with_indifferent_access)
|
23
|
+
rescue StandardError => e
|
24
|
+
Foreman::Logging.exception('Failed to import monitoring result', e)
|
24
25
|
render :json => { 'message' => e.message }, :status => :unprocessable_entity
|
25
26
|
return
|
26
27
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanMonitoring
|
4
|
+
module FindHostByClientCert
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def authorize_host_by_client_cert(actions, _options = {})
|
9
|
+
skip_before_action :require_login, :only => actions, :raise => false
|
10
|
+
skip_before_action :check_user_enabled, :only => actions, :raise => false
|
11
|
+
skip_before_action :authorize, :only => actions
|
12
|
+
skip_before_action :verify_authenticity_token, :only => actions
|
13
|
+
skip_before_action :set_taxonomy, :only => actions, :raise => false
|
14
|
+
skip_before_action :session_expiry, :update_activity_time, :only => actions
|
15
|
+
before_action(:only => actions) { require_client_cert_or_login }
|
16
|
+
attr_reader :detected_host
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# Permits Hosts authorized by their client cert
|
23
|
+
# or a user with permission
|
24
|
+
def require_client_cert_or_login
|
25
|
+
@detected_host = find_host_by_client_cert
|
26
|
+
|
27
|
+
if detected_host
|
28
|
+
set_admin_user
|
29
|
+
return true
|
30
|
+
end
|
31
|
+
|
32
|
+
require_login
|
33
|
+
unless User.current
|
34
|
+
render_error 'unauthorized', :status => :unauthorized unless performed? && api_request?
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
authorize
|
38
|
+
end
|
39
|
+
|
40
|
+
def find_host_by_client_cert
|
41
|
+
hostname = get_client_cert_hostname
|
42
|
+
|
43
|
+
return unless hostname
|
44
|
+
|
45
|
+
host ||= Host::Base.find_by(certname: hostname) ||
|
46
|
+
Host::Base.find_by(name: hostname)
|
47
|
+
logger.info { "Found Host #{host} by client cert #{hostname}" } if host
|
48
|
+
host
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_client_cert_hostname
|
52
|
+
client_certificate = Foreman::ClientCertificate.new(request: request)
|
53
|
+
return unless client_certificate.verified?
|
54
|
+
|
55
|
+
hostname = client_certificate.subject
|
56
|
+
logger.debug "Extracted hostname '#{hostname}' from client certificate." if hostname
|
57
|
+
hostname
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,18 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ForemanMonitoring
|
2
4
|
module HostsControllerExtensions
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
alias_method_chain :update_multiple_power_state, :monitoring
|
5
|
+
def self.prepended(base)
|
6
|
+
base.class_eval do
|
7
|
+
before_action :find_resource_with_monitoring, :only => [:downtime]
|
8
|
+
before_action :find_multiple_with_monitoring, :only => %i[select_multiple_downtime update_multiple_downtime
|
9
|
+
select_multiple_monitoring_proxy update_multiple_monitoring_proxy]
|
10
|
+
before_action :validate_host_downtime_params, :only => [:downtime]
|
11
|
+
before_action :validate_hosts_downtime_params, :only => [:update_multiple_downtime]
|
12
|
+
before_action :validate_multiple_monitoring_proxy, :only => :update_multiple_monitoring_proxy
|
13
|
+
|
14
|
+
alias_method :find_resource_with_monitoring, :find_resource
|
15
|
+
alias_method :find_multiple_with_monitoring, :find_multiple
|
16
|
+
end
|
16
17
|
end
|
17
18
|
|
18
19
|
def downtime
|
@@ -39,14 +40,14 @@ module ForemanMonitoring
|
|
39
40
|
failed_hosts[host.name] = error_message
|
40
41
|
logger.error "Failed to set a host downtime for #{host}: #{error_message}"
|
41
42
|
end
|
42
|
-
rescue =>
|
43
|
-
failed_hosts[host.name] =
|
44
|
-
Foreman::Logging.exception(_('Failed to set a host downtime for %s.') % host,
|
43
|
+
rescue StandardError => e
|
44
|
+
failed_hosts[host.name] = e
|
45
|
+
Foreman::Logging.exception(_('Failed to set a host downtime for %s.') % host, e)
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
48
49
|
if failed_hosts.empty?
|
49
|
-
|
50
|
+
success _('A downtime was set for the selected hosts.')
|
50
51
|
else
|
51
52
|
error n_('A downtime clould not be set for host: %s.',
|
52
53
|
'A downtime could not be set for hosts: %s.',
|
@@ -65,7 +66,7 @@ module ForemanMonitoring
|
|
65
66
|
update_multiple_proxy(_('Monitoring'), :monitoring_proxy=)
|
66
67
|
end
|
67
68
|
|
68
|
-
def
|
69
|
+
def update_multiple_power_state
|
69
70
|
options = {
|
70
71
|
:comment => 'Power state changed in Foreman',
|
71
72
|
:author => "Foreman User #{User.current}",
|
@@ -86,7 +87,7 @@ module ForemanMonitoring
|
|
86
87
|
end
|
87
88
|
end
|
88
89
|
end
|
89
|
-
|
90
|
+
super
|
90
91
|
end
|
91
92
|
|
92
93
|
private
|
@@ -129,7 +130,7 @@ module ForemanMonitoring
|
|
129
130
|
def action_permission
|
130
131
|
case params[:action]
|
131
132
|
when 'downtime', 'select_multiple_downtime', 'update_multiple_downtime'
|
132
|
-
:
|
133
|
+
:manage_downtime
|
133
134
|
when 'select_multiple_monitoring_proxy', 'update_multiple_monitoring_proxy'
|
134
135
|
:edit
|
135
136
|
else
|
@@ -1,33 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ForemanMonitoring
|
2
4
|
module HostsHelperExt
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
9
|
-
|
10
|
-
def multiple_actions_with_monitoring
|
11
|
-
return multiple_actions_without_monitoring unless authorized_for(:controller => :hosts, :action => :select_multiple_downtime)
|
12
|
-
multiple_actions_without_monitoring + [[_('Set downtime'), select_multiple_downtime_hosts_path], [_('Change Monitoring Proxy'), select_multiple_monitoring_proxy_hosts_path]]
|
5
|
+
def multiple_actions
|
6
|
+
actions = super
|
7
|
+
actions << [_('Set downtime'), select_multiple_downtime_hosts_path] if authorized_for(:controller => :hosts, :action => :select_multiple_downtime)
|
8
|
+
actions << [_('Change Monitoring Proxy'), select_multiple_monitoring_proxy_hosts_path] if authorized_for(:controller => :hosts, :action => :select_multiple_monitoring_proxy)
|
9
|
+
actions
|
13
10
|
end
|
14
11
|
|
15
|
-
def
|
12
|
+
def host_title_actions(host)
|
16
13
|
title_actions(
|
17
14
|
button_group(
|
18
15
|
display_link_if_authorized(_('Downtime'),
|
19
16
|
hash_for_host_path(:id => host).merge(:auth_object => host,
|
20
|
-
:permission => :
|
17
|
+
:permission => :manage_downtime_hosts,
|
21
18
|
:anchor => 'set_host_downtime'),
|
22
19
|
:class => 'btn btn-default',
|
23
20
|
:disabled => !host.monitored?,
|
24
|
-
:title
|
25
|
-
:id
|
26
|
-
:data
|
27
|
-
|
21
|
+
:title => _('Set a downtime for this host'),
|
22
|
+
:id => 'host-downtime',
|
23
|
+
:data => { :toggle => 'modal',
|
24
|
+
:target => '#set_host_downtime' })
|
28
25
|
)
|
29
26
|
)
|
30
|
-
|
27
|
+
super
|
31
28
|
end
|
32
29
|
|
33
30
|
def host_monitoring_result_icon_class(result)
|
@@ -58,10 +55,10 @@ module ForemanMonitoring
|
|
58
55
|
end
|
59
56
|
end
|
60
57
|
|
61
|
-
def
|
58
|
+
def monitoring_datetime_f(f, attr, options = {})
|
62
59
|
field(f, attr, options) do
|
63
60
|
addClass options, 'form-control'
|
64
|
-
f.
|
61
|
+
f.datetime_field attr, options
|
65
62
|
end
|
66
63
|
end
|
67
64
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ProxyAPI
|
2
4
|
class Monitoring < ProxyAPI::Resource
|
3
5
|
def initialize(args)
|
@@ -7,34 +9,35 @@ module ProxyAPI
|
|
7
9
|
|
8
10
|
def create_host_downtime(host, args = {})
|
9
11
|
parse(post(args, "downtime/host/#{host}"))
|
10
|
-
rescue => e
|
12
|
+
rescue StandardError => e
|
11
13
|
raise ProxyException.new(url, e, N_('Unable to set downtime for %s') % host)
|
12
14
|
end
|
13
15
|
|
14
16
|
def remove_host_downtime(host, args = {})
|
15
17
|
parse(delete("downtime/host/#{host}?#{args.to_query}"))
|
16
|
-
rescue => e
|
18
|
+
rescue StandardError => e
|
17
19
|
raise ProxyException.new(url, e, N_('Unable to remove downtime for %s') % host)
|
18
20
|
end
|
19
21
|
|
20
22
|
def create_host(host, attributes = {})
|
21
23
|
parse(put({ :attributes => attributes }, "host/#{host}"))
|
22
|
-
rescue => e
|
24
|
+
rescue StandardError => e
|
23
25
|
raise ProxyException.new(url, e, N_('Unable to create monitoring host object for %s') % host)
|
24
26
|
end
|
25
27
|
|
26
28
|
def update_host(host, attributes = {})
|
27
29
|
parse(post({ :attributes => attributes }, "host/#{host}"))
|
28
|
-
rescue => e
|
30
|
+
rescue StandardError => e
|
29
31
|
raise ProxyException.new(url, e, N_('Unable to update monitoring host object for %s') % host)
|
30
32
|
end
|
31
33
|
|
32
34
|
def delete_host(host)
|
33
35
|
raise Foreman::Exception, 'Missing hostname.' if host.blank?
|
36
|
+
|
34
37
|
parse(delete("host/#{host}"))
|
35
38
|
rescue RestClient::ResourceNotFound
|
36
39
|
true
|
37
|
-
rescue => e
|
40
|
+
rescue StandardError => e
|
38
41
|
raise ProxyException.new(url, e, N_('Unable to delete monitoring host object for %s') % host)
|
39
42
|
end
|
40
43
|
|
@@ -42,7 +45,7 @@ module ProxyAPI
|
|
42
45
|
parse(get("host/#{host}"))
|
43
46
|
rescue RestClient::ResourceNotFound
|
44
47
|
nil
|
45
|
-
rescue => e
|
48
|
+
rescue StandardError => e
|
46
49
|
raise ProxyException.new(url, e, N_('Unable to query monitoring host object for %{host}: %{message}') % { :host => host, :message => e.try(:response) || e.try(:message) })
|
47
50
|
end
|
48
51
|
end
|
@@ -1,15 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ForemanMonitoring
|
2
4
|
module HostExtensions
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
after_build :downtime_host_build
|
5
|
+
def self.prepended(base)
|
6
|
+
base.class_eval do
|
7
|
+
include Orchestration::Monitoring
|
8
8
|
|
9
|
-
|
10
|
-
alias_method_chain :hostgroup_inherited_attributes, :monitoring
|
9
|
+
after_build :downtime_host_build
|
11
10
|
|
12
|
-
|
11
|
+
has_many :monitoring_results, :dependent => :destroy, :foreign_key => 'host_id', :inverse_of => :host
|
12
|
+
end
|
13
13
|
end
|
14
14
|
|
15
15
|
def monitoring_status(options = {})
|
@@ -30,6 +30,7 @@ module ForemanMonitoring
|
|
30
30
|
|
31
31
|
def downtime_host(options)
|
32
32
|
return unless monitored?
|
33
|
+
|
33
34
|
begin
|
34
35
|
monitoring.set_downtime_host(self, options)
|
35
36
|
rescue ProxyAPI::ProxyException => e
|
@@ -42,12 +43,12 @@ module ForemanMonitoring
|
|
42
43
|
monitoring_proxy.present?
|
43
44
|
end
|
44
45
|
|
45
|
-
def
|
46
|
-
|
46
|
+
def hostgroup_inherited_attributes
|
47
|
+
super + ['monitoring_proxy_id']
|
47
48
|
end
|
48
49
|
|
49
|
-
def
|
50
|
-
ids =
|
50
|
+
def smart_proxy_ids
|
51
|
+
ids = super
|
51
52
|
[monitoring_proxy, hostgroup.try(:monitoring_proxy)].compact.each do |proxy|
|
52
53
|
ids << proxy.id
|
53
54
|
end
|
@@ -61,12 +62,12 @@ module ForemanMonitoring
|
|
61
62
|
:architecture => architecture.try(:name),
|
62
63
|
:os => operatingsystem.try(:to_label),
|
63
64
|
:osfamily => operatingsystem.try(:family),
|
64
|
-
:virtual => provider != 'BareMetal',
|
65
|
+
:virtual => virtual.presence || provider != 'BareMetal',
|
65
66
|
:provider => provider,
|
66
67
|
:compute_resource => compute_resource.try(:to_label),
|
67
68
|
:hostgroup => hostgroup.try(:to_label),
|
68
69
|
:organization => organization.try(:name),
|
69
|
-
:location =>
|
70
|
+
:location => location.try(:name),
|
70
71
|
:comment => comment,
|
71
72
|
:environment => environment.try(:to_s),
|
72
73
|
:owner_name => owner.try(:name)
|