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

Add the VRouter service #1

Merged
merged 2 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ packer-service_vnf: packer-alpine318 ${DIR_EXPORT}/service_vnf.qcow2
packer-service_wordpress: packer-alma8 ${DIR_EXPORT}/service_wordpress.qcow2
@${INFO} "Packer service_wordpress done"

packer-service_VRouter: packer-alpine318 ${DIR_EXPORT}/service_VRouter.qcow2
@${INFO} "Packer service_VRouter done"

packer-service_OneKE: packer-ubuntu2204 ${DIR_EXPORT}/service_OneKE.qcow2
@${INFO} "Packer service_OneKE done"

Expand Down
2 changes: 1 addition & 1 deletion Makefile.config
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ DISTROS := alma8 alma9 \
rocky8 rocky9 \
ubuntu2004 ubuntu2004min ubuntu2204 ubuntu2204min

SERVICES := service_vnf service_wordpress service_OneKE service_OneKEa
SERVICES := service_vnf service_wordpress service_VRouter service_OneKE service_OneKEa

.DEFAULT_GOAL := help

Expand Down
179 changes: 179 additions & 0 deletions appliances/VRouter/DHCP4/main.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
# frozen_string_literal: true

require 'json'
require_relative '../vrouter.rb'

module Service
module DHCP4
extend self

DEPENDS_ON = %w[Service::Failover]

ONEAPP_VNF_DHCP4_ENABLED = env :ONEAPP_VNF_DHCP4_ENABLED, 'NO'

ONEAPP_VNF_DHCP4_AUTHORITATIVE = env :ONEAPP_VNF_DHCP4_AUTHORITATIVE, 'YES'

ONEAPP_VNF_DHCP4_MAC2IP_ENABLED = env :ONEAPP_VNF_DHCP4_MAC2IP_ENABLED, 'YES'
ONEAPP_VNF_DHCP4_MAC2IP_MACPREFIX = env :ONEAPP_VNF_DHCP4_MAC2IP_MACPREFIX, '02:00'

ONEAPP_VNF_DHCP4_LEASE_TIME = env :ONEAPP_VNF_DHCP4_LEASE_TIME, '3600'

ONEAPP_VNF_DHCP4_GATEWAY = env :ONEAPP_VNF_DHCP4_GATEWAY, nil
ONEAPP_VNF_DHCP4_DNS = env :ONEAPP_VNF_DHCP4_DNS, nil

ONEAPP_VNF_DHCP4_INTERFACES = env :ONEAPP_VNF_DHCP4_INTERFACES, '' # nil -> none, empty -> all

def parse_env
@interfaces ||= parse_interfaces ONEAPP_VNF_DHCP4_INTERFACES
@mgmt ||= detect_mgmt_interfaces

interfaces = @interfaces.keys - @mgmt

@n2a ||= addrs_to_nics(interfaces, family: %w[inet]).to_h do |a, n|
[n.first, a]
end

@a2s ||= addrs_to_subnets(interfaces, family: %w[inet]).to_h do |a, s|
[a.split('/').first, s]
end

@s2r ||= subnets_to_ranges(@a2s.values)

interfaces.each_with_object({}) do |nic, vars|
p = env("ONEAPP_VNF_DHCP4_#{nic.upcase}", nil)&.split(':')&.map(&:strip)

vars[nic] = {
address: @n2a[nic],
subnet: if p.nil? then @a2s[@n2a[nic]] else p[0] end,
range: if p.nil? then @s2r[@a2s[@n2a[nic]]] else p[1] end,
gateway: env("ONEAPP_VNF_DHCP4_#{nic.upcase}_GATEWAY", ONEAPP_VNF_DHCP4_GATEWAY),
dns: env("ONEAPP_VNF_DHCP4_#{nic.upcase}_DNS", ONEAPP_VNF_DHCP4_DNS),
mtu: env("ONEAPP_VNF_DHCP4_#{nic.upcase}_MTU", ip_link_show(nic)['mtu']),
}
end
end

def install(initdir: '/etc/init.d')
msg :info, 'DHCP4::install'

onelease4_apk = File.join File.dirname(__FILE__), 'kea-hook-onelease4-1.1.1-r0.apk'

