smart_proxy_dhcp_infoblox 0.0.5 → 0.0.18
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.
- checksums.yaml +5 -5
- data/README.md +57 -2
- data/config/dhcp_infoblox.yml.example +34 -13
- data/lib/smart_proxy_dhcp_infoblox/common_crud.rb +46 -9
- data/lib/smart_proxy_dhcp_infoblox/dhcp_infoblox_main.rb +48 -14
- data/lib/smart_proxy_dhcp_infoblox/dhcp_infoblox_plugin.rb +13 -4
- data/lib/smart_proxy_dhcp_infoblox/dhcp_infoblox_version.rb +1 -1
- data/lib/smart_proxy_dhcp_infoblox/fixed_address_crud.rb +59 -18
- data/lib/smart_proxy_dhcp_infoblox/grid_restart.rb +15 -4
- data/lib/smart_proxy_dhcp_infoblox/host_ipv4_address_crud.rb +57 -15
- data/lib/smart_proxy_dhcp_infoblox/ip_address_arithmetic.rb +6 -6
- data/lib/smart_proxy_dhcp_infoblox/network_address_range_regex_generator.rb +19 -12
- data/lib/smart_proxy_dhcp_infoblox/plugin_configuration.rb +32 -21
- data/lib/smart_proxy_dhcp_infoblox.rb +0 -1
- data/test/host_and_fixedaddress_crud_test.rb +166 -34
- data/test/infoblox_provider_test.rb +65 -11
- data/test/integration_test.rb +96 -0
- data/test/plugin_configuration_test.rb +25 -13
- data/test/test_helper.rb +1 -1
- data/test/unused_ip_test.rb +39 -29
- metadata +22 -11
- data/lib/smart_proxy_dhcp_infoblox/record_type_validator.rb +0 -8
- data/lib/smart_proxy_dhcp_infoblox/unused_ips.rb +0 -47
- data/test/record_type_validator_test.rb +0 -20
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 644a754d3e910db7479ae0a9bb5329dcb9c690af8c25ce1eba5a92425855f397
|
|
4
|
+
data.tar.gz: cb1a382785eb1accea703a945b187aa83cb74184ca06194829969d1d33b915a5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 07c4763058d119b947ff381d9977090aebd9365d556ad9ca61ede8e85f2f5191b214a4d6254ea042730cf85893df69c3040d67d7c91309148fdddc44946c6b6f
|
|
7
|
+
data.tar.gz: 1ab4070a4260f0e97ee442c50fb3e7eccf92c44b5afc75484ef300cfb222b8d536d21815475fdabd555ddabd6c05d12795f588e980100a796c5ccc0b52fea3c3
|
data/README.md
CHANGED
|
@@ -9,6 +9,19 @@ for how to install Smart Proxy plugins
|
|
|
9
9
|
|
|
10
10
|
This plugin is compatible with Smart Proxy 1.11 or higher.
|
|
11
11
|
|
|
12
|
+
Example installation command via foreman-installer:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
# foreman-installer --enable-foreman-proxy-plugin-dhcp-infoblox \
|
|
16
|
+
--foreman-proxy-dhcp-provider infoblox \
|
|
17
|
+
--foreman-proxy-plugin-dhcp-infoblox-record-type host \
|
|
18
|
+
--foreman-proxy-dhcp-server 192.168.201.2 \
|
|
19
|
+
--foreman-proxy-plugin-dhcp-infoblox-username admin \
|
|
20
|
+
--foreman-proxy-plugin-dhcp-infoblox-password infoblox \
|
|
21
|
+
--foreman-proxy-plugin-dhcp-infoblox-network-view default \
|
|
22
|
+
--foreman-proxy-plugin-dhcp-infoblox-dns-view default
|
|
23
|
+
```
|
|
24
|
+
|
|
12
25
|
When installing using "gem", make sure to install the bundle file:
|
|
13
26
|
|
|
14
27
|
echo "gem 'smart_proxy_dhcp_infoblox'" > /usr/share/foreman-proxy/bundler.d/dhcp_infoblox.rb
|
|
@@ -24,15 +37,57 @@ To enable this DHCP provider, edit `/etc/foreman-proxy/settings.d/dhcp.yml` and
|
|
|
24
37
|
Configuration options for this plugin are in `/etc/foreman-proxy/settings.d/dhcp_infoblox.yml` and include:
|
|
25
38
|
|
|
26
39
|
* username: API Username
|
|
27
|
-
*
|
|
40
|
+
* password: API Password
|
|
28
41
|
* record_type: host / fixedaddress (see different record types chapter)
|
|
29
|
-
*
|
|
42
|
+
* used_ips_search_type: record_type / used
|
|
30
43
|
|
|
31
44
|
## Different record types
|
|
32
45
|
The main difference between host and fixedaddress is that a host record already includes the dns records. It's an infoblox object that includes dhcp/a record/ptr records. If you use the host objects there is no need to use a dns smart proxy. Everything gets handled inside the dhcp smart proxy. This does however limit functionality. You can't delete conflicting records or you can't change dns names using foreman gui. Beware when editing host objects manually in infoblox, once you delete a host in foreman all associated host objects get deleted.
|
|
33
46
|
|
|
34
47
|
If you chose to use fixedaddress you'll need to use the infoblox dns smart proxy (https://github.com/theforeman/smart_proxy_dns_infoblox) if you want to manage dns records.
|
|
35
48
|
|
|
49
|
+
## Used IP search type
|
|
50
|
+
When using "record_type" here, used IPs will be looked up among the record type you select on the record_type setting (host or fixedaddress). So everything which is not a host or a fixedaddress (depending on the setting), will be defined as free and can be selected as an IP to provision a host.
|
|
51
|
+
If the IP is used by just a DNS A entry for example, this can lead to conflicts. If "used" is set here, any usage of an IP will mark it as used and the IP will not be selected as free ip to provision a host.
|
|
52
|
+
Usages without a mac address will get a dummy mac address ("00:00:00:00:00:00"), when Foreman looks for "all_hosts".
|
|
53
|
+
|
|
54
|
+
## SSL
|
|
55
|
+
|
|
56
|
+
The plugin enforces HTTPS server certificate verification. Follow a standard CA cert installation procedure for your operating system. It's possible to either download the server certificate from Infoblox web UI or use openssl command to extract it from server response. Here are example steps for Red Hat compatible systems:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
# update-ca-trust enable
|
|
60
|
+
# openssl s_client -showcerts -connect 192.168.201.2:443 </dev/null | openssl x509 -text >/etc/pki/ca-trust/source/anchors/infoblox.crt
|
|
61
|
+
# update-ca-trust extract
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
For Debian-compatible systems:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
# openssl s_client -showcerts -connect 192.168.201.2:443 </dev/null | openssl x509 -text >/usr/local/share/ca-certificates/infoblox.crt
|
|
68
|
+
# update-ca-certificates
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
To test the CA certificate, a simple curl query can be used. This is a positive test:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
# curl -u admin:infoblox https://192.168.201.2/wapi/v2.0/network
|
|
75
|
+
[
|
|
76
|
+
{
|
|
77
|
+
"_ref": "network/ZG5zLm5ldHdvcmskMTkyLjE2OC4yMDIuMC8yNC8w:192.168.202.0/24/default",
|
|
78
|
+
"network": "192.168.202.0/24",
|
|
79
|
+
"network_view": "default"
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
And a negative one:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
# curl -u admin:infoblox https://192.168.201.2/wapi/v2.0/network
|
|
88
|
+
curl: (60) SSL certificate problem: self signed certificate
|
|
89
|
+
```
|
|
90
|
+
|
|
36
91
|
## Contributing
|
|
37
92
|
|
|
38
93
|
Fork and send a Pull Request. Thanks!
|
|
@@ -1,17 +1,38 @@
|
|
|
1
1
|
---
|
|
2
|
-
#
|
|
3
2
|
# Configuration file for 'dhcp_infoblox' dhcp provider
|
|
4
3
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
# Use :server setting in dhcp.yml if you are managing a dhcp server which is not localhost.
|
|
5
|
+
# Use :subnets setting in dhcp.yml if you want to restrict subnets available to smart-proxy.
|
|
6
|
+
|
|
7
|
+
# Credentials for Infoblox API, make sure the DHCP Role is assigned
|
|
8
|
+
:username: "admin"
|
|
9
9
|
:password: "infoblox"
|
|
10
|
-
|
|
11
|
-
# Record type to manage: can be "host" or "
|
|
12
|
-
#
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
#
|
|
17
|
-
|
|
10
|
+
|
|
11
|
+
# Record type to manage: can be "host" or "fixedaddress". The latter is recommended as
|
|
12
|
+
# "host" setting will cause conflicts when using Infoblox DNS smart proxy plugin. When
|
|
13
|
+
# using "host" setting make sure domain exists in Infoblox.
|
|
14
|
+
:record_type: 'fixedaddress'
|
|
15
|
+
|
|
16
|
+
# Search type used when looking for used IPs: can be "record_type" or "used". The latter can be used when you want to include all "USED"
|
|
17
|
+
# IPs in the search for used IPs, so that only really "UNUSED" (no Host, no DNS object, no DHCP Range, not unmanaged, etc.) are used, when
|
|
18
|
+
# searching for a unused IP. Defaults to "record_type", which uses the record_type selected above to look for used IPs.
|
|
19
|
+
#:used_ips_search_type: 'record_type'
|
|
20
|
+
|
|
21
|
+
# View used for fixedaddress record type.
|
|
22
|
+
#:network_view: 'default'
|
|
23
|
+
|
|
24
|
+
# View used for host record type, usually 'default.myview' for custom names.
|
|
25
|
+
#:dns_view: 'default'
|
|
26
|
+
|
|
27
|
+
# Number of seconds to wait after successful Grid restart (make sure to increase Foreman and CLI timeouts).
|
|
28
|
+
# Set to 0 to disable the delay.
|
|
29
|
+
#:wait_after_restart: 10
|
|
30
|
+
|
|
31
|
+
# DHCP custom options (name, num, value and vendor_class). Set to blank to ignore.
|
|
32
|
+
# This is only used for 'fixedaddress' record types.
|
|
33
|
+
#:options:
|
|
34
|
+
#-
|
|
35
|
+
#name: "DHCP option name"
|
|
36
|
+
#num: 1234
|
|
37
|
+
#value: "A value"
|
|
38
|
+
#vendor_class: "A vendor class"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'resolv'
|
|
2
2
|
require 'smart_proxy_dhcp_infoblox/ip_address_arithmetic'
|
|
3
|
+
require 'smart_proxy_dhcp_infoblox/network_address_range_regex_generator'
|
|
3
4
|
require "proxy/validations"
|
|
4
5
|
|
|
5
6
|
module ::Proxy::DHCP::Infoblox
|
|
@@ -9,16 +10,33 @@ module ::Proxy::DHCP::Infoblox
|
|
|
9
10
|
|
|
10
11
|
attr_reader :connection
|
|
11
12
|
|
|
12
|
-
def initialize(connection)
|
|
13
|
+
def initialize(connection, used_ips_search_type)
|
|
13
14
|
@connection = connection
|
|
15
|
+
@used_ips_search_type = used_ips_search_type
|
|
14
16
|
end
|
|
15
17
|
|
|
16
|
-
def all_leases(network_address)
|
|
17
|
-
|
|
18
|
+
def all_leases(network_address, subnet)
|
|
19
|
+
address_range_regex = NetworkAddressesRegularExpressionGenerator.new.generate_regex(network_address)
|
|
20
|
+
::Infoblox::Lease.find(@connection, 'address~' => address_range_regex).map do |lease|
|
|
21
|
+
# Infoblox can return MAC address set to nil
|
|
22
|
+
next unless lease.hardware
|
|
23
|
+
|
|
24
|
+
Proxy::DHCP::Lease.new(
|
|
25
|
+
lease.client_hostname,
|
|
26
|
+
lease.address,
|
|
27
|
+
lease.hardware,
|
|
28
|
+
subnet,
|
|
29
|
+
lease.starts,
|
|
30
|
+
lease.ends,
|
|
31
|
+
lease.binding_state,
|
|
32
|
+
:hostname => lease.client_hostname
|
|
33
|
+
)
|
|
34
|
+
end.compact
|
|
18
35
|
end
|
|
19
36
|
|
|
20
37
|
def find_record(subnet_address, an_address)
|
|
21
38
|
return find_record_by_ip(subnet_address, an_address) if Resolv::IPv4::Regex =~ an_address
|
|
39
|
+
|
|
22
40
|
find_record_by_mac(subnet_address, an_address)
|
|
23
41
|
end
|
|
24
42
|
|
|
@@ -43,14 +61,33 @@ module ::Proxy::DHCP::Infoblox
|
|
|
43
61
|
if options[:mac] != existing_host.mac || options[:hostname] != existing_name
|
|
44
62
|
raise Proxy::DHCP::Collision, "Record #{options[:ip]} conflicts with an existing record."
|
|
45
63
|
end
|
|
64
|
+
|
|
46
65
|
raise Proxy::DHCP::AlreadyExists, "Record #{options[:ip]} already exists."
|
|
47
66
|
end
|
|
48
67
|
|
|
49
68
|
def del_record(_, record)
|
|
50
69
|
raise InvalidRecord, "#{record} is static - unable to delete" unless record.deleteable?
|
|
51
|
-
|
|
70
|
+
|
|
71
|
+
found = find_hosts('ipv4addr' => record.ip).first
|
|
52
72
|
return if found.nil?
|
|
73
|
+
|
|
74
|
+
found.delete
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def del_records_by_ip(ip_address)
|
|
78
|
+
found = find_hosts({ 'ipv4addr' => ip_address }, 2147483646)
|
|
79
|
+
return if found.empty?
|
|
80
|
+
|
|
81
|
+
found.each { |record| record.delete }
|
|
82
|
+
nil
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def del_record_by_mac(mac_address)
|
|
86
|
+
found = find_hosts('mac' => mac_address).first
|
|
87
|
+
return if found.nil?
|
|
88
|
+
|
|
53
89
|
found.delete
|
|
90
|
+
nil
|
|
54
91
|
end
|
|
55
92
|
|
|
56
93
|
def build_reservation(name, host, full_subnet_address)
|
|
@@ -60,16 +97,16 @@ module ::Proxy::DHCP::Infoblox
|
|
|
60
97
|
return nil if host.mac.nil? || host.mac.empty?
|
|
61
98
|
|
|
62
99
|
opts = { :hostname => name }
|
|
63
|
-
opts[:mac] = host.mac
|
|
64
|
-
opts[:ip] = host.ipv4addr
|
|
65
100
|
opts[:deleteable] = true
|
|
66
|
-
# TODO: nextserver, use_nextserver, bootfile, and use_bootfile attrs exist
|
|
101
|
+
# TODO: nextserver, use_nextserver, bootfile, and use_bootfile attrs exist
|
|
102
|
+
# but are not available in the Fixedaddress model
|
|
67
103
|
# Might be useful to extend the model to include these
|
|
68
104
|
opts[:nextServer] = host.nextserver if (host.respond_to?(:use_nextserver) && host.use_nextserver)
|
|
69
105
|
opts[:filename] = host.bootfile if (host.respond_to?(:use_bootfile) && host.use_bootfile)
|
|
70
|
-
|
|
106
|
+
subnet = ::Proxy::DHCP::Subnet.new(full_subnet_address.split('/').first,
|
|
107
|
+
cidr_to_ip_mask(cidr_to_i(full_subnet_address.split('/').last)))
|
|
71
108
|
|
|
72
|
-
Proxy::DHCP::Reservation.new(opts)
|
|
109
|
+
Proxy::DHCP::Reservation.new(name, host.ipv4addr, host.mac, subnet, opts)
|
|
73
110
|
end
|
|
74
111
|
end
|
|
75
112
|
end
|
|
@@ -7,19 +7,17 @@ module Proxy::DHCP::Infoblox
|
|
|
7
7
|
include Proxy::Util
|
|
8
8
|
include IpAddressArithmetic
|
|
9
9
|
|
|
10
|
-
attr_reader :connection, :crud, :restart_grid, :
|
|
10
|
+
attr_reader :connection, :crud, :restart_grid, :network_view
|
|
11
11
|
|
|
12
|
-
def initialize(connection, crud, restart_grid, unused_ips, managed_subnets)
|
|
12
|
+
def initialize(connection, crud, restart_grid, unused_ips, managed_subnets, network_view)
|
|
13
13
|
@connection = connection
|
|
14
14
|
@crud = crud
|
|
15
15
|
@restart_grid = restart_grid
|
|
16
|
-
@
|
|
17
|
-
super('infoblox', managed_subnets, nil)
|
|
16
|
+
@network_view = network_view
|
|
17
|
+
super('infoblox', managed_subnets, nil, unused_ips)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def find_subnet(address)
|
|
21
|
-
def load_subnets; end
|
|
22
|
-
def load_subnet_data(_); end
|
|
20
|
+
def find_subnet(address); ::Proxy::DHCP::Subnet.new(address, '255.255.255.0'); end
|
|
23
21
|
|
|
24
22
|
def subnets
|
|
25
23
|
::Infoblox::Network.all(connection).map do |network|
|
|
@@ -34,32 +32,68 @@ module Proxy::DHCP::Infoblox
|
|
|
34
32
|
end
|
|
35
33
|
|
|
36
34
|
def all_leases(network_address)
|
|
37
|
-
crud.all_leases(full_network_address(network_address))
|
|
35
|
+
crud.all_leases(full_network_address(network_address), find_subnet(network_address))
|
|
38
36
|
end
|
|
39
37
|
|
|
40
38
|
def find_record(subnet_address, an_address)
|
|
41
39
|
crud.find_record(full_network_address(subnet_address), an_address)
|
|
42
40
|
end
|
|
43
41
|
|
|
42
|
+
def find_record_by_mac(subnet_address, mac_address)
|
|
43
|
+
crud.find_record_by_mac(full_network_address(subnet_address), mac_address)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def find_records_by_ip(subnet_address, ip_address)
|
|
47
|
+
crud.find_records_by_ip(full_network_address(subnet_address), ip_address)
|
|
48
|
+
end
|
|
49
|
+
|
|
44
50
|
def add_record(options)
|
|
45
51
|
crud.add_record(options)
|
|
46
52
|
logger.debug("Added DHCP reservation for #{options[:ip]}/#{options[:mac]}")
|
|
47
53
|
restart_grid.try_restart
|
|
48
54
|
end
|
|
49
55
|
|
|
50
|
-
def del_record(
|
|
51
|
-
crud.del_record(full_network_address(
|
|
56
|
+
def del_record(record)
|
|
57
|
+
crud.del_record(full_network_address(record.subnet_address), record)
|
|
52
58
|
logger.debug("Removed DHCP reservation for #{record.ip} => #{record}")
|
|
53
59
|
restart_grid.try_restart
|
|
54
60
|
end
|
|
55
61
|
|
|
56
|
-
def
|
|
57
|
-
|
|
62
|
+
def del_record_by_mac(_, mac_address)
|
|
63
|
+
crud.del_record_by_mac(mac_address)
|
|
64
|
+
logger.debug("Removed DHCP reservation for #{mac_address}")
|
|
65
|
+
restart_grid.try_restart
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def del_records_by_ip(_, ip_address)
|
|
69
|
+
crud.del_records_by_ip(ip_address)
|
|
70
|
+
logger.debug("Removed DHCP reservation(s) for #{ip_address}")
|
|
71
|
+
restart_grid.try_restart
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
require 'dhcp_common/subnet'
|
|
75
|
+
def get_subnet(subnet_address)
|
|
76
|
+
address, prefix_length = full_network_address(subnet_address).split("/")
|
|
77
|
+
netmask = cidr_to_ip_mask(prefix_length.to_i)
|
|
78
|
+
::Proxy::DHCP::Subnet.new(address, netmask)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def find_ip_by_mac_address_and_range(subnet, mac_address, from_address, to_address)
|
|
82
|
+
r = crud.find_record_by_mac("#{subnet.network}/#{subnet.cidr}", mac_address)
|
|
83
|
+
|
|
84
|
+
if r && (IPAddr.new(from_address)..IPAddr.new(to_address)).cover?(IPAddr.new(r.ip))
|
|
85
|
+
logger.debug "Found an existing DHCP record #{r}, reusing..."
|
|
86
|
+
return r.ip
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
nil
|
|
58
90
|
end
|
|
59
91
|
|
|
60
92
|
def find_network(network_address)
|
|
61
|
-
network = ::Infoblox::Network.find(connection, 'network
|
|
62
|
-
|
|
93
|
+
network = ::Infoblox::Network.find(connection, 'network' => network_address, 'network_view' => network_view,
|
|
94
|
+
'_max_results' => 1).first
|
|
95
|
+
raise "Subnet #{network_address} not found in network view #{network_view}" if network.nil?
|
|
96
|
+
|
|
63
97
|
network
|
|
64
98
|
end
|
|
65
99
|
|
|
@@ -2,15 +2,24 @@ module Proxy::DHCP::Infoblox
|
|
|
2
2
|
class Plugin < ::Proxy::Provider
|
|
3
3
|
plugin :dhcp_infoblox, ::Proxy::DHCP::Infoblox::VERSION
|
|
4
4
|
|
|
5
|
-
default_settings :record_type => '
|
|
5
|
+
default_settings :record_type => 'fixedaddress',
|
|
6
|
+
:used_ips_search_type => "record_type",
|
|
7
|
+
:dns_view => "default",
|
|
8
|
+
:network_view => "default",
|
|
9
|
+
:blacklist_duration_minutes => 30 * 60,
|
|
10
|
+
:wait_after_restart => 10,
|
|
11
|
+
:options => []
|
|
12
|
+
|
|
6
13
|
validate_presence :username, :password
|
|
7
14
|
|
|
8
|
-
requires :dhcp, '>=
|
|
15
|
+
requires :dhcp, '>= 3.2'
|
|
9
16
|
|
|
10
17
|
load_classes ::Proxy::DHCP::Infoblox::PluginConfiguration
|
|
11
|
-
load_validators :record_type_validator => ::Proxy::DHCP::Infoblox::RecordTypeValidator
|
|
12
18
|
load_dependency_injection_wirings ::Proxy::DHCP::Infoblox::PluginConfiguration
|
|
13
19
|
|
|
14
|
-
validate :record_type, :
|
|
20
|
+
validate :record_type, enum: %w[host fixedaddress]
|
|
21
|
+
validate :used_ips_search_type, enum: %w[record_type used]
|
|
22
|
+
|
|
23
|
+
start_services :unused_ips
|
|
15
24
|
end
|
|
16
25
|
end
|
|
@@ -1,39 +1,80 @@
|
|
|
1
|
+
require 'yaml'
|
|
1
2
|
require 'smart_proxy_dhcp_infoblox/common_crud'
|
|
2
3
|
|
|
3
4
|
module ::Proxy::DHCP::Infoblox
|
|
4
5
|
class FixedAddressCRUD < CommonCRUD
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
attr_reader :network_view
|
|
7
|
+
|
|
8
|
+
def initialize(connection, network_view, used_ips_search_type)
|
|
9
|
+
@memoized_hosts = []
|
|
7
10
|
@memoized_condition = nil
|
|
8
|
-
|
|
11
|
+
@network_view = network_view
|
|
12
|
+
super(connection, used_ips_search_type)
|
|
9
13
|
end
|
|
10
14
|
|
|
11
15
|
def all_hosts(subnet_address)
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
if @used_ips_search_type == 'used'
|
|
17
|
+
addresses = ::Infoblox::Ipv4address.find(
|
|
18
|
+
@connection,
|
|
19
|
+
'network' => subnet_address,
|
|
20
|
+
'status' => 'USED',
|
|
21
|
+
'_max_results' => 2147483646)
|
|
22
|
+
network = addresses.map do |address|
|
|
23
|
+
if address.mac_address.nil? || address.mac_address.empty?
|
|
24
|
+
checked_mac = '00:00:00:00:00:00'
|
|
25
|
+
else
|
|
26
|
+
checked_mac = address.mac_address
|
|
27
|
+
end
|
|
28
|
+
::Infoblox::Fixedaddress.new(
|
|
29
|
+
:name => address.names[0],
|
|
30
|
+
:ipv4addr => address.ip_address,
|
|
31
|
+
:mac => checked_mac
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
else
|
|
35
|
+
network = ::Infoblox::Fixedaddress.find(
|
|
36
|
+
@connection,
|
|
37
|
+
'network' => subnet_address,
|
|
38
|
+
'network_view' => network_view,
|
|
39
|
+
'_max_results' => 2147483646) #2**(32-cidr_to_i(subnet_address)))
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
network.map { |h| build_reservation(h.name, h, subnet_address) }.compact
|
|
14
43
|
end
|
|
15
44
|
|
|
16
45
|
def find_record_by_ip(subnet_address, ip_address)
|
|
17
|
-
found =
|
|
46
|
+
found = find_hosts('ipv4addr' => ip_address).first
|
|
18
47
|
return nil if found.nil?
|
|
48
|
+
|
|
19
49
|
build_reservation(found.name, found, subnet_address)
|
|
20
50
|
end
|
|
21
51
|
|
|
52
|
+
def find_records_by_ip(subnet_address, ip_address)
|
|
53
|
+
found = find_hosts({ 'ipv4addr' => ip_address }, 2147483646)
|
|
54
|
+
return [] if found.empty?
|
|
55
|
+
|
|
56
|
+
to_return = found.map { |record| build_reservation(record.name, record, subnet_address) }
|
|
57
|
+
to_return.compact
|
|
58
|
+
end
|
|
59
|
+
|
|
22
60
|
def find_record_by_mac(subnet_address, mac_address)
|
|
23
|
-
found =
|
|
61
|
+
found = find_hosts('mac' => mac_address).first
|
|
24
62
|
return nil if found.nil?
|
|
63
|
+
|
|
25
64
|
build_reservation(found.name, found, subnet_address)
|
|
26
65
|
end
|
|
27
66
|
|
|
28
|
-
def
|
|
29
|
-
return @
|
|
67
|
+
def find_hosts(condition, max_results = 1)
|
|
68
|
+
return @memoized_hosts if (!@memoized_hosts.empty? && @memoized_condition = condition)
|
|
69
|
+
|
|
30
70
|
@memoized_condition = condition
|
|
31
|
-
@
|
|
71
|
+
@memoized_hosts = ::Infoblox::Fixedaddress.find(@connection, condition.merge('_max_results' => max_results,
|
|
72
|
+
'network_view' => network_view))
|
|
32
73
|
end
|
|
33
74
|
|
|
34
75
|
def find_host_and_name_by_ip(ip_address)
|
|
35
|
-
h =
|
|
36
|
-
[h.name, h]
|
|
76
|
+
h = find_hosts('ipv4addr' => ip_address).first
|
|
77
|
+
h.nil? ? [nil, nil] : [h.name, h]
|
|
37
78
|
end
|
|
38
79
|
|
|
39
80
|
def build_host(options)
|
|
@@ -41,12 +82,12 @@ module ::Proxy::DHCP::Infoblox
|
|
|
41
82
|
host.name = options[:hostname]
|
|
42
83
|
host.ipv4addr = options[:ip]
|
|
43
84
|
host.mac = options[:mac]
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
85
|
+
host.nextserver = options[:nextServer]
|
|
86
|
+
host.use_nextserver = true
|
|
87
|
+
host.bootfile = options[:filename]
|
|
88
|
+
host.use_bootfile = true
|
|
89
|
+
host.network_view = network_view
|
|
90
|
+
host.options = Proxy::DHCP::Infoblox::Plugin.settings.options
|
|
50
91
|
host
|
|
51
92
|
end
|
|
52
93
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module ::Proxy::DHCP::Infoblox
|
|
2
2
|
class GridRestart
|
|
3
|
-
MAX_ATTEMPTS =
|
|
3
|
+
MAX_ATTEMPTS = 5
|
|
4
4
|
|
|
5
5
|
include ::Proxy::Log
|
|
6
6
|
attr_reader :connection
|
|
@@ -10,21 +10,32 @@ module ::Proxy::DHCP::Infoblox
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def try_restart
|
|
13
|
-
logger.
|
|
13
|
+
logger.info 'Restarting Infoblox Grid'
|
|
14
14
|
|
|
15
|
+
delay = Proxy::DHCP::Infoblox::Plugin.settings.wait_after_restart.to_i
|
|
15
16
|
MAX_ATTEMPTS.times do |tries|
|
|
17
|
+
if restart
|
|
18
|
+
if delay > 0
|
|
19
|
+
logger.info "Starting post-restart delay of #{delay} seconds..."
|
|
20
|
+
sleep delay
|
|
21
|
+
logger.debug "Post-restart delay done"
|
|
22
|
+
end
|
|
23
|
+
return
|
|
24
|
+
end
|
|
16
25
|
sleep tries
|
|
17
|
-
return if restart
|
|
18
26
|
end
|
|
19
27
|
|
|
20
|
-
logger.
|
|
28
|
+
logger.warn 'Restarting Infoblox Grid failed, giving up'
|
|
21
29
|
false
|
|
22
30
|
end
|
|
23
31
|
|
|
32
|
+
private
|
|
33
|
+
|
|
24
34
|
def restart
|
|
25
35
|
(@grid ||= ::Infoblox::Grid.get(@connection).first).restartservices
|
|
26
36
|
true
|
|
27
37
|
rescue Exception => e
|
|
38
|
+
logger.warn "Error during Grid restart: #{e}"
|
|
28
39
|
false
|
|
29
40
|
end
|
|
30
41
|
end
|
|
@@ -3,45 +3,86 @@ require 'smart_proxy_dhcp_infoblox/network_address_range_regex_generator'
|
|
|
3
3
|
|
|
4
4
|
module ::Proxy::DHCP::Infoblox
|
|
5
5
|
class HostIpv4AddressCRUD < CommonCRUD
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
attr_reader :dns_view
|
|
7
|
+
|
|
8
|
+
def initialize(connection, dns_view, used_ips_search_type)
|
|
9
|
+
@memoized_hosts = []
|
|
8
10
|
@memoized_condition = nil
|
|
9
|
-
|
|
11
|
+
@dns_view = dns_view
|
|
12
|
+
super(connection, used_ips_search_type)
|
|
10
13
|
end
|
|
11
14
|
|
|
12
15
|
def all_hosts(subnet_address)
|
|
13
16
|
address_range_regex = NetworkAddressesRegularExpressionGenerator.new.generate_regex(subnet_address)
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
if @used_ips_search_type == 'used'
|
|
19
|
+
addresses = ::Infoblox::Ipv4address.find(
|
|
20
|
+
@connection,
|
|
21
|
+
'network' => subnet_address,
|
|
22
|
+
'status' => 'USED',
|
|
23
|
+
'_max_results' => 2147483646
|
|
24
|
+
)
|
|
25
|
+
hosts = addresses.map do |address|
|
|
26
|
+
if address.mac_address.nil? || address.mac_address.empty?
|
|
27
|
+
checked_mac = '00:00:00:00:00:00'
|
|
28
|
+
else
|
|
29
|
+
checked_mac = address.mac_address
|
|
30
|
+
end
|
|
31
|
+
::Infoblox::Host.new(
|
|
32
|
+
:name => address.names[0],
|
|
33
|
+
:ipv4addrs => [{ :name => address.names[0], :ipv4addr => address.ip_address, :mac => checked_mac,
|
|
34
|
+
:configure_for_dhcp => true }]
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
else
|
|
38
|
+
hosts = ::Infoblox::Host.find(
|
|
16
39
|
@connection,
|
|
17
40
|
'ipv4addr~' => address_range_regex,
|
|
18
|
-
'
|
|
41
|
+
'view' => dns_view,
|
|
42
|
+
'_max_results' => 2147483646
|
|
43
|
+
)
|
|
44
|
+
end
|
|
19
45
|
|
|
20
46
|
ip_addr_matcher = Regexp.new(address_range_regex) # pre-compile the regex
|
|
21
|
-
hosts.map
|
|
47
|
+
hosts.map do |host|
|
|
48
|
+
build_reservation(host.name, host.ipv4addrs.find { |ip| ip_addr_matcher =~ ip.ipv4addr }, subnet_address)
|
|
49
|
+
end.compact
|
|
22
50
|
end
|
|
23
51
|
|
|
24
52
|
def find_record_by_ip(subnet_address, ip_address)
|
|
25
|
-
found =
|
|
53
|
+
found = find_hosts('ipv4addr' => ip_address).first
|
|
26
54
|
return nil if found.nil?
|
|
27
|
-
|
|
55
|
+
|
|
56
|
+
build_reservation(found.name, found.ipv4addrs.find { |ip| ip.ipv4addr == ip_address }, subnet_address)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def find_records_by_ip(subnet_address, ip_address)
|
|
60
|
+
found = find_hosts({ 'ipv4addr' => ip_address }, 2147483646)
|
|
61
|
+
return [] if found.empty?
|
|
62
|
+
|
|
63
|
+
found.map do |record|
|
|
64
|
+
build_reservation(record.name, record.ipv4addrs.find { |ip| ip.ipv4addr == ip_address }, subnet_address)
|
|
65
|
+
end.compact
|
|
28
66
|
end
|
|
29
67
|
|
|
30
68
|
def find_record_by_mac(subnet_address, mac_address)
|
|
31
|
-
found =
|
|
69
|
+
found = find_hosts('mac' => mac_address).first
|
|
32
70
|
return nil if found.nil?
|
|
33
|
-
|
|
71
|
+
|
|
72
|
+
build_reservation(found.name, found.ipv4addrs.find { |ip| ip.mac == mac_address }, subnet_address)
|
|
34
73
|
end
|
|
35
74
|
|
|
36
75
|
def find_host_and_name_by_ip(ip_address)
|
|
37
|
-
h =
|
|
38
|
-
[h.name, h.ipv4addrs.find {|ip| ip.ipv4addr == ip_address}]
|
|
76
|
+
h = find_hosts('ipv4addr' => ip_address).first
|
|
77
|
+
h.nil? ? [nil, nil] : [h.name, h.ipv4addrs.find { |ip| ip.ipv4addr == ip_address }]
|
|
39
78
|
end
|
|
40
79
|
|
|
41
|
-
def
|
|
42
|
-
return @
|
|
80
|
+
def find_hosts(condition, max_results = 1)
|
|
81
|
+
return @memoized_hosts if (!@memoized_hosts.empty? && @memoized_condition == condition)
|
|
82
|
+
|
|
43
83
|
@memoized_condition = condition
|
|
44
|
-
@
|
|
84
|
+
@memoized_hosts = ::Infoblox::Host.find(@connection, condition.merge('view' => dns_view,
|
|
85
|
+
'_max_results' => max_results))
|
|
45
86
|
end
|
|
46
87
|
|
|
47
88
|
def build_host(options)
|
|
@@ -54,6 +95,7 @@ module ::Proxy::DHCP::Infoblox
|
|
|
54
95
|
host_addr.use_nextserver = true
|
|
55
96
|
host_addr.bootfile = options[:filename]
|
|
56
97
|
host_addr.use_bootfile = true
|
|
98
|
+
host.view = dns_view
|
|
57
99
|
host
|
|
58
100
|
end
|
|
59
101
|
end
|