Commit 57ea5789eb144ce1a18060230e5a4eed0585fb80

Authored by Antonio Terceiro
1 parent c574e691

Support using lxc containers

Not everything works yet, but one can bring an environment up and use
it.
1 /utils/obs/isv* 1 /utils/obs/isv*
2 /Gemfile.lock 2 /Gemfile.lock
3 /config/local/ssh_config 3 /config/local/ssh_config
  4 +/config/lxc/
4 /.tmp 5 /.tmp
5 /tmp 6 /tmp
6 /docs/_build 7 /docs/_build
  1 +require 'yaml'
  2 +
1 begin 3 begin
2 load 'local.rake' 4 load 'local.rake'
3 rescue LoadError 5 rescue LoadError
@@ -13,15 +15,40 @@ iptables_file = "config/#{$SPB_ENV}/iptables-filter-rules" @@ -13,15 +15,40 @@ iptables_file = "config/#{$SPB_ENV}/iptables-filter-rules"
13 15
14 ENV['CHAKE_SSH_CONFIG'] = ssh_config_file 16 ENV['CHAKE_SSH_CONFIG'] = ssh_config_file
15 17
  18 +if $SPB_ENV == 'lxc'
  19 + system("mkdir -p config/lxc; sudo lxc-ls -f -F name,ipv4 | sed -e '/^softwarepublico/ !d; s/softwarepublico_//; s/_[0-9_]*/:/ ' > #{ips_file}.new")
  20 + begin
  21 + ips = YAML.load_file("#{ips_file}.new")
  22 + raise ArgumentError unless ips.is_a?(Hash)
  23 + FileUtils.mv ips_file + '.new', ips_file
  24 + rescue Exception => ex
  25 + puts ex.message
  26 + puts
  27 + puts "Q: did you boot the containers first?"
  28 + exit
  29 + end
  30 + config = YAML.load_file('config/local/config.yaml')
  31 + config['external_ip'] = ips['reverseproxy']
  32 + config['relay_ip'] = ips['email']
  33 + File.open(config_file, 'w') do |f|
  34 + f.puts(YAML.dump(config))
  35 + end
  36 +
  37 + File.open('config/lxc/iptables-filter-rules', 'w') do |f|
  38 + lxc_host_bridge_ip = '192.168.122.1' # FIXME don't hardcode
  39 + f.puts "-A INPUT -s #{lxc_host_bridge_ip} -p tcp -m state --state NEW --dport 22 -j ACCEPT"
  40 + end
  41 +end
  42 +
16 require 'chake' 43 require 'chake'
17 44
18 if Chake::VERSION < '0.4.3' 45 if Chake::VERSION < '0.4.3'
19 fail "Please upgrade to chake 0.4.3+" 46 fail "Please upgrade to chake 0.4.3+"
20 end 47 end
21 48
22 -config = YAML.load_file(config_file)  
23 -ips = YAML.load_file(ips_file)  
24 -firewall = File.open(iptables_file).read 49 +ips ||= YAML.load_file(ips_file)
  50 +config ||= YAML.load_file(config_file)
  51 +firewall ||= File.open(iptables_file).read
25 $nodes.each do |node| 52 $nodes.each do |node|
26 node.data['config'] = config 53 node.data['config'] = config
27 node.data['peers'] = ips 54 node.data['peers'] = ips
@@ -38,13 +65,15 @@ task :test do @@ -38,13 +65,15 @@ task :test do
38 end 65 end
39 66
40 file 'ssh_config.erb' 67 file 'ssh_config.erb'
41 -file 'config/local/ssh_config' => ['nodes.yaml', 'config/local/ips.yaml', 'ssh_config.erb', 'Rakefile'] do |t|  
42 - require 'erb'  
43 - template = ERB.new(File.read('ssh_config.erb'))  
44 - File.open(t.name, 'w') do |f|  
45 - f.write(template.result(binding)) 68 +if ['local', 'lxc'].include?($SPB_ENV)
  69 + file ssh_config_file => ['nodes.yaml', ips_file, 'ssh_config.erb', 'Rakefile'] do |t|
  70 + require 'erb'
  71 + template = ERB.new(File.read('ssh_config.erb'))
  72 + File.open(t.name, 'w') do |f|
  73 + f.write(template.result(binding))
  74 + end
  75 + puts 'ERB %s' % t.name