puts bash <<~SCRIPT
apk --no-cache add ruby kea-dhcp4
apk --no-cache --allow-untrusted add '#{onelease4_apk}'
SCRIPT

file "#{initdir}/one-dhcp4", <<~SERVICE, mode: 'u=rwx,g=rx,o='
#!/sbin/openrc-run

source /run/one-context/one_env

command="/usr/bin/ruby"
command_args="-r /etc/one-appliance/lib/helpers.rb -r #{__FILE__}"

output_log="/var/log/one-appliance/one-dhcp4.log"
error_log="/var/log/one-appliance/one-dhcp4.log"

depend() {
after net firewall keepalived
}

start_pre() {
rc-service kea-dhcp4 start --nodeps
}

start() { :; }

stop() { :; }

stop_post() {
rc-service kea-dhcp4 stop --nodeps
}
SERVICE

toggle [:update]
end

def configure(basedir: '/etc/kea')
msg :info, 'DHCP4::configure'

if ONEAPP_VNF_DHCP4_ENABLED
dhcp4_vars = parse_env

config = { 'Dhcp4' => {
'interfaces-config' => { 'interfaces' => dhcp4_vars.keys },
'authoritative' => ONEAPP_VNF_DHCP4_AUTHORITATIVE,
'option-data' => [],
'subnet4' => dhcp4_vars.map do |nic, vars|
data = []
data << { 'name' => 'routers', 'data' => vars[:gateway] } unless vars[:gateway].nil?
data << { 'name' => 'domain-name-servers', 'data' => vars[:dns] } unless vars[:dns].nil?
data << { 'name' => 'interface-mtu', 'data' => vars[:mtu].to_s } unless vars[:mtu].nil? || nic == 'lo'
{ 'subnet' => vars[:subnet],
'pools' => [ { 'pool' => vars[:range] } ],
'option-data' => data,
'reservations' => [
{ 'flex-id' => "'DO-NOT-LEASE-#{vars[:address]}'",
'ip-address' => vars[:address] } ],
'reservation-mode' => 'all' }
end,
'lease-database' => {
'type' => 'memfile',
'persist' => true,
'lfc-interval' => 2 * ONEAPP_VNF_DHCP4_LEASE_TIME.to_i
},
'sanity-checks' => { 'lease-checks' => 'fix-del' },
'valid-lifetime' => ONEAPP_VNF_DHCP4_LEASE_TIME.to_i,
'calculate-tee-times' => true,
'loggers' => [
{ 'name' => 'kea-dhcp4',
'output_options' => [ { 'output' => '/var/log/kea/kea-dhcp4.log' } ],
'severity' => 'INFO',
'debuglevel' => 0 }
],
'hooks-libraries' => if ONEAPP_VNF_DHCP4_MAC2IP_ENABLED then
[ { 'library' => '/usr/lib/kea/hooks/libkea-onelease-dhcp4.so',
'parameters' => {
'enabled' => true,
'byte-prefix' => ONEAPP_VNF_DHCP4_MAC2IP_MACPREFIX,
'logger-name' => 'onelease-dhcp4',
'debug' => false,
'debug-logfile' => '/var/log/kea/onelease-dhcp4-debug.log' } } ]
else [] end
} }

file "#{basedir}/kea-dhcp4.conf", JSON.pretty_generate(config), owner: 'kea',
group: 'kea',
mode: 'u=rw,g=r,o=',
overwrite: true
toggle [:enable]
else
toggle [:stop, :disable]
end
end

def toggle(operations)
operations.each do |op|
msg :debug, "DHCP4::toggle([:#{op}])"
case op
when :reload
puts bash 'rc-service kea-dhcp4 reload'
when :enable
puts bash 'rc-update add kea-dhcp4 default'
puts bash 'rc-update add one-dhcp4 default'
when :disable
puts bash 'rc-update del kea-dhcp4 default ||:'
puts bash 'rc-update del one-dhcp4 default ||:'
when :update
puts bash 'rc-update -u'
else
puts bash "rc-service one-dhcp4 #{op.to_s}"
end
end
end

