foreman_netbox 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +619 -0
- data/README.md +50 -0
- data/Rakefile +50 -0
- data/app/contracts/foreman_netbox/device_contract.rb +42 -0
- data/app/contracts/foreman_netbox/params/interface_params.rb +16 -0
- data/app/contracts/foreman_netbox/params/ip_address_params.rb +15 -0
- data/app/contracts/foreman_netbox/params/tenant_params.rb +13 -0
- data/app/contracts/foreman_netbox/virtual_machine_contract.rb +29 -0
- data/app/interactors/foreman_netbox/concerns/facts.rb +11 -0
- data/app/interactors/foreman_netbox/concerns/primary_ips.rb +25 -0
- data/app/interactors/foreman_netbox/delete_host/delete_device.rb +20 -0
- data/app/interactors/foreman_netbox/delete_host/delete_virtual_machine.rb +20 -0
- data/app/interactors/foreman_netbox/delete_host/organizer.rb +12 -0
- data/app/interactors/foreman_netbox/sync_host/organizer.rb +35 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/create.rb +36 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/find.rb +41 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/organizer.rb +30 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/save_netbox_url.rb +29 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_role/create.rb +32 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_role/find.rb +28 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_role/organizer.rb +20 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/create.rb +34 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/find.rb +28 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/organizer.rb +22 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/sync_manufacturer/create.rb +34 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/sync_manufacturer/find.rb +40 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/sync_manufacturer/organizer.rb +22 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/update.rb +33 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/create.rb +37 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/delete.rb +36 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/find.rb +30 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/organizer.rb +23 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/create.rb +46 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/delete.rb +40 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/find.rb +32 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/organizer.rb +24 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/update.rb +39 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/update.rb +38 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_site/create.rb +32 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_site/find.rb +28 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_site/organizer.rb +25 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_site/update.rb +35 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/update.rb +85 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/validate.rb +25 -0
- data/app/interactors/foreman_netbox/sync_host/sync_tenant/create.rb +30 -0
- data/app/interactors/foreman_netbox/sync_host/sync_tenant/find.rb +26 -0
- data/app/interactors/foreman_netbox/sync_host/sync_tenant/organizer.rb +19 -0
- data/app/interactors/foreman_netbox/sync_host/sync_tenant/update.rb +33 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/create.rb +34 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/find.rb +34 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/organizer.rb +28 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/save_netbox_url.rb +31 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/create.rb +35 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/find.rb +28 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/organizer.rb +22 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/sync_cluster_type/create.rb +34 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/sync_cluster_type/find.rb +32 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/sync_cluster_type/organizer.rb +22 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/update.rb +35 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/create.rb +33 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/delete.rb +36 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/find.rb +30 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/organizer.rb +23 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/create.rb +46 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/delete.rb +40 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/find.rb +28 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/organizer.rb +24 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/update.rb +39 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/update.rb +38 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/update.rb +82 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/validate.rb +25 -0
- data/app/jobs/foreman_netbox/sync_host_job.rb +19 -0
- data/app/lib/foreman_netbox/api.rb +12 -0
- data/app/models/concerns/foreman_netbox/host_extensions.rb +27 -0
- data/app/models/concerns/foreman_netbox/location_extensions.rb +13 -0
- data/app/models/concerns/foreman_netbox/nic/base_extensions.rb +23 -0
- data/app/models/concerns/foreman_netbox/user_usergroup_common_extensions.rb +18 -0
- data/app/models/foreman_netbox/netbox_facet.rb +34 -0
- data/app/models/orchestration/netbox.rb +64 -0
- data/app/models/setting/netbox.rb +32 -0
- data/app/services/foreman_netbox/cached_netbox_parameters.rb +103 -0
- data/app/services/foreman_netbox/netbox_parameters.rb +185 -0
- data/app/services/foreman_netbox/netbox_parameters_comparator.rb +96 -0
- data/app/views/hosts/_netbox_tab.html.erb +28 -0
- data/config/routes.rb +4 -0
- data/db/migrate/20200527135812_create_netbox_facet.rb +12 -0
- data/db/migrate/20200604141933_add_sync_info_to_netbox_facet.rb +8 -0
- data/db/migrate/20200708093607_add_raw_data_to_netbox_facet.rb +7 -0
- data/lib/foreman_netbox.rb +6 -0
- data/lib/foreman_netbox/engine.rb +64 -0
- data/lib/foreman_netbox/version.rb +5 -0
- data/lib/tasks/foreman_netbox_tasks.rake +67 -0
- data/test/factories/host.rb +17 -0
- data/test/factories/netbox_facet.rb +17 -0
- data/test/fixtures/facts/k8s_physical_host.json +328 -0
- data/test/fixtures/facts/rhel_physical_host.json +512 -0
- data/test/fixtures/facts/rhel_virtual_host.json +455 -0
- data/test/fixtures/netbox_device_raw_data.json +330 -0
- data/test/fixtures/netbox_virtual_machine_raw_data.json +241 -0
- data/test/integration/foreman_netbox/sync_k8s_physical_host_test.rb +81 -0
- data/test/integration/foreman_netbox/sync_rhel_physical_host_test.rb +81 -0
- data/test/integration/foreman_netbox/sync_rhel_virtual_host_test.rb +93 -0
- data/test/interactors/foreman_netbox/sync_host/organizer_test.rb +78 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/create_test.rb +65 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/find_test.rb +105 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/save_netbox_url_test.rb +39 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_role/create_test.rb +45 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_role/find_test.rb +58 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/create_test.rb +55 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/find_test.rb +63 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/sync_manufacturer/create_test.rb +48 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/sync_manufacturer/find_test.rb +105 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/update_test.rb +54 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/create_test.rb +51 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/delete_test.rb +41 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/find_test.rb +53 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/create_test.rb +80 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/delete_test.rb +72 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/find_test.rb +51 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/update_test.rb +64 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/update_test.rb +92 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_site/create_test.rb +51 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_site/find_test.rb +59 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_site/update_test.rb +54 -0
- data/test/interactors/foreman_netbox/sync_host/sync_device/update_test.rb +188 -0
- data/test/interactors/foreman_netbox/sync_host/sync_tenant/create_test.rb +50 -0
- data/test/interactors/foreman_netbox/sync_host/sync_tenant/find_test.rb +58 -0
- data/test/interactors/foreman_netbox/sync_host/sync_tenant/update_test.rb +59 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/create_test.rb +74 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/find_test.rb +77 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/save_netbox_url_test.rb +39 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/create_test.rb +54 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/find_test.rb +58 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/sync_cluster_type/create_test.rb +50 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/sync_cluster_type/find_test.rb +65 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/update_test.rb +54 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/create_test.rb +53 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/delete_test.rb +37 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/find_test.rb +53 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/create_test.rb +80 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/delete_test.rb +73 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/find_test.rb +51 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/update_test.rb +64 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/update_test.rb +88 -0
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/update_test.rb +171 -0
- data/test/jobs/foreman_netbox/sync_host_job_test.rb +14 -0
- data/test/models/foreman_netbox/location_test.rb +42 -0
- data/test/models/foreman_netbox/netbox_facet_test.rb +219 -0
- data/test/models/foreman_netbox/nics/base_test.rb +81 -0
- data/test/models/foreman_netbox/usergroup_test.rb +23 -0
- data/test/models/host/managed_test.rb +63 -0
- data/test/services/foreman_netbox/netbox_attributes_test.rb +278 -0
- data/test/services/foreman_netbox/netbox_parameters_comparator_test.rb +136 -0
- data/test/test_plugin_helper.rb +25 -0
- metadata +343 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanNetbox
|
4
|
+
module SyncHost
|
5
|
+
module SyncVirtualMachine
|
6
|
+
class Validate
|
7
|
+
include ::Interactor
|
8
|
+
|
9
|
+
def call
|
10
|
+
validator = ForemanNetbox::VirtualMachineContract.new.call(netbox_params)
|
11
|
+
|
12
|
+
return if validator.success?
|
13
|
+
|
14
|
+
message = validator.errors
|
15
|
+
.messages
|
16
|
+
.map { |m| "#{m.path} #{m.text}" }
|
17
|
+
.to_sentence
|
18
|
+
context.fail!(error: _('Invalid Virtual Machine parameters: %s') % message)
|
19
|
+
end
|
20
|
+
|
21
|
+
delegate :netbox_params, to: :context
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanNetbox
|
4
|
+
class SyncHostJob < ::ApplicationJob
|
5
|
+
queue_as :netbox_queue
|
6
|
+
|
7
|
+
def perform(host_id)
|
8
|
+
Host::Managed.find(host_id)&.push_to_netbox
|
9
|
+
end
|
10
|
+
|
11
|
+
rescue_from(StandardError) do |error|
|
12
|
+
Foreman::Logging.logger('background').error("Netbox: Error #{error}: #{error.backtrace}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def humanized_name
|
16
|
+
_('Push host to Netbox')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanNetbox
|
4
|
+
class API
|
5
|
+
def self.client
|
6
|
+
NetboxClientRuby.configure do |config|
|
7
|
+
config.netbox.api_base_url = "#{Setting::Netbox['netbox_url']}/api"
|
8
|
+
config.netbox.auth.token = Setting::Netbox['netbox_api_token']
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanNetbox
|
4
|
+
module HostExtensions
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
include ::Orchestration::Netbox
|
9
|
+
end
|
10
|
+
|
11
|
+
def netbox_facet
|
12
|
+
@netbox_facet ||= super || ForemanNetbox::NetboxFacet.new(host: self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def push_to_netbox_async
|
16
|
+
ForemanNetbox::SyncHostJob.perform_later(id)
|
17
|
+
end
|
18
|
+
|
19
|
+
def push_to_netbox
|
20
|
+
ForemanNetbox::SyncHost::Organizer.call(host: self)
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete_from_netbox
|
24
|
+
ForemanNetbox::DeleteHost::Organizer.call(host: self)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanNetbox
|
4
|
+
module Nic
|
5
|
+
module BaseExtensions
|
6
|
+
def netbox_name
|
7
|
+
identifier || (mac && "Interface #{mac}")
|
8
|
+
end
|
9
|
+
|
10
|
+
def netbox_ips
|
11
|
+
[netbox_ip, netbox_ip6].compact
|
12
|
+
end
|
13
|
+
|
14
|
+
def netbox_ip
|
15
|
+
ip && subnet && "#{ip}/#{subnet.cidr}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def netbox_ip6
|
19
|
+
ip6 && subnet6 && "#{ip6}/#{subnet6.cidr}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanNetbox
|
4
|
+
module UserUsergroupCommonExtensions
|
5
|
+
NETBOX_TENANT_MAX_LENGTH = 30
|
6
|
+
|
7
|
+
def netbox_tenant_name
|
8
|
+
return name unless name.length > NETBOX_TENANT_MAX_LENGTH
|
9
|
+
|
10
|
+
name_length = NETBOX_TENANT_MAX_LENGTH - id.to_s.length - 1
|
11
|
+
"#{name.to_s.truncate(name_length, omission: '')}-#{id}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def netbox_tenant_slug
|
15
|
+
netbox_tenant_name&.parameterize
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanNetbox
|
4
|
+
class NetboxFacet < ApplicationRecord
|
5
|
+
include Facets::Base
|
6
|
+
|
7
|
+
COMMON_PARAMS = %i[interfaces ip_addresses tenant].freeze
|
8
|
+
DEVICE_PARAMS = %i[device device_role device_type manufacturer site].freeze
|
9
|
+
VIRTUAL_MACHINE_PARAMS = %i[virtual_machine cluster cluster_type].freeze
|
10
|
+
|
11
|
+
validates :host, presence: true, allow_blank: false
|
12
|
+
validates :url, uniqueness: true
|
13
|
+
|
14
|
+
def synchronization_success?
|
15
|
+
!synchronization_error
|
16
|
+
end
|
17
|
+
|
18
|
+
def netbox_params
|
19
|
+
ForemanNetbox::NetboxParameters.call(host)
|
20
|
+
end
|
21
|
+
|
22
|
+
def cached_netbox_params
|
23
|
+
ForemanNetbox::CachedNetboxParameters.call(host)
|
24
|
+
end
|
25
|
+
|
26
|
+
def netbox_params_diff
|
27
|
+
ForemanNetbox::NetboxParametersComparator.call(cached_netbox_params, netbox_params)
|
28
|
+
end
|
29
|
+
|
30
|
+
def netbox_will_change?
|
31
|
+
netbox_params_diff.keys.any?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orchestration
|
4
|
+
module Netbox
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
after_validation :queue_netbox_push, if: :netbox_orchestration_allowed?
|
9
|
+
before_destroy :queue_netbox_destroy
|
10
|
+
end
|
11
|
+
|
12
|
+
delegate :netbox_will_change?, :netbox_params_diff, to: :netbox_facet
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def netbox_orchestration_allowed?
|
17
|
+
Setting::Netbox[:netbox_orchestration_enabled] && netbox_will_change?
|
18
|
+
end
|
19
|
+
|
20
|
+
def queue_netbox_push
|
21
|
+
return unless errors.empty? && managed?
|
22
|
+
|
23
|
+
::Foreman::Logging.logger('foreman_netbox/import')
|
24
|
+
.info("Queued import of #{name} to Netbox. Changes that will be sent: #{netbox_params_diff}")
|
25
|
+
|
26
|
+
post_queue.create(name: _('Push host %s to Netbox') % self, priority: 100,
|
27
|
+
action: [self, :set_netbox])
|
28
|
+
end
|
29
|
+
|
30
|
+
def queue_netbox_destroy
|
31
|
+
return unless errors.empty? && managed?
|
32
|
+
|
33
|
+
queue.create(name: _('Delete host %s from Netbox') % self, priority: 60,
|
34
|
+
action: [self, :del_netbox])
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_netbox
|
38
|
+
::Foreman::Logging.logger('foreman_netbox/import')
|
39
|
+
.info("Pushing #{name} to Netbox")
|
40
|
+
|
41
|
+
push_to_netbox_async
|
42
|
+
rescue StandardError => e
|
43
|
+
::Foreman::Logging.logger('foreman_netbox/import')
|
44
|
+
.error("Failed to push #{name} to Netbox. Error #{e}: #{e.backtrace}")
|
45
|
+
|
46
|
+
failure format(_('Failed to push %{name} to Netbox: %{message}\n '), name: name, message: e.message), e
|
47
|
+
end
|
48
|
+
|
49
|
+
def del_netbox
|
50
|
+
::Foreman::Logging.logger('foreman_netbox/import')
|
51
|
+
.info("Deleting #{name} from Netbox")
|
52
|
+
|
53
|
+
result = delete_from_netbox
|
54
|
+
return true if result.success?
|
55
|
+
|
56
|
+
raise Foreman::Exception, result.error
|
57
|
+
rescue StandardError => e
|
58
|
+
::Foreman::Logging.logger('foreman_netbox/import')
|
59
|
+
.error("Failed to delete #{name} from Netbox. Error #{e}: #{e.backtrace}")
|
60
|
+
|
61
|
+
failure format(_('Failed to delete %{name} from Netbox: %{message}\n '), name: name, message: e.message), e
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Setting
|
4
|
+
class Netbox < ::Setting
|
5
|
+
BLANK_ATTRS << 'netbox_url'
|
6
|
+
BLANK_ATTRS << 'netbox_api_token'
|
7
|
+
URI_BLANK_ATTRS << 'netbox_url'
|
8
|
+
|
9
|
+
def self.default_settings
|
10
|
+
[
|
11
|
+
set('netbox_url', N_('URL where Netbox is reachable'), nil, N_('Netbox URL')),
|
12
|
+
set('netbox_api_token', N_('API token to Netbox'), nil, N_('Netbox API token'), nil, encrypted: true),
|
13
|
+
set('netbox_orchestration_enabled', N_('Enable Netbox Orchestration'), false, N_('Netbox Orchestration'))
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.load_defaults
|
18
|
+
# Check the table exists
|
19
|
+
return unless super
|
20
|
+
|
21
|
+
transaction do
|
22
|
+
default_settings.each { |s| create! s.update(category: 'Setting::Netbox') }
|
23
|
+
end
|
24
|
+
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.humanized_category
|
29
|
+
N_('Netbox')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanNetbox
|
4
|
+
class CachedNetboxParameters
|
5
|
+
def self.call(host)
|
6
|
+
new(host).call
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(host)
|
10
|
+
@is_compute = host.compute?
|
11
|
+
@data = host.netbox_facet.raw_data&.deep_symbolize_keys || {}
|
12
|
+
@result = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
additional_params = is_compute ? ForemanNetbox::NetboxFacet::VIRTUAL_MACHINE_PARAMS : ForemanNetbox::NetboxFacet::DEVICE_PARAMS
|
17
|
+
(ForemanNetbox::NetboxFacet::COMMON_PARAMS + additional_params).map { |key| send("read_#{key}") }
|
18
|
+
|
19
|
+
result
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :data, :is_compute
|
25
|
+
attr_accessor :result
|
26
|
+
|
27
|
+
def read_interfaces
|
28
|
+
return unless data.keys.include?(:interfaces)
|
29
|
+
|
30
|
+
result[:interfaces] = data.fetch(:interfaces, {}).fetch(:results, []).map do |interface|
|
31
|
+
interface.slice(:name, :mac_address, :tags)
|
32
|
+
.merge(type: interface.fetch(:type, {}).slice(:value))
|
33
|
+
.compact
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def read_ip_addresses
|
38
|
+
return unless data.keys.include?(:ip_addresses)
|
39
|
+
|
40
|
+
result[:ip_addresses] = data.fetch(:ip_addresses, {}).fetch(:results, []).map do |ip_address|
|
41
|
+
ip_address.slice(:address, :tags)
|
42
|
+
.merge(interface: ip_address.fetch(:interface, {}).slice(:name))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def read_virtual_machine
|
47
|
+
return unless data.keys.include?(:virtual_machine)
|
48
|
+
|
49
|
+
result[:virtual_machine] = data.fetch(:virtual_machine, {}).slice(:name, :vcpus, :memory, :disk, :tags)
|
50
|
+
end
|
51
|
+
|
52
|
+
def read_tenant
|
53
|
+
return unless data.keys.include?(:tenant)
|
54
|
+
|
55
|
+
result[:tenant] = data.fetch(:tenant, {}).slice(:name, :slug, :tags)
|
56
|
+
end
|
57
|
+
|
58
|
+
def read_cluster
|
59
|
+
return unless data.keys.include?(:cluster)
|
60
|
+
|
61
|
+
result[:cluster] = data.fetch(:cluster, {}).slice(:name, :tags)
|
62
|
+
end
|
63
|
+
|
64
|
+
def read_cluster_type
|
65
|
+
return unless data.keys.include?(:cluster_type)
|
66
|
+
|
67
|
+
result[:cluster_type] = data.fetch(:cluster_type, {}).slice(:name, :slug)
|
68
|
+
end
|
69
|
+
|
70
|
+
def read_device
|
71
|
+
return unless data.keys.include?(:device)
|
72
|
+
|
73
|
+
result[:device] = data.fetch(:device, {})
|
74
|
+
.slice(:name, :serial, :tags)
|
75
|
+
.compact
|
76
|
+
.reject { |k, v| k == :serial && v.blank? }
|
77
|
+
end
|
78
|
+
|
79
|
+
def read_device_role
|
80
|
+
return unless data.keys.include?(:device_role)
|
81
|
+
|
82
|
+
result[:device_role] = data.fetch(:device_role, {}).slice(:name, :color, :slug)
|
83
|
+
end
|
84
|
+
|
85
|
+
def read_device_type
|
86
|
+
return unless data.keys.include?(:device_type)
|
87
|
+
|
88
|
+
result[:device_type] = data.fetch(:device_type, {}).slice(:model, :slug, :tags)
|
89
|
+
end
|
90
|
+
|
91
|
+
def read_manufacturer
|
92
|
+
return unless data.keys.include?(:manufacturer)
|
93
|
+
|
94
|
+
result[:manufacturer] = data.fetch(:manufacturer, {}).slice(:name, :slug)
|
95
|
+
end
|
96
|
+
|
97
|
+
def read_site
|
98
|
+
return unless data.keys.include?(:site)
|
99
|
+
|
100
|
+
result[:site] = data.fetch(:site, {}).slice(:name, :slug, :tags)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanNetbox
|
4
|
+
# rubocop:disable Metrics/ClassLength
|
5
|
+
class NetboxParameters
|
6
|
+
UNKNOWN = 'Unknown'
|
7
|
+
DEFAULT_TAGS = ['foreman'].freeze
|
8
|
+
DEFAULT_INTERFACE_TYPE = 'virtual'
|
9
|
+
CLUSTER_TYPES = {
|
10
|
+
:'Foreman::Model::Vmware' => {
|
11
|
+
name: 'VMware ESXi',
|
12
|
+
slug: 'vmware-esxi'
|
13
|
+
}
|
14
|
+
}.freeze
|
15
|
+
DEVICE_ROLE = {
|
16
|
+
name: 'SERVER',
|
17
|
+
color: '9e9e9e',
|
18
|
+
slug: 'server'
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
def self.call(host)
|
22
|
+
new(host).call
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(host)
|
26
|
+
@host = host
|
27
|
+
end
|
28
|
+
|
29
|
+
def call
|
30
|
+
additional_params = host.compute? ? ForemanNetbox::NetboxFacet::VIRTUAL_MACHINE_PARAMS : ForemanNetbox::NetboxFacet::DEVICE_PARAMS
|
31
|
+
|
32
|
+
(ForemanNetbox::NetboxFacet::COMMON_PARAMS + additional_params).map do |param|
|
33
|
+
send(param)
|
34
|
+
end.reduce({}, :merge)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_accessor :host
|
40
|
+
|
41
|
+
delegate :netbox_facet, to: :host
|
42
|
+
delegate :cached_netbox_params, to: :netbox_facet
|
43
|
+
|
44
|
+
def netbox_compute_attributes
|
45
|
+
@netbox_compute_attributes ||= host.compute_object.yield_self do |compute_object|
|
46
|
+
{
|
47
|
+
vcpus: compute_object&.cpus,
|
48
|
+
memory: compute_object&.memory_mb,
|
49
|
+
disk: compute_object&.volumes&.map(&:size_gb)&.reduce(&:+),
|
50
|
+
cluster: compute_object&.cluster
|
51
|
+
}.compact
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def tenant
|
56
|
+
{
|
57
|
+
tenant: {
|
58
|
+
name: host.owner&.netbox_tenant_name,
|
59
|
+
slug: host.owner&.netbox_tenant_slug,
|
60
|
+
tags: DEFAULT_TAGS
|
61
|
+
}
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def device
|
66
|
+
{
|
67
|
+
device: {
|
68
|
+
name: host.name,
|
69
|
+
serial: host.facts.deep_symbolize_keys[:serialnumber],
|
70
|
+
tags: DEFAULT_TAGS
|
71
|
+
}
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def device_role
|
76
|
+
{
|
77
|
+
device_role: DEVICE_ROLE
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
def device_type
|
82
|
+
model = host.facts.deep_symbolize_keys[:productname] || host.facts.deep_symbolize_keys[:'dmi::product::name'] || UNKNOWN
|
83
|
+
|
84
|
+
{
|
85
|
+
device_type: {
|
86
|
+
model: model,
|
87
|
+
slug: model.parameterize,
|
88
|
+
tags: DEFAULT_TAGS
|
89
|
+
}
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def manufacturer
|
94
|
+
name = host.facts.deep_symbolize_keys[:manufacturer] || host.facts.deep_symbolize_keys[:'dmi::manufacturer'] || UNKNOWN
|
95
|
+
|
96
|
+
{
|
97
|
+
manufacturer: {
|
98
|
+
name: name,
|
99
|
+
slug: cached_netbox_params.dig(:manufacturer, :slug) || name.parameterize
|
100
|
+
}
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
def site
|
105
|
+
{
|
106
|
+
site: {
|
107
|
+
name: host.location&.netbox_site_name,
|
108
|
+
slug: host.location&.netbox_site_slug,
|
109
|
+
tags: DEFAULT_TAGS
|
110
|
+
}
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
def interfaces
|
115
|
+
{
|
116
|
+
interfaces: host.interfaces.map do |interface|
|
117
|
+
identifier = interface.identifier.present? && interface.identifier
|
118
|
+
mac_address = interface.mac&.upcase
|
119
|
+
|
120
|
+
{
|
121
|
+
name: identifier || (mac_address && "Interface #{mac_address}"),
|
122
|
+
mac_address: mac_address,
|
123
|
+
type: {
|
124
|
+
value: DEFAULT_INTERFACE_TYPE
|
125
|
+
},
|
126
|
+
tags: DEFAULT_TAGS
|
127
|
+
}
|
128
|
+
end
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
133
|
+
def ip_addresses
|
134
|
+
{
|
135
|
+
ip_addresses: host.interfaces.map do |interface|
|
136
|
+
[
|
137
|
+
interface.ip && interface.subnet && "#{interface.ip}/#{interface.subnet.cidr}",
|
138
|
+
interface.ip6 && interface.subnet6 && "#{interface.ip6}/#{interface.subnet6.cidr}"
|
139
|
+
].compact.map do |ip_address|
|
140
|
+
identifier = interface.identifier.present? && interface.identifier
|
141
|
+
mac_address = interface.mac&.upcase
|
142
|
+
|
143
|
+
{
|
144
|
+
address: ip_address,
|
145
|
+
interface: {
|
146
|
+
name: identifier || (mac_address && "Interface #{mac_address}")
|
147
|
+
},
|
148
|
+
tags: DEFAULT_TAGS
|
149
|
+
}
|
150
|
+
end
|
151
|
+
end.flatten
|
152
|
+
}
|
153
|
+
end
|
154
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
155
|
+
|
156
|
+
def virtual_machine
|
157
|
+
{
|
158
|
+
virtual_machine: netbox_compute_attributes.slice(
|
159
|
+
:vcpus, :memory, :disk
|
160
|
+
).merge(
|
161
|
+
name: host.name,
|
162
|
+
tags: DEFAULT_TAGS
|
163
|
+
)
|
164
|
+
}
|
165
|
+
end
|
166
|
+
|
167
|
+
def cluster
|
168
|
+
{
|
169
|
+
cluster: {
|
170
|
+
name: netbox_compute_attributes[:cluster],
|
171
|
+
tags: DEFAULT_TAGS
|
172
|
+
}.compact
|
173
|
+
}
|
174
|
+
end
|
175
|
+
|
176
|
+
def cluster_type
|
177
|
+
type = host.compute_resource&.type&.to_sym
|
178
|
+
|
179
|
+
{
|
180
|
+
cluster_type: CLUSTER_TYPES.fetch(type, nil)
|
181
|
+
}
|
182
|
+
end
|
183
|
+
end
|
184
|
+
# rubocop:enable Metrics/ClassLength
|
185
|
+
end
|