diff --git a/Berksfile b/Berksfile index 7144c7c..4e08be1 100644 --- a/Berksfile +++ b/Berksfile @@ -4,6 +4,7 @@ site :opscode cookbook "apt" cookbook "minitest-handler" +cookbook "network_interfaces" def own_cookbook(name,opts={}) opts = { path: "site-cookbooks/#{name}"}.merge!(opts) @@ -14,3 +15,4 @@ own_cookbook "dhcp" own_cookbook "bind" own_cookbook "ntp" own_cookbook "main" +own_cookbook "lctp-network" diff --git a/nodes/node0.json b/nodes/node0.json index 6f2bf94..15b85aa 100644 --- a/nodes/node0.json +++ b/nodes/node0.json @@ -1,25 +1,32 @@ { - "main": { - "head_node": { - "internal_ip": "172.28.128.1" + "lctp_network" : { + "domain_servers": ["127.0.0.1"], + "search_domains": ["lctp"], + "interfaces": { + "eth0": { }, + "eth1": { + "static_ip": "172.28.128.1", + "netmask": "255.255.255.0" + } } }, "dhcp" : { "domain": { - "name": "lctp", - "server": "node0.lctp" + "names": ["lctp"], + "servers": ["172.28.128.1"] }, - "interface": "eth1", + "ntp_servers": ["172.28.128.1"], + "interfaces": ["eth1"], "subnet": { - "gateway": "node0.lctp", + "gateway": "172.28.128.1", "prefix": "172.28.128.0", "netmask": "255.255.255.0" }, - "hosts": [{ - "name": "node1", - "mac": "5c:a1:ab:1e:00:01", - "ip": "172.28.128.101" - }] + "hosts": { + "node1": { + "mac": "5c:a1:ab:1e:00:02" + } + } }, "ntp" : { "subnets": ["::1", "127.0.0.1", "172.28.128.0/24"] diff --git a/nodes/node1.json b/nodes/node1.json index 0967ef4..714fd87 100644 --- a/nodes/node1.json +++ b/nodes/node1.json @@ -1 +1,8 @@ -{} +{ + "lctp_network": { + "interfaces": { + "eth0": { "metric": 100 }, + "eth1": { "metric": 50 } + } + } +} diff --git a/site-cookbooks/dhcp/attributes/default.rb b/site-cookbooks/dhcp/attributes/default.rb index b6c4b2b..5f42eab 100644 --- a/site-cookbooks/dhcp/attributes/default.rb +++ b/site-cookbooks/dhcp/attributes/default.rb @@ -1,7 +1,8 @@ -default.dhcp.domain.name = "privat" -default.dhcp.domain.server = "ns.privat" -default.dhcp.hosts = [] -default.dhcp.interface = "eth0" +default.dhcp.domain.names = [] +default.dhcp.domain.servers = [] +default.dhcp.ntp_servers = [] +default.dhcp.hosts = {} +default.dhcp.interfaces = ["eth0"] default.dhcp.subnet.prefix = "192.168.2.0" default.dhcp.subnet.netmask = "255.255.255.0" default.dhcp.subnet.gateway = "192.168.2.1" diff --git a/site-cookbooks/dhcp/templates/default/dhcpd.conf.erb b/site-cookbooks/dhcp/templates/default/dhcpd.conf.erb index 535b464..7a0020b 100644 --- a/site-cookbooks/dhcp/templates/default/dhcpd.conf.erb +++ b/site-cookbooks/dhcp/templates/default/dhcpd.conf.erb @@ -1,18 +1,29 @@ # dhcpd.conf for <%= @node.name %> managed by Chef. Changes will be overwritten. default-lease-time 600; max-lease-time 7200; -# option definitions common to all supported networks... -option domain-name <%= @node.dhcp.domain.name %>; -option domain-name-servers <%= @node.dhcp.domain.server %>; + +<% if @node.dhcp.domain.names.size > 0 %> +option domain-name <%= @node.dhcp.domain.names.join(" ") %>; +<% end %> +<% if @node.dhcp.domain.servers.size > 0 %> +option domain-name-servers <%= @node.dhcp.domain.servers.join(" ") %>; +<% end %> +<% if @node.dhcp.ntp_servers.size > 0 %> +option ntp-servers <%= @node.dhcp.ntp_servers.join(" ") %>; +<% end %> subnet <%= @node.dhcp.subnet.prefix %> netmask <%= @node.dhcp.subnet.netmask%> { option routers <%= @node.dhcp.subnet.gateway%>; } -<% @node.dhcp.hosts.each do |host| -%> -host <%= host.name %> { +<% @node.dhcp.hosts.each do |name, host| -%> +host <%= name %> { hardware ethernet <%= host.mac %>; - fixed-address <%= "#{host.name}.#{@node.dhcp.domain.name}" %>; + <% if host.attribute?("ip") %> + fixed-address <%= "#{host.ip}" %>; + <% else %> + fixed-address <%= "#{name}.#{@node.dhcp.domain.names.first}" %>; + <% end %> use-host-decl-names true; } <% end -%> diff --git a/site-cookbooks/dhcp/templates/default/isc-dhcp-server.erb b/site-cookbooks/dhcp/templates/default/isc-dhcp-server.erb index cbc1fc2..f78e099 100644 --- a/site-cookbooks/dhcp/templates/default/isc-dhcp-server.erb +++ b/site-cookbooks/dhcp/templates/default/isc-dhcp-server.erb @@ -1,2 +1,2 @@ # /etc/default/isc-dhcp-server for <%= @node.name %> managed by Chef. Changes will be overwritten. -INTERFACES="<%= @node.dhcp.interface %>" +INTERFACES="<%= @node.dhcp.interfaces.join(" ") %>" diff --git a/site-cookbooks/lctp-network/attributes/default.rb b/site-cookbooks/lctp-network/attributes/default.rb new file mode 100644 index 0000000..169eb11 --- /dev/null +++ b/site-cookbooks/lctp-network/attributes/default.rb @@ -0,0 +1,3 @@ +default.lctp_network.interfaces = {} +default.lctp_network.domain_servers = [] +default.lctp_network.search_domains = [] diff --git a/site-cookbooks/lctp-network/attributes/router.rb b/site-cookbooks/lctp-network/attributes/router.rb new file mode 100644 index 0000000..7640ab6 --- /dev/null +++ b/site-cookbooks/lctp-network/attributes/router.rb @@ -0,0 +1 @@ +default.lctp_network.gateway_device = "eth0" diff --git a/site-cookbooks/lctp-network/files/default/interfaces b/site-cookbooks/lctp-network/files/default/interfaces new file mode 100644 index 0000000..c3ddbb7 --- /dev/null +++ b/site-cookbooks/lctp-network/files/default/interfaces @@ -0,0 +1,9 @@ +# Interfaces managed by Chef. Changes will be overwritten. +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). + +# The loopback network interface +auto lo +iface lo inet loopback + +source /etc/network/interfaces.d/* diff --git a/site-cookbooks/lctp-network/files/default/iptables-load b/site-cookbooks/lctp-network/files/default/iptables-load new file mode 100644 index 0000000..43b9ff3 --- /dev/null +++ b/site-cookbooks/lctp-network/files/default/iptables-load @@ -0,0 +1,4 @@ +#!/bin/sh +# iptables-load managed by Chef. Changes will be overwritten. +iptables-restore < /etc/iptables.rules +exit 0 diff --git a/site-cookbooks/lctp-network/files/default/iptables-save b/site-cookbooks/lctp-network/files/default/iptables-save new file mode 100644 index 0000000..9734a51 --- /dev/null +++ b/site-cookbooks/lctp-network/files/default/iptables-save @@ -0,0 +1,7 @@ +#!/bin/sh +# iptables-save managed by Chef. Changes will be overwritten. +iptables-save -c > /etc/iptables.rules +if [ -f /etc/iptables.downrules ]; then + iptables-restore < /etc/iptables.downrules +fi +exit 0 diff --git a/site-cookbooks/lctp-network/files/default/test/default_test.rb b/site-cookbooks/lctp-network/files/default/test/default_test.rb new file mode 100644 index 0000000..8d4484c --- /dev/null +++ b/site-cookbooks/lctp-network/files/default/test/default_test.rb @@ -0,0 +1,15 @@ +require 'minitest/spec' + +describe_recipe 'lctp-network::default' do + it "assign a ip for every device" do + node.lctp_network.interfaces.keys.each do |interface| + assert_sh("ifconfig #{interface} | grep -q 'inet addr'") + end + end + it "should be able to resolve dns" do + assert_sh("host examples.com") + end + it "should be able to reach the internet" do + assert_sh("ping -c 1 examples.com") + end +end diff --git a/site-cookbooks/lctp-network/files/default/test/router_test.rb b/site-cookbooks/lctp-network/files/default/test/router_test.rb new file mode 100644 index 0000000..ee59fe3 --- /dev/null +++ b/site-cookbooks/lctp-network/files/default/test/router_test.rb @@ -0,0 +1,7 @@ +require 'minitest/spec' + +describe_recipe 'lctp-network::default' do + it "starts the named daemon" do + assert_sh("iptables -L -t nat | grep -q MASQUERADE") + end +end diff --git a/site-cookbooks/lctp-network/metadata.rb b/site-cookbooks/lctp-network/metadata.rb new file mode 100644 index 0000000..063a676 --- /dev/null +++ b/site-cookbooks/lctp-network/metadata.rb @@ -0,0 +1,3 @@ +name "lctp-network" +depends "network_interfaces" +depends "modules" diff --git a/site-cookbooks/lctp-network/recipes/default.rb b/site-cookbooks/lctp-network/recipes/default.rb new file mode 100644 index 0000000..61af3ac --- /dev/null +++ b/site-cookbooks/lctp-network/recipes/default.rb @@ -0,0 +1,44 @@ +include_recipe "network_interfaces" + +package "ifmetric" + +cookbook_file "/etc/network/interfaces" do + source "interfaces" + mode 0644 + owner "root" + group "root" +end + +network = node.lctp_network + +unless network.domain_servers.empty? and network.search_domains.empty? + file "/etc/dhcp/dhclient-enter-hooks.d/resolvconf" do + action :delete + end + template "/etc/resolv.conf" do + source "resolv.conf.erb" + variables(network: network) + end +end + +network.interfaces.each do |device, iface| + network_interfaces device do + if iface.attribute? "metric" + metric iface.metric + end + + if iface.attribute? "static_ip" + target iface.static_ip + + if iface.attribute? "netmask" + mask iface.netmask + else + mask "255.255.255.0" + end + + bootproto "static" + else + bootproto "dhcp" + end + end +end diff --git a/site-cookbooks/lctp-network/recipes/router.rb b/site-cookbooks/lctp-network/recipes/router.rb new file mode 100644 index 0000000..64469fe --- /dev/null +++ b/site-cookbooks/lctp-network/recipes/router.rb @@ -0,0 +1,38 @@ +execute "iptables-load" do + action :nothing + command "/etc/network/if-pre-up.d/iptables-load" +end + +template "/etc/iptables.rules" do + source "iptables.rules.erb" + mode 0644 + owner "root" + group "root" +end + +modules "iptable_nat" +modules "ipt_MASQUERADE" + +execute "enable ip_forward" do + command "sysctl -w net.ipv4.ip_forward=1" +end + +file "/etc/sysctl.d/10-ip-forwarding.conf" do + mode "0644" + content "net.ipv4.ip_forward = 1" +end + +cookbook_file "/etc/network/if-pre-up.d/iptables-load" do + source "iptables-load" + mode 0755 + owner "root" + group "root" + notifies :run, "execute[iptables-load]" +end + +cookbook_file "/etc/network/if-post-down.d/iptables-save" do + source "iptables-save" + mode 0755 + owner "root" + group "root" +end diff --git a/site-cookbooks/lctp-network/templates/default/iptables.rules.erb b/site-cookbooks/lctp-network/templates/default/iptables.rules.erb new file mode 100644 index 0000000..bcbe859 --- /dev/null +++ b/site-cookbooks/lctp-network/templates/default/iptables.rules.erb @@ -0,0 +1,10 @@ +# iptables.rules for <%= @node.name %> managed by Chef. Changes will be overwritten. +*nat +:PREROUTING ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] + +# masquerading (NAT) +-A POSTROUTING -o <%= @node.lctp_network.gateway_device %> -j MASQUERADE + +COMMIT diff --git a/site-cookbooks/lctp-network/templates/default/resolv.conf.erb b/site-cookbooks/lctp-network/templates/default/resolv.conf.erb new file mode 100644 index 0000000..c05128c --- /dev/null +++ b/site-cookbooks/lctp-network/templates/default/resolv.conf.erb @@ -0,0 +1,5 @@ +# resolv.conf for <%= @node.name %> managed by Chef. Changes will be overwritten. +<% @network.domain_servers.each do |server| -%> +nameserver <%= server %> +<% end -%> +search <%= @network.search_domains.join(" ") %> diff --git a/site-cookbooks/main/attributes/head_node.rb b/site-cookbooks/main/attributes/head_node.rb deleted file mode 100644 index ff15daa..0000000 --- a/site-cookbooks/main/attributes/head_node.rb +++ /dev/null @@ -1,2 +0,0 @@ -default.main.head_node.internal_ip = "192.168.2.1" -default.main.head_node.internal_network_device = "eth1" diff --git a/site-cookbooks/main/metadata.rb b/site-cookbooks/main/metadata.rb index aa24c22..edc215a 100644 --- a/site-cookbooks/main/metadata.rb +++ b/site-cookbooks/main/metadata.rb @@ -3,4 +3,5 @@ depends "apt" depends "ntp" depends "dhcp" depends "bind" +depends "lctp-network" depends "minitest-handler" diff --git a/site-cookbooks/main/recipes/compute_node.rb b/site-cookbooks/main/recipes/compute_node.rb index b7937de..f617641 100644 --- a/site-cookbooks/main/recipes/compute_node.rb +++ b/site-cookbooks/main/recipes/compute_node.rb @@ -1,3 +1,4 @@ include_recipe "minitest-handler" +include_recipe "lctp-network" include_recipe "apt" include_recipe "ntp" diff --git a/site-cookbooks/main/recipes/head_node.rb b/site-cookbooks/main/recipes/head_node.rb index 30f5226..86f4d0c 100644 --- a/site-cookbooks/main/recipes/head_node.rb +++ b/site-cookbooks/main/recipes/head_node.rb @@ -1,11 +1,7 @@ include_recipe "minitest-handler" +include_recipe "lctp-network" +include_recipe "lctp-network::router" include_recipe "apt" include_recipe "ntp" include_recipe "bind" - -ifconfig node.main.head_node.internal_ip do - provider Chef::Provider::Ifconfig::Debian - device node.main.head_node.internal_network_device -end - include_recipe "dhcp" diff --git a/spec/coobooks/dhcp_spec.rb b/spec/coobooks/dhcp_spec.rb index 31c34e4..c1b4cea 100644 --- a/spec/coobooks/dhcp_spec.rb +++ b/spec/coobooks/dhcp_spec.rb @@ -3,11 +3,24 @@ require_relative '../spec_helper' describe 'dhcp::default' do let(:chef_run) do ChefSpec::Runner.new do |node| - node.set["dhcp"]["hosts"] =[{ - name: "node0", - mac: "5c:a1:ab:1e:00:01", - ip: "172.28.128.101" - }] + node.set["dhcp"] ={ + domain: { + names: ["foo"], + servers: ["node0.foo"] + }, + ntp_servers: ["foo.lctp"], + interfaces: ["eth1"], + subnet: { + gateway: "172.28.128.1", + prefix: "172.28.128.0", + netmask: "255.255.255.0" + }, + hosts: { + node1: { + mac: "5c:a1:ab:1e:00:02" + } + } + } end.converge(described_recipe) end diff --git a/spec/coobooks/lctp-network_spec.rb b/spec/coobooks/lctp-network_spec.rb new file mode 100644 index 0000000..73efddc --- /dev/null +++ b/spec/coobooks/lctp-network_spec.rb @@ -0,0 +1,42 @@ +require_relative '../spec_helper' + +describe 'lctp-network::default' do + let(:chef_run) do + ChefSpec::Runner.new do |node| + node.set["lctp_network"] = { + domain_servers: ["127.0.0.1"], + search_domains: ["lctp"], + interfaces: { + eth0: { }, + eth1: { + static_ip: "10.0.0.1" + } + } + } + end.converge(described_recipe) + end + it "should include cookbooks" do + chef_run.should render_file("/etc/network/interfaces") + chef_run.should render_file("/etc/resolv.conf"). + with_content("127.0.0.1").with_content("lctp") + + eth0 = chef_run.find_resource(:network_interfaces, "eth0") + eth0.should_not == nil + eth0.bootproto.should == "dhcp" + + eth1 = chef_run.find_resource(:network_interfaces, "eth1") + eth1.should_not == nil + eth1.bootproto.should == "static" + eth1.target.should == "10.0.0.1" + eth1.mask.should == "255.255.255.0" # default netmask + end +end + +describe 'lctp-network::router' do + let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) } + it "should setup NAT" do + chef_run.should render_file("/etc/network/if-pre-up.d/iptables-load") + chef_run.should render_file("/etc/network/if-post-down.d/iptables-save") + chef_run.should render_file("/etc/iptables.rules").with_content("eth0") + end +end diff --git a/spec/coobooks/main_spec.rb b/spec/coobooks/main_spec.rb index cc33851..06aa58b 100644 --- a/spec/coobooks/main_spec.rb +++ b/spec/coobooks/main_spec.rb @@ -3,18 +3,11 @@ require_relative '../spec_helper' describe 'main::head_node' do let(:chef_run) do ChefSpec::Runner.new do |node| - node.set["main"] = { - head_node: { - internal_ip: "10.10.1.1", - internal_network_device: "10.10.1.1" - } - } end.converge(described_recipe) end it "should include cookbooks" do - chef_run.should include_recipe('ntp') - chef_run.should include_recipe('bind') - chef_run.should include_recipe('dhcp') + cookbooks = %w{minitest-handler apt ntp lctp-network lctp-network::router bind dhcp} + cookbooks.each { |cookbook| chef_run.should include_recipe(cookbook) } end end @@ -24,7 +17,7 @@ describe 'main::compute_node' do end.converge(described_recipe) end it "should include cookbooks" do - chef_run.should include_recipe('apt') - chef_run.should include_recipe('ntp') + cookbooks = %w{minitest-handler apt ntp lctp-network} + cookbooks.each { |cookbook| chef_run.should include_recipe(cookbook) } end end