46 end 76 end
47 - puts 'ERB %s' % t.name  
48 end 77 end
49 78
50 task :backup => ssh_config_file do 79 task :backup => ssh_config_file do
@@ -13,28 +13,43 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| @@ -13,28 +13,43 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
13 config.vm.provision 'shell', path: 'utils/proxy.sh', args: [proxy] 13 config.vm.provision 'shell', path: 'utils/proxy.sh', args: [proxy]
14 end 14 end
15 15
16 - ips = YAML.load_file('config/local/ips.yaml') 16 + load './local.rake' if File.exists?('local.rake')
  17 + env = ENV.fetch('SPB_ENV', 'local')
  18 +
  19 + if File.exist?("config/#{env}/ips.yaml")
  20 + ips = YAML.load_file("config/#{env}/ips.yaml")
  21 + else
  22 + ips = nil
  23 + end
17 24
18 config.vm.define 'database' do |database| 25 config.vm.define 'database' do |database|
19 - database.vm.network 'private_network', ip: ips['database'] 26 + database.vm.provider "virtualbox" do |vm|
  27 + database.vm.network 'private_network', ip: ips['database'] if ips
  28 + end
20 end 29 end
21 config.vm.define 'integration' do |integration| 30 config.vm.define 'integration' do |integration|
22 - integration.vm.network 'private_network', ip: ips['integration']  
23 - integration.vm.provider "virtualbox" do |v|  
24 - v.memory = 1024  
25 - v.cpus = 2 31 + integration.vm.provider "virtualbox" do |vm|
  32 + integration.vm.network 'private_network', ip: ips['integration'] if ips
  33 + vm.memory = 1024
  34 + vm.cpus = 2
26 end 35 end
27 end 36 end
28 config.vm.define 'email' do |email| 37 config.vm.define 'email' do |email|
29 - email.vm.network 'private_network', ip: ips['email'] 38 + email.vm.provider "virtualbox" do |vm|
  39 + email.vm.network 'private_network', ip: ips['email'] if ips
  40 + end
30 end 41 end
31 config.vm.define 'social' do |social| 42 config.vm.define 'social' do |social|
32 - social.vm.network 'private_network', ip: ips['social'] 43 + social.vm.provider "virtualbox" do |vm|
  44 + social.vm.network 'private_network', ip: ips['social'] if ips
  45 + end
33 end 46 end
34 config.vm.define 'reverseproxy' do |reverseproxy| 47 config.vm.define 'reverseproxy' do |reverseproxy|
35 - reverseproxy.vm.network 'private_network', ip: ips['reverseproxy']  
36 - if File.exist?('tmp/preconfig.local.stamp')  
37 - reverseproxy.ssh.port = File.read('tmp/preconfig.local.stamp').strip.to_i 48 + reverseproxy.vm.provider "virtualbox" do |vm|
  49 + reverseproxy.vm.network 'private_network', ip: ips['reverseproxy'] if ips
  50 + end
  51 + if File.exist?("tmp/preconfig.#{env}.stamp")
  52 + reverseproxy.ssh.port = File.read("tmp/preconfig.#{env}.stamp").strip.to_i
38 reverseproxy.ssh.host = ips['reverseproxy'] 53 reverseproxy.ssh.host = ips['reverseproxy']
39 end 54 end
40 end 55 end
cookbooks/basics/files/default/is-a-container 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +#!/bin/sh
  2 +
  3 +# MANAGED WITH CHEF; DO NOT CHANGE BY HAND
  4 +
  5 +set -e
  6 +
  7 +if grep -q '/$' /proc/1/cgroup; then
  8 + # "Real" system
  9 + exit 1
  10 +else
  11 + # container
  12 + exit 0
  13 +fi
cookbooks/basics/files/default/selinux-enabled 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +#!/bin/sh
  2 +
  3 +# MANAGED WITH CHEF; DO NOT CHANGE BY HAND
  4 +
  5 +set -e
  6 +
  7 +selinux_status=$(sestatus | sed -e '/^SELinux status:/ !d; s/.*\s//')
  8 +[ "$selinux_status" = 'enabled' ]
