Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #11081 - broke out dhcp providers into modules #312

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 8 additions & 21 deletions config/settings.d/dhcp.yml.example
Expand Up @@ -2,24 +2,11 @@
# Can be true, false, or http/https to enable just one of the protocols
:enabled: false

# valid vendors:
# - isc
# - native_ms (Microsoft native implementation)
# - virsh (simple implementation for libvirt)
#:dhcp_vendor: isc
#:dhcp_server: 127.0.0.1
#:dhcp_omapi_port: 7911
# dhcp_subnets is an ISC & Native MS implementation setting. It restricts the subnets queried to a
# subset, so as to reduce the query time.
#:dhcp_subnets: [192.168.205.0/255.255.255.128, 192.168.205.128/255.255.255.128]
# Settings for Ubuntu ISC
#:dhcp_config: /etc/dhcp3/dhcpd.conf
#:dhcp_leases: /var/lib/dhcp3/dhcpd.leases
# Settings for Redhat ISC
# Redhat 5
#:dhcp_config: /etc/dhcpd.conf
# Redhat 6
#:dhcp_config: /etc/dhcp/dhcpd.conf
#:dhcp_leases: /var/lib/dhcpd/dhcpd.leases
#:dhcp_key_name: secret_key_name
#:dhcp_key_secret: secret_key
# valid providers:
# - dhcp_isc (ISC dhcp server)
# - dhcp_native_ms (Microsoft native implementation)
# - dhcp_virsh (simple implementation for libvirt)
#:use_provider: dhcp_isc
#:server: 127.0.0.1
# subnets restricts the subnets queried to a subset, to reduce the query time.
#:subnets: [192.168.205.0/255.255.255.128, 192.168.205.128/255.255.255.128]
24 changes: 24 additions & 0 deletions config/settings.d/dhcp_isc.yml.example
@@ -0,0 +1,24 @@
---
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing "Configuration file for..." introduction.

#
# Configuration file for ISC dhcp provider
#

#:config: /etc/dhcp/dhcpd.conf
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The order in this file is muddled, this used to be under a "Redhat 6" (ugh) heading with the other OSes. I'd suggest some whitespace between the config/lease sections and key/secret sections would help make it more readable.

#:leases: /var/lib/dhcpd/dhcpd.leases
#
# Redhat 5
#
#:config: /etc/dhcpd.conf
#
# Settings for Ubuntu
#
#:config: /etc/dhcp3/dhcpd.conf
#:leases: /var/lib/dhcp3/dhcpd.leases

# Specifies TSIG key name and secret
#:key_name: secret_key_name
#:key_secret: secret_key

#:omapi_port: 7911
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick, just put a new line between the keys and omapi_port, as the port's not part of the TSIG config


# use :server setting in dhcp.yml if you are managing a dhcp server which is not localhost
6 changes: 6 additions & 0 deletions config/settings.d/dhcp_ms_native.yml.example
@@ -0,0 +1,6 @@
---
#
# Configuration file for Windows-specific 'netsh' dhcp provider
#
# There's currently no configuration options for this provider.
# use :server setting in dhcp.yml if you are managing a dhcp server which is not localhost
8 changes: 8 additions & 0 deletions config/settings.d/dhcp_virsh.yml.example
@@ -0,0 +1,8 @@
---
#
# Configuration file for libvirtd-specific 'virsh' dhcp provider
#
# There's currently no configuration options for this provider.
# Virsh network name is a global parameter that can be set
# in the main settings.yml file in 'virsh_network' parameter.
#
69 changes: 69 additions & 0 deletions extra/migrations/20150826000000_migrate_dhcp_settings.rb
@@ -0,0 +1,69 @@
require 'yaml'

class MigrateDhcpSettings < ::Proxy::Migration
KNOWN_PARAMETERS = {
:enabled => [:dhcp, :enabled],
:dhcp_vendor => [:dhcp, :use_provider, :old_provider_name_to_new],
:dhcp_subnets => [:dhcp, :subnets],
:dhcp_config => [:dhcp_isc, :config],
:dhcp_leases => [:dhcp_isc, :leases],
:dhcp_key_name => [:dhcp_isc, :key_name],
:dhcp_key_secret => [:dhcp_isc, :key_secret],
:dhcp_omapi_port => [:dhcp_isc, :omapi_port],
:dhcp_server => [:dhcp, :server]
}

def remap_parameter(aparameter, avalue)
module_name, parameter_name, converter =
KNOWN_PARAMETERS.has_key?(aparameter) ? KNOWN_PARAMETERS[aparameter] : [:unknown, aparameter]

converter.nil? ? [module_name, parameter_name, avalue] : [module_name, parameter_name, send(converter, avalue)]
end

def migrate
dhcp_config = path(src_dir, "settings.d", "dhcp.yml")
if !File.exist?(dhcp_config)
duplicate_original_configuration
return
end

to_migrate = YAML.load_file(dhcp_config)
output = migrate_dhcp_configuration(to_migrate)
copy_original_configuration_except(path("settings.d", "dhcp.yml"))
write_to_files(output)
end