def bootstrap
msg :info, 'DHCP4::bootstrap'
end
end
end
111 changes: 111 additions & 0 deletions appliances/VRouter/DHCP4/tests.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# frozen_string_literal: true

require 'rspec'

def clear_env
ENV.delete_if { |name| name.include?('VROUTER_') || name.include?('_VNF_') }
end

def clear_vars(object)
object.instance_variables.each { |name| object.remove_instance_variable(name) }
end

RSpec.describe self do
it 'should provide and parse all env vars' do
clear_env

ENV['ONEAPP_VNF_DHCP4_ENABLED'] = 'YES'
ENV['ONEAPP_VNF_DHCP4_AUTHORITATIVE'] = 'YES'

ENV['ONEAPP_VNF_DHCP4_MAC2IP_ENABLED'] = 'YES'
ENV['ONEAPP_VNF_DHCP4_MAC2IP_MACPREFIX'] = '02:00'

ENV['ONEAPP_VNF_DHCP4_LEASE_TIME'] = '3600'

ENV['ONEAPP_VNF_DHCP4_GATEWAY'] = '1.2.3.4'
ENV['ONEAPP_VNF_DHCP4_DNS'] = '1.1.1.1'

ENV['ONEAPP_VNF_DHCP4_INTERFACES'] = 'lo/127.0.0.1 eth0 eth1 eth2 eth3'
ENV['ETH0_VROUTER_MANAGEMENT'] = 'YES'

ENV['ONEAPP_VNF_DHCP4_ETH2'] = '30.0.0.0/8:30.40.50.64-30.40.50.68'
ENV['ONEAPP_VNF_DHCP4_ETH2_GATEWAY'] = '30.40.50.1'
ENV['ONEAPP_VNF_DHCP4_ETH2_DNS'] = '8.8.8.8'

ENV['ONEAPP_VNF_DHCP4_ETH3_GATEWAY'] = '40.50.60.1'
ENV['ONEAPP_VNF_DHCP4_ETH3_DNS'] = '8.8.4.4'

load './main.rb'; include Service::DHCP4

allow(Service::DHCP4).to receive(:ip_addr_list).and_return([
{ 'ifname' => 'lo',
'addr_info' => [ { 'family' => 'inet',
'local' => '127.0.0.1',
'prefixlen' => 8 } ] },

{ 'ifname' => 'eth0',
'addr_info' => [ { 'family' => 'inet',
'local' => '10.20.30.40',
'prefixlen' => 24 } ] },

{ 'ifname' => 'eth1',
'addr_info' => [ { 'family' => 'inet',
'local' => '20.30.40.50',
'prefixlen' => 16 } ] },

{ 'ifname' => 'eth2',
'addr_info' => [ { 'family' => 'inet',
'local' => '30.40.50.60',
'prefixlen' => 8 } ] },

{ 'ifname' => 'eth3',
'addr_info' => [ { 'family' => 'inet',
'local' => '40.50.60.70',
'prefixlen' => 24 } ] },
])

allow(Service::DHCP4).to receive(:ip_link_show).and_return(
{ 'mtu' => 1111 },
{ 'mtu' => 2222 },
{ 'mtu' => 3333 },
{ 'mtu' => 4444 },
)

clear_vars Service::DHCP4

expect(Service::DHCP4.parse_env).to eq ({
'lo' => {
address: '127.0.0.1',
dns: '1.1.1.1',
gateway: '1.2.3.4',
mtu: 1111,
range: '127.0.0.2-127.255.255.254',
subnet: '127.0.0.0/8',
},
'eth1' => {
address: '20.30.40.50',
dns: '1.1.1.1',
gateway: '1.2.3.4',
mtu: 2222,
range: '20.30.0.2-20.30.255.254',
subnet: '20.30.0.0/16',
},
'eth2' => {
address: '30.40.50.60',
dns: '8.8.8.8',
gateway: '30.40.50.1',
mtu: 3333,
range: '30.40.50.64-30.40.50.68',
subnet: '30.0.0.0/8',
},
'eth3' => {
address: '40.50.60.70',
dns: '8.8.4.4',
gateway: '40.50.60.1',
mtu: 4444,
range: '40.50.60.2-40.50.60.254',
subnet: '40.50.60.0/24',
},
})
end
end
Loading