cookbooks/basics/files/default/selinux-install-module
@@ -9,6 +9,12 @@ if [ $# -ne 1 ]; then @@ -9,6 +9,12 @@ if [ $# -ne 1 ]; then
9 exit 1 9 exit 1
10 fi 10 fi
11 11
  12 +selinux_status=$(sestatus | sed -e '/^SELinux status:/ !d; s/.*\s//')
  13 +if ! selinux-enabled; then
  14 + echo "I: SELinux disabled, skipping"
  15 + exit 0
  16 +fi
  17 +
12 input="$1" 18 input="$1"
13 19
14 directory=$(dirname "$input") 20 directory=$(dirname "$input")
cookbooks/basics/recipes/default.rb
@@ -10,8 +10,19 @@ cookbook_file &#39;/etc/selinux/config&#39; do @@ -10,8 +10,19 @@ cookbook_file &#39;/etc/selinux/config&#39; do
10 group 'root' 10 group 'root'
11 mode 0644 11 mode 0644
12 end 12 end
13 -execute 'setenforce Enforcing'  
14 -execute 'setsebool httpd_can_network_connect 1' 13 +
  14 +cookbook_file '/usr/local/bin/selinux-enabled' do
  15 + owner 'root'
  16 + group 'root'
  17 + mode '0755'
  18 +end
  19 +
  20 +execute 'setenforce Enforcing' do
  21 + only_if 'selinux-enabled'
  22 +end
  23 +execute 'setsebool httpd_can_network_connect 1' do
  24 + only_if 'selinux-enabled'
  25 +end
15 # directory for local type enforcements 26 # directory for local type enforcements
16 directory '/etc/selinux/local' do 27 directory '/etc/selinux/local' do
17 owner 'root' 28 owner 'root'
@@ -32,8 +43,14 @@ package &#39;less&#39; @@ -32,8 +43,14 @@ package &#39;less&#39;
32 package 'htop' 43 package 'htop'
33 package 'ntp' 44 package 'ntp'
34 45
  46 +cookbook_file '/usr/local/bin/is-a-container' do
  47 + owner 'root'
  48 + group 'root'
  49 + mode '0755'
  50 +end
35 service 'ntpd' do 51 service 'ntpd' do
36 action [:enable, :start] 52 action [:enable, :start]
  53 + not_if 'is-a-container'
37 end 54 end
38 55
39 service 'firewalld' do 56 service 'firewalld' do
cookbooks/reverse_proxy/recipes/default.rb
@@ -12,7 +12,9 @@ cookbook_file &quot;/etc/sysctl.d/ip_forward.conf&quot; do @@ -12,7 +12,9 @@ cookbook_file &quot;/etc/sysctl.d/ip_forward.conf&quot; do
12 mode 0644 12 mode 0644
13 end 13 end
14 14
15 -execute 'sysctl -w net.ipv4.ip_forward=1' 15 +execute 'sysctl -w net.ipv4.ip_forward=1' do
  16 + not_if 'is-a-container'
  17 +end
16 18
17 cookbook_file "/etc/nginx/#{node['config']['external_hostname']}.key" do 19 cookbook_file "/etc/nginx/#{node['config']['external_hostname']}.key" do
18 owner 'root' 20 owner 'root'
test/dns_test.sh
1 . $(dirname $0)/test_helper.sh 1 . $(dirname $0)/test_helper.sh
2 2
3 -if [ "$SPB_ENV" = local ]; then 3 +if [ "$SPB_ENV" = local -o "$SPB_ENV" = lxc ]; then
4 echo "_No DNS for local environment_" 4 echo "_No DNS for local environment_"
5 exit 5 exit
6 fi 6 fi
utils/reverseproxy_ssh_setup
@@ -11,7 +11,15 @@ sed -i -e &#39;s/^#\?\s*Port\s*[0-9]\+\s*$/Port &#39;$port&#39;/g&#39; /etc/ssh/sshd_config @@ -11,7 +11,15 @@ sed -i -e &#39;s/^#\?\s*Port\s*[0-9]\+\s*$/Port &#39;$port&#39;/g&#39; /etc/ssh/sshd_config
11 yum install -y selinux-policy policycoreutils-python 11 yum install -y selinux-policy policycoreutils-python
12 12
13 # Tell SELinux to allow the new port 13 # Tell SELinux to allow the new port
14 -semanage port -a -t ssh_port_t -p tcp "$port" 14 +if grep -q '/$' /proc/1/cgroup; then
  15 + # not in a container
  16 + semanage port -a -t ssh_port_t -p tcp "$port"
  17 +else
  18 + # in container; will fail if host does not have SELinux enabled
  19 + if ! semanage port -a -t ssh_port_t -p tcp "$port"; then
  20 + echo "I: can't use SELinux, your host probably does not have it enabled"
  21 + fi
  22 +fi
15 23
16 # Restart SSH 24 # Restart SSH
17 systemctl restart sshd 25 systemctl restart sshd