def old_provider_name_to_new(aname)
if ['isc', 'native_ms', 'virsh'].include?(aname)
'dhcp_' + aname
else
aname
end
end

def migrate_dhcp_configuration(to_migrate)
migrated = Hash.new { |h,k| h[k] = Hash.new }
to_migrate.each do |option, value|
module_name, parameter_name, parameter_value = remap_parameter(option, value)
migrated[module_name][parameter_name] = parameter_value
end
migrated
end

def write_to_files(output)
output.keys.each do |m|
next if output[m].empty? || m == :unknown
File.open(path(dst_dir, "settings.d", "#{m}.yml"),'w') do |f|
f.write(strip_ruby_symbol_encoding(output[m].to_yaml))
if (m == :dhcp) && !output[:unknown].empty?
f.write "\n# Unparsed options, please review\n"
f.write(strip_ruby_symbol_encoding(output[:unknown].to_yaml).gsub(/^---/,''))
end
end
end
end

def strip_ruby_symbol_encoding(astring)
astring.gsub("!ruby/symbol ", ":").gsub("!ruby/sym ", ":")
end
end
2 changes: 1 addition & 1 deletion lib/proxy/provider.rb
Expand Up @@ -3,7 +3,7 @@ class ::Proxy::Provider
include ::Proxy::Log

class << self
attr_reader :provider_factory_proc
attr_reader :provider_factory

def plugin(plugin_name, aversion, attrs = {})
@plugin_name = plugin_name.to_sym
Expand Down
5 changes: 3 additions & 2 deletions lib/proxy/provider_factory.rb
@@ -1,8 +1,9 @@
class ::Proxy::ProviderFactory
class << self
def get_provider(provider_name, opts)
def get_provider(provider_name, opts = {})
provider = ::Proxy::Plugins.find_provider(provider_name.to_sym)
provider.provider_factory.call(opts)
pf = provider.provider_factory
pf.is_a?(Proc) ? pf.call(opts) : pf.new.get_provider(opts)
end
end
end
3 changes: 2 additions & 1 deletion lib/proxy/settings/global.rb
Expand Up @@ -8,7 +8,8 @@ class Global < ::OpenStruct
:daemon => false,
:daemon_pid => "/var/run/foreman-proxy/foreman-proxy.pid",
:forward_verify => true,
:bind_host => "*"
:bind_host => "*",
:virsh_network => 'default'
}

HOW_TO_NORMALIZE = {
Expand Down
3 changes: 3 additions & 0 deletions lib/smart_proxy_main.rb
Expand Up @@ -62,6 +62,9 @@ module Proxy
require 'templates/templates'
require 'tftp/tftp'
require 'dhcp/dhcp'
require 'dhcp_isc/dhcp_isc'
require 'dhcp_native_ms/dhcp_native_ms'
require 'dhcp_virsh/dhcp_virsh'
require 'puppetca/puppetca'
require 'puppet_proxy/puppet'
require 'bmc/bmc'
Expand Down
27 changes: 0 additions & 27 deletions modules/dhcp/dhcp.rb
@@ -1,28 +1 @@
require 'dhcp/dhcp_plugin'

module Proxy::DHCP
Standard = {
:hostname => {:code => 12, :kind => "String" }, # The host's name
:PXEClient => {:code => 60, :kind => "String" }, # Needs to be empty for foreman to function
:nextServer => {:code => 66, :kind => "String" }, # From where we download the pxeboot image via TFTP
:filename => {:code => 67, :kind => "String" } # The pxeboot image
}
SUNW = {
:root_server_ip => {:code => 2, :kind => "IPAddress" }, # 192.168.216.241
:root_server_hostname => {:code => 3, :kind => "String" }, # mediahost
:root_path_name => {:code => 4, :kind => "String" }, # /vol/solgi_5.10/sol10_hw0910/Solaris_10/Tools/Boot
:install_server_ip => {:code => 10, :kind => "IPAddress" }, # 192.168.216.241
:install_server_name => {:code => 11, :kind => "String" }, # mediahost
:install_path => {:code => 12, :kind => "String" }, # /vol/solgi_5.10/sol10_hw0910
:sysid_server_path => {:code => 13, :kind => "String" }, # 192.168.216.241:/vol/jumpstart/sysidcfg/sysidcfg_primary
:jumpstart_server_path => {:code => 14, :kind => "String" } # 192.168.216.241:/vol/jumpstart
}
class Error < RuntimeError; end
class Collision < RuntimeError; end
class InvalidRecord < RuntimeError; end
class AlreadyExists < RuntimeError; end

def kind
self.class.to_s.sub("Proxy::DHCP::","").downcase
end
end
45 changes: 15 additions & 30 deletions modules/dhcp/dhcp_api.rb
@@ -1,45 +1,30 @@
class Proxy::DhcpApi < ::Sinatra::Base
extend Proxy::DHCP::DependencyInjection::Injectors

helpers ::Proxy::Helpers
authorize_with_trusted_hosts
authorize_with_ssl_client
use Rack::MethodOverride

inject_attr :dhcp_provider, :server

before do
begin
raise "Smart Proxy is not configured to support DHCP" unless Proxy::DhcpPlugin.settings.enabled
case Proxy::DhcpPlugin.settings.dhcp_vendor.downcase
when "isc"
require 'dhcp/providers/server/isc'
unless Proxy::DhcpPlugin.settings.dhcp_config && Proxy::DhcpPlugin.settings.dhcp_leases \
&& File.exist?(Proxy::DhcpPlugin.settings.dhcp_config) && File.exist?(Proxy::DhcpPlugin.settings.dhcp_leases)
log_halt 400, "Unable to find the DHCP configuration or lease files"
end
@server = Proxy::DHCP::ISC.instance_with_default_parameters
when "native_ms"
require 'dhcp/providers/server/native_ms'
@server = Proxy::DHCP::NativeMS.instance_with_default_parameters
when "virsh"
require 'dhcp/providers/server/virsh'
@server = Proxy::DHCP::Virsh.instance_with_default_parameters
else
log_halt 400, "Unrecognized or missing DHCP vendor type: #{Proxy::DhcpPlugin.settings.dhcp_vendor.nil? ? 'MISSING' : Proxy::DhcpPlugin.settings.dhcp_vendor}"
end

@server.loadSubnets
server.load_subnets
rescue => e
log_halt 400, e
end
end

helpers do
def load_subnet
@subnet = @server.find_subnet(params[:network])
@subnet = server.find_subnet(params[:network])
log_halt 404, "Subnet #{params[:network]} not found" unless @subnet
@subnet
end

def load_subnet_data
@server.loadSubnetData(@subnet)
server.load_subnet_data(@subnet)
end
end

Expand All @@ -48,8 +33,8 @@ def load_subnet_data
if request.accept? 'application/json'
content_type :json

log_halt 404, "No subnets found on server @{name}" unless @server.subnets
@server.subnets.map{|s| {:network => s.network, :netmask => s.netmask, :options => s.options}}.to_json
log_halt 404, "No subnets found on server @{name}" unless server.subnets
server.subnets.map{|s| {:network => s.network, :netmask => s.netmask, :options => s.options}}.to_json
else
erb :"dhcp/index"
end
Expand All @@ -65,7 +50,7 @@ def load_subnet_data

if request.accept? 'application/json'
content_type :json
{:reservations => @server.all_hosts(@subnet.network), :leases => @server.all_leases(@subnet.network)}.to_json
{:reservations => server.all_hosts(@subnet.network), :leases => server.all_leases(@subnet.network)}.to_json
else
erb :"dhcp/show"
end
Expand All @@ -81,7 +66,7 @@ def load_subnet_data
load_subnet
load_subnet_data

({:ip => @server.unused_ip(@subnet, params[:mac], params[:from], params[:to])}).to_json
({:ip => server.unused_ip(@subnet, params[:mac], params[:from], params[:to])}).to_json
rescue => e
log_halt 400, e
end
Expand All @@ -94,7 +79,7 @@ def load_subnet_data
load_subnet
load_subnet_data

record = @server.find_record(@subnet.network, params[:record])
record = server.find_record(@subnet.network, params[:record])
log_halt 404, "Record #{params[:network]}/#{params[:record]} not found" unless record
record.options.to_json
rescue => e
Expand All @@ -109,7 +94,7 @@ def load_subnet_data
load_subnet_data

content_type :json
@server.addRecord(params)
server.add_record(params)
rescue Proxy::DHCP::Collision => e
log_halt 409, e
rescue Proxy::DHCP::AlreadyExists # rubocop:disable Lint/HandleExceptions
Expand All @@ -125,9 +110,9 @@ def load_subnet_data
load_subnet
load_subnet_data

record = @server.find_record(@subnet.network, params[:record])
record = server.find_record(@subnet.network, params[:record])
log_halt 404, "Record #{params[:network]}/#{params[:record]} not found" unless record
@server.delRecord @subnet, record
server.del_record @subnet, record
if request.accept? 'application/json'
content_type :json
{}
Expand Down
8 changes: 7 additions & 1 deletion modules/dhcp/dhcp_plugin.rb
Expand Up @@ -2,6 +2,12 @@ class Proxy::DhcpPlugin < ::Proxy::Plugin
http_rackup_path File.expand_path("http_config.ru", File.expand_path("../", __FILE__))
https_rackup_path File.expand_path("http_config.ru", File.expand_path("../", __FILE__))

default_settings :dhcp_provider => 'isc', :dhcp_server => '127.0.0.1', :dhcp_omapi_port => '7911'
uses_provider
default_settings :use_provider => 'dhcp_isc', :server => '127.0.0.1'
plugin :dhcp, ::Proxy::VERSION

after_activation do
require 'dhcp_common/dependency_injection/container'
require 'dhcp/dhcp_api'
end
end