pauper 0.2.0 → 0.2.1
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 +4 -4
- data/bin/pauper +12 -4
- data/lib/fusion.rb +1 -1
- data/lib/lxc_template.rb +643 -0
- data/lib/pauper.rb +115 -668
- data/lib/pauper/version.rb +1 -1
- data/test/pauper_test.rb +4 -2
- metadata +17 -16
data/lib/pauper.rb
CHANGED
@@ -20,6 +20,7 @@ require 'pauper/version'
|
|
20
20
|
class Pauper
|
21
21
|
DEFAULT_PAUPERFILE = './Pauperfile'
|
22
22
|
DEFAULT_VM_PATH = File.expand_path('/var/lib/lxc/')
|
23
|
+
SUPPORTED_RELEASES = [:lucid, :precise]
|
23
24
|
|
24
25
|
def initialize(ignore_network = false, pauperfile = DEFAULT_PAUPERFILE)
|
25
26
|
if root?
|
@@ -39,37 +40,69 @@ class Pauper
|
|
39
40
|
@pauper_config
|
40
41
|
end
|
41
42
|
|
42
|
-
def
|
43
|
-
|
43
|
+
def self.version
|
44
|
+
puts "Pauper v#{VERSION}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.grok_release(release_s)
|
48
|
+
release = release_s.intern
|
49
|
+
raise "Unsupported release '#{release_s}'" unless SUPPORTED_RELEASES.include?(release)
|
50
|
+
release
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_base_name(release)
|
54
|
+
case Pauper.grok_release(release)
|
55
|
+
when :lucid
|
56
|
+
'base'
|
57
|
+
when :precise
|
58
|
+
'base-precise'
|
59
|
+
else
|
60
|
+
raise "Unsupported release #{release}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_base_ip(base_name)
|
65
|
+
if base_name == 'base'
|
66
|
+
return @pauper_config.config[:subnet] + '.2'
|
67
|
+
elsif base_name == 'base-precise'
|
68
|
+
return @pauper_config.config[:subnet] + '.3'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def bootstrap(release)
|
73
|
+
release = Pauper.grok_release(release)
|
74
|
+
base_name = get_base_name(release)
|
75
|
+
|
76
|
+
raise "Base '#{base_name}' already exists!" if vm_exists?(base_name)
|
44
77
|
|
45
|
-
ip =
|
46
|
-
ssh_clean_known_hosts(
|
78
|
+
ip = get_base_ip(base_name)
|
79
|
+
ssh_clean_known_hosts(base_name, ip)
|
47
80
|
@pauper_config.config[:nodes].each { |n| ssh_clean_known_hosts(n.name, "#{@pauper_config.config[:subnet]}.#{n.config[:last_octet]}") }
|
48
81
|
|
49
82
|
lxc_pauper_template
|
50
83
|
system("sudo touch /var/lib/lxc/lxc.conf")
|
51
|
-
system("sudo lxc-create -n
|
84
|
+
system("sudo lxc-create -n #{base_name} -t pauper -f /var/lib/lxc/lxc.conf -- -a amd64 --auth-key #{public_ssh_key} -r #{release}")
|
52
85
|
mac = generate_mac
|
53
86
|
|
54
|
-
lxc = LXC.new(
|
87
|
+
lxc = LXC.new(base_name)
|
55
88
|
lxc.interface = @pauper_config.config[:bridge]
|
56
89
|
lxc.mac = mac
|
57
90
|
lxc.save
|
58
91
|
|
59
|
-
prepare_fstab(
|
60
|
-
prepare_vm_network(
|
61
|
-
prepare_base_cache
|
92
|
+
prepare_fstab(base_name, release)
|
93
|
+
prepare_vm_network(base_name,ip)
|
94
|
+
prepare_base_cache(release)
|
62
95
|
|
63
96
|
puts "Installing chef..."
|
64
|
-
cmd "sudo chroot /var/lib/lxc/
|
97
|
+
cmd "sudo chroot /var/lib/lxc/#{base_name}/rootfs/ bash -c 'wget #{@pauper_config.config[:chef_download_url][release]}/#{@pauper_config.config[:chef_deb_name][release]} && dpkg -i #{@pauper_config.config[:chef_deb_name][release]}; rm #{@pauper_config.config[:chef_deb_name][release]}'"
|
65
98
|
|
66
|
-
start_node(
|
99
|
+
start_node(base_name)
|
67
100
|
sleep 3
|
68
101
|
|
69
|
-
chef_node = "
|
102
|
+
chef_node = "#{base_name}#{@pauper_config.config[:node_suffix]}"
|
70
103
|
cmd "knife bootstrap --bootstrap-version chef-full -N #{chef_node} -E #{@pauper_config.config[:chef_environment]} -x root -r \"#{@pauper_config.config[:default_run_list].join(",")}\" #{ip}"
|
71
104
|
|
72
|
-
stop_node(
|
105
|
+
stop_node(base_name)
|
73
106
|
end
|
74
107
|
|
75
108
|
def username
|
@@ -89,9 +122,14 @@ class Pauper
|
|
89
122
|
ssh_key + ".pub"
|
90
123
|
end
|
91
124
|
|
92
|
-
def
|
125
|
+
def get_share_release(options)
|
126
|
+
options[:release] || :lucid
|
127
|
+
end
|
128
|
+
|
129
|
+
def prepare_fstab(node_name, release)
|
93
130
|
File.open('.tmp.fstab','w') do |f|
|
94
131
|
@pauper_config.config[:shares].each do |share_name, guest_path, host_path, options|
|
132
|
+
next if get_share_release(options) != release
|
95
133
|
f.puts "#{host_path} #{DEFAULT_VM_PATH}/#{node_name}/rootfs/#{guest_path} none defaults,bind 0 0"
|
96
134
|
end
|
97
135
|
end
|
@@ -117,12 +155,15 @@ class Pauper
|
|
117
155
|
system "sudo mv .tmp.resolv.conf #{DEFAULT_VM_PATH}/#{node_name}/rootfs/etc/resolv.conf"
|
118
156
|
end
|
119
157
|
|
120
|
-
def prepare_base_cache
|
121
|
-
|
158
|
+
def prepare_base_cache(release)
|
159
|
+
base_name = get_base_name(release)
|
160
|
+
shares = @pauper_config.config[:shares]
|
161
|
+
shares.each do |share_name, guest_path, host_path, options|
|
162
|
+
next if get_share_release(options) != release
|
122
163
|
cmd "sudo mkdir -p #{host_path}"
|
123
|
-
cmd "sudo mkdir -p /var/lib/lxc/
|
164
|
+
cmd "sudo mkdir -p /var/lib/lxc/#{base_name}/rootfs#{guest_path}"
|
124
165
|
end
|
125
|
-
cmd "sudo mkdir -p /var/cache/lxc/
|
166
|
+
cmd "sudo mkdir -p /var/cache/lxc/#{release}/cache/apt/partial"
|
126
167
|
end
|
127
168
|
|
128
169
|
def reconfigure_ssh(node_name)
|
@@ -134,8 +175,16 @@ class Pauper
|
|
134
175
|
|
135
176
|
raise "VM already exists!" if vm_exists?(node_name)
|
136
177
|
|
137
|
-
|
138
|
-
|
178
|
+
release = node_config.config[:release]
|
179
|
+
base_name = get_base_name(release)
|
180
|
+
|
181
|
+
unless vm_exists?(base_name)
|
182
|
+
puts "Bootstrapping base '#{base_name}' for release '#{release}'"
|
183
|
+
bootstrap(release)
|
184
|
+
end
|
185
|
+
|
186
|
+
puts "Cloning #{base_name}..."
|
187
|
+
clone_base(base_name, node_name)
|
139
188
|
mac = generate_mac
|
140
189
|
ip = "#{@pauper_config.config[:subnet]}.#{node_config.config[:last_octet]}"
|
141
190
|
|
@@ -144,24 +193,26 @@ class Pauper
|
|
144
193
|
lxc.mac = mac
|
145
194
|
lxc.save
|
146
195
|
|
147
|
-
prepare_fstab(node_name)
|
196
|
+
prepare_fstab(node_name, release)
|
148
197
|
prepare_vm_network(node_name,ip)
|
149
198
|
reconfigure_ssh(node_name)
|
150
199
|
puts "Starting..."
|
151
200
|
start_node(node_name)
|
152
201
|
sleep 3
|
202
|
+
write_hosts
|
153
203
|
setup(node_name)
|
154
204
|
end
|
155
205
|
|
156
206
|
def setup(node_name)
|
157
207
|
node_config = get_node_config(node_name)
|
208
|
+
release = node_config.config[:release]
|
158
209
|
config = @pauper_config.config
|
159
210
|
puts "Setting up #{node_name}..."
|
160
211
|
client_erb = ERB.new <<EOF
|
161
212
|
node_name "<%= chef_node %>"
|
162
213
|
chef_server_url "<%= config[:chef_server_url] %>"
|
163
|
-
chef_download_url "<%= config[:chef_download_url] %>"
|
164
|
-
chef_deb_name "<%= config[:chef_deb_name] %>"
|
214
|
+
chef_download_url "<%= config[:chef_download_url][release] %>"
|
215
|
+
chef_deb_name "<%= config[:chef_deb_name][release] %>"
|
165
216
|
validation_client_name "<%= config[:validation_client_name] %>"
|
166
217
|
environment "<%= config[:chef_environment] %>"
|
167
218
|
verbose_logging false
|
@@ -207,9 +258,8 @@ EOF
|
|
207
258
|
end
|
208
259
|
|
209
260
|
def destroy(node_name)
|
210
|
-
|
211
|
-
|
212
|
-
else
|
261
|
+
ip = get_base_ip(node_name)
|
262
|
+
if ip.nil?
|
213
263
|
node_config = get_node_config(node_name)
|
214
264
|
ip = node_ip(node_config)
|
215
265
|
end
|
@@ -225,6 +275,7 @@ EOF
|
|
225
275
|
puts "Destroying #{node_name}..."
|
226
276
|
cmd "sudo lxc-destroy -n '#{node_name}' >> pauper.log 2>&1"
|
227
277
|
ssh_clean_known_hosts(node_name, ip)
|
278
|
+
write_hosts
|
228
279
|
else
|
229
280
|
puts "#{node_name} hasn't even been created yet, thusly you can't destroy it!"
|
230
281
|
end
|
@@ -273,7 +324,9 @@ EOF
|
|
273
324
|
def write_hosts
|
274
325
|
puts "Writing /etc/hosts file..."
|
275
326
|
hosts = Hosts.new
|
327
|
+
hosts.config.clear
|
276
328
|
@pauper_config.config[:nodes].each do |node|
|
329
|
+
next unless vm_exists?(node.name)
|
277
330
|
hosts.config[node_ip(node)] = node.name
|
278
331
|
end
|
279
332
|
hosts.save(@pauper_config.config[:dev_domain])
|
@@ -474,7 +527,10 @@ EOF
|
|
474
527
|
|
475
528
|
def cmd(*args)
|
476
529
|
puts ["local>", *args].join(" ")
|
477
|
-
system *args
|
530
|
+
ok = system *args
|
531
|
+
if not ok
|
532
|
+
raise "shell command '"+args.join(" ")+"' failed"
|
533
|
+
end
|
478
534
|
end
|
479
535
|
|
480
536
|
def ssh_clean_known_hosts(hostname, ip)
|
@@ -505,11 +561,11 @@ EOF
|
|
505
561
|
`sudo lxc-info -n '#{node_name}'`.include?("FROZEN")
|
506
562
|
end
|
507
563
|
|
508
|
-
def clone_base(node_name)
|
509
|
-
cmd "sudo cp -ax #{DEFAULT_VM_PATH}
|
510
|
-
cmd "sudo rm #{DEFAULT_VM_PATH}/#{node_name}/rootfs/etc/chef/client.pem"
|
511
|
-
cmd "sudo rm #{DEFAULT_VM_PATH}/#{node_name}/rootfs/etc/ssh/ssh*key*"
|
512
|
-
cmd "sudo sed -i \"s
|
564
|
+
def clone_base(base_name, node_name)
|
565
|
+
cmd "sudo cp -ax #{DEFAULT_VM_PATH}/#{base_name} #{DEFAULT_VM_PATH}/#{node_name}"
|
566
|
+
cmd "sudo rm -f #{DEFAULT_VM_PATH}/#{node_name}/rootfs/etc/chef/client.pem"
|
567
|
+
cmd "sudo rm -f #{DEFAULT_VM_PATH}/#{node_name}/rootfs/etc/ssh/ssh*key*"
|
568
|
+
cmd "sudo sed -i \"s/#{base_name}/#{node_name}/g\" /var/lib/lxc/#{node_name}/rootfs/etc/hostname /var/lib/lxc/#{node_name}/rootfs/etc/chef/client.rb"
|
513
569
|
end
|
514
570
|
|
515
571
|
def vm_config(node_name)
|
@@ -553,637 +609,15 @@ EOF
|
|
553
609
|
File.dirname(@pauper_config.config[:vmx])
|
554
610
|
end
|
555
611
|
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
#
|
563
|
-
|
564
|
-
#
|
565
|
-
|
566
|
-
# Copyright � 2011 Serge Hallyn <serge.hallyn@canonical.com>
|
567
|
-
# Copyright � 2010 Wilhelm Meier
|
568
|
-
# Author: Wilhelm Meier <wilhelm.meier@fh-kl.de>
|
569
|
-
#
|
570
|
-
# This program is free software; you can redistribute it and/or modify
|
571
|
-
# it under the terms of the GNU General Public License version 2, as
|
572
|
-
# published by the Free Software Foundation.
|
573
|
-
|
574
|
-
# This program is distributed in the hope that it will be useful,
|
575
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
576
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
577
|
-
# GNU General Public License for more details.
|
578
|
-
|
579
|
-
# You should have received a copy of the GNU General Public License along
|
580
|
-
# with this program; if not, write to the Free Software Foundation, Inc.,
|
581
|
-
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
582
|
-
#
|
583
|
-
|
584
|
-
set -e
|
585
|
-
|
586
|
-
if [ -r /etc/default/lxc ]; then
|
587
|
-
. /etc/default/lxc
|
588
|
-
fi
|
589
|
-
|
590
|
-
configure_ubuntu()
|
591
|
-
{
|
592
|
-
rootfs=$1
|
593
|
-
hostname=$2
|
594
|
-
release=$3
|
595
|
-
|
596
|
-
# configure the network using the dhcp
|
597
|
-
cat <<EOF > $rootfs/etc/network/interfaces
|
598
|
-
# This file describes the network interfaces available on your system
|
599
|
-
# and how to activate them. For more information, see interfaces(5).
|
600
|
-
|
601
|
-
# The loopback network interface
|
602
|
-
auto lo
|
603
|
-
iface lo inet loopback
|
604
|
-
|
605
|
-
auto eth0
|
606
|
-
iface eth0 inet dhcp
|
607
|
-
EOF
|
608
|
-
|
609
|
-
# set the hostname
|
610
|
-
cat <<EOF > $rootfs/etc/hostname
|
611
|
-
$hostname
|
612
|
-
EOF
|
613
|
-
# set minimal hosts
|
614
|
-
cat <<EOF > $rootfs/etc/hosts
|
615
|
-
127.0.0.1 localhost
|
616
|
-
127.0.1.1 $hostname
|
617
|
-
|
618
|
-
# The following lines are desirable for IPv6 capable hosts
|
619
|
-
::1 ip6-localhost ip6-loopback
|
620
|
-
fe00::0 ip6-localnet
|
621
|
-
ff00::0 ip6-mcastprefix
|
622
|
-
ff02::1 ip6-allnodes
|
623
|
-
ff02::2 ip6-allrouters
|
624
|
-
EOF
|
625
|
-
|
626
|
-
if [ ! -f $rootfs/etc/init/container-detect.conf ]; then
|
627
|
-
# suppress log level output for udev
|
628
|
-
sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf
|
629
|
-
|
630
|
-
# remove jobs for consoles 5 and 6 since we only create 4 consoles in
|
631
|
-
# this template
|
632
|
-
rm -f $rootfs/etc/init/tty{5,6}.conf
|
633
|
-
fi
|
634
|
-
|
635
|
-
return 0
|
636
|
-
}
|
637
|
-
|
638
|
-
# finish setting up the user in the container by injecting ssh key
|
639
|
-
finalize_user()
|
640
|
-
{
|
641
|
-
if [ -n "$auth_key" -a -f "$auth_key" ]; then
|
642
|
-
u_path="/root/.ssh"
|
643
|
-
root_u_path="$rootfs/$u_path"
|
644
|
-
|
645
|
-
mkdir -p $root_u_path
|
646
|
-
cp $auth_key "$root_u_path/authorized_keys"
|
647
|
-
chroot $rootfs chown -R root: "$u_path"
|
648
|
-
|
649
|
-
echo "Inserted SSH public key from $auth_key into /root/.ssh/authorized_keys"
|
650
|
-
fi
|
651
|
-
return 0
|
652
|
-
}
|
653
|
-
|
654
|
-
write_sourceslist()
|
655
|
-
{
|
656
|
-
# $1 => path to the rootfs
|
657
|
-
# $2 => architecture we want to add
|
658
|
-
# $3 => whether to use the multi-arch syntax or not
|
659
|
-
|
660
|
-
case $2 in
|
661
|
-
amd64|i386)
|
662
|
-
MIRROR=${MIRROR:-http://mirrors.fastly.net/ubuntu}
|
663
|
-
SECURITY_MIRROR=${SECURITY_MIRROR:-http://mirrors.fastly.net/ubuntu}
|
664
|
-
;;
|
665
|
-
*)
|
666
|
-
MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
|
667
|
-
SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
|
668
|
-
;;
|
669
|
-
esac
|
670
|
-
if [ -n "$3" ]; then
|
671
|
-
cat >> "$1/etc/apt/sources.list" << EOF
|
672
|
-
deb [arch=$2] $MIRROR ${release} main restricted universe multiverse
|
673
|
-
deb [arch=$2] $MIRROR ${release}-updates main restricted universe multiverse
|
674
|
-
deb [arch=$2] $SECURITY_MIRROR ${release}-security main restricted universe multiverse
|
675
|
-
EOF
|
676
|
-
else
|
677
|
-
cat >> "$1/etc/apt/sources.list" << EOF
|
678
|
-
deb $MIRROR ${release} main restricted universe multiverse
|
679
|
-
deb $MIRROR ${release}-updates main restricted universe multiverse
|
680
|
-
deb $SECURITY_MIRROR ${release}-security main restricted universe multiverse
|
681
|
-
EOF
|
682
|
-
fi
|
683
|
-
}
|
684
|
-
|
685
|
-
cleanup()
|
686
|
-
{
|
687
|
-
rm -rf $cache/partial-$arch
|
688
|
-
rm -rf $cache/rootfs-$arch
|
689
|
-
}
|
690
|
-
|
691
|
-
download_ubuntu()
|
692
|
-
{
|
693
|
-
cache=$1
|
694
|
-
arch=$2
|
695
|
-
release=$3
|
696
|
-
|
697
|
-
packages=vim,ssh,curl,wget
|
698
|
-
echo "installing packages: $packages"
|
699
|
-
|
700
|
-
trap cleanup EXIT SIGHUP SIGINT SIGTERM
|
701
|
-
# check the mini ubuntu was not already downloaded
|
702
|
-
mkdir -p "$cache/partial-$arch"
|
703
|
-
if [ $? -ne 0 ]; then
|
704
|
-
echo "Failed to create '$cache/partial-$arch' directory"
|
705
|
-
return 1
|
706
|
-
fi
|
707
|
-
|
708
|
-
# download a mini ubuntu into a cache
|
709
|
-
echo "Downloading ubuntu $release minimal ..."
|
710
|
-
if [ -n "$(which qemu-debootstrap)" ]; then
|
711
|
-
qemu-debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR
|
712
|
-
else
|
713
|
-
debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR
|
714
|
-
fi
|
715
|
-
|
716
|
-
if [ $? -ne 0 ]; then
|
717
|
-
echo "Failed to download the rootfs, aborting."
|
718
|
-
return 1
|
719
|
-
fi
|
720
|
-
|
721
|
-
# Serge isn't sure whether we should avoid doing this when
|
722
|
-
# $release == `distro-info -d`
|
723
|
-
echo "Installing updates"
|
724
|
-
> $cache/partial-$arch/etc/apt/sources.list
|
725
|
-
write_sourceslist $cache/partial-$arch/ $arch
|
726
|
-
|
727
|
-
chroot "$1/partial-${arch}" apt-get update
|
728
|
-
if [ $? -ne 0 ]; then
|
729
|
-
echo "Failed to update the apt cache"
|
730
|
-
return 1
|
731
|
-
fi
|
732
|
-
cat > "$1/partial-${arch}"/usr/sbin/policy-rc.d << EOF
|
733
|
-
#!/bin/sh
|
734
|
-
exit 101
|
735
|
-
EOF
|
736
|
-
chmod +x "$1/partial-${arch}"/usr/sbin/policy-rc.d
|
737
|
-
|
738
|
-
lxc-unshare -s MOUNT -- chroot "$1/partial-${arch}" apt-get dist-upgrade -y
|
739
|
-
ret=$?
|
740
|
-
rm -f "$1/partial-${arch}"/usr/sbin/policy-rc.d
|
741
|
-
|
742
|
-
if [ $ret -ne 0 ]; then
|
743
|
-
echo "Failed to upgrade the cache"
|
744
|
-
return 1
|
745
|
-
fi
|
746
|
-
|
747
|
-
mv "$1/partial-$arch" "$1/rootfs-$arch"
|
748
|
-
trap EXIT
|
749
|
-
trap SIGINT
|
750
|
-
trap SIGTERM
|
751
|
-
trap SIGHUP
|
752
|
-
echo "Download complete"
|
753
|
-
return 0
|
754
|
-
}
|
755
|
-
|
756
|
-
copy_ubuntu()
|
757
|
-
{
|
758
|
-
cache=$1
|
759
|
-
arch=$2
|
760
|
-
rootfs=$3
|
761
|
-
|
762
|
-
# make a local copy of the miniubuntu
|
763
|
-
echo "Copying rootfs to $rootfs ..."
|
764
|
-
mkdir -p $rootfs
|
765
|
-
rsync -a $cache/rootfs-$arch/ $rootfs/ || return 1
|
766
|
-
return 0
|
767
|
-
}
|
768
|
-
|
769
|
-
install_ubuntu()
|
770
|
-
{
|
771
|
-
rootfs=$1
|
772
|
-
release=$2
|
773
|
-
flushcache=$3
|
774
|
-
cache="/var/cache/lxc/$release"
|
775
|
-
mkdir -p /var/lock/subsys/
|
776
|
-
|
777
|
-
(
|
778
|
-
flock -x 200
|
779
|
-
if [ $? -ne 0 ]; then
|
780
|
-
echo "Cache repository is busy."
|
781
|
-
return 1
|
782
|
-
fi
|
783
|
-
|
784
|
-
|
785
|
-
if [ $flushcache -eq 1 ]; then
|
786
|
-
echo "Flushing cache..."
|
787
|
-
rm -rf "$cache/partial-$arch"
|
788
|
-
rm -rf "$cache/rootfs-$arch"
|
789
|
-
fi
|
790
|
-
|
791
|
-
echo "Checking cache download in $cache/rootfs-$arch ... "
|
792
|
-
if [ ! -e "$cache/rootfs-$arch" ]; then
|
793
|
-
download_ubuntu $cache $arch $release
|
794
|
-
if [ $? -ne 0 ]; then
|
795
|
-
echo "Failed to download 'ubuntu $release base'"
|
796
|
-
return 1
|
797
|
-
fi
|
798
|
-
fi
|
799
|
-
|
800
|
-
echo "Copy $cache/rootfs-$arch to $rootfs ... "
|
801
|
-
copy_ubuntu $cache $arch $rootfs
|
802
|
-
if [ $? -ne 0 ]; then
|
803
|
-
echo "Failed to copy rootfs"
|
804
|
-
return 1
|
805
|
-
fi
|
806
|
-
|
807
|
-
return 0
|
808
|
-
|
809
|
-
) 200>/var/lock/subsys/lxc
|
810
|
-
|
811
|
-
return $?
|
812
|
-
}
|
813
|
-
|
814
|
-
copy_configuration()
|
815
|
-
{
|
816
|
-
path=$1
|
817
|
-
rootfs=$2
|
818
|
-
name=$3
|
819
|
-
arch=$4
|
820
|
-
release=$5
|
821
|
-
|
822
|
-
if [ $arch = "i386" ]; then
|
823
|
-
arch="i686"
|
824
|
-
fi
|
825
|
-
|
826
|
-
ttydir=""
|
827
|
-
if [ -f $rootfs/etc/init/container-detect.conf ]; then
|
828
|
-
ttydir=" lxc"
|
829
|
-
fi
|
830
|
-
|
831
|
-
# if there is exactly one veth network entry, make sure it has an
|
832
|
-
# associated hwaddr.
|
833
|
-
nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
|
834
|
-
if [ $nics -eq 1 ]; then
|
835
|
-
grep -q "^lxc.network.hwaddr" $path/config || cat <<EOF >> $path/config
|
836
|
-
lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')
|
837
|
-
EOF
|
838
|
-
fi
|
839
|
-
|
840
|
-
cat <<EOF >> $path/config
|
841
|
-
lxc.utsname = $name
|
842
|
-
|
843
|
-
lxc.devttydir =$ttydir
|
844
|
-
lxc.tty = 4
|
845
|
-
lxc.pts = 1024
|
846
|
-
lxc.rootfs = $rootfs
|
847
|
-
lxc.mount = $path/fstab
|
848
|
-
lxc.arch = $arch
|
849
|
-
lxc.cap.drop = sys_module mac_admin
|
850
|
-
lxc.pivotdir = lxc_putold
|
851
|
-
|
852
|
-
# uncomment the next line to run the container unconfined:
|
853
|
-
#lxc.aa_profile = unconfined
|
854
|
-
|
855
|
-
lxc.cgroup.devices.deny = a
|
856
|
-
# Allow any mknod (but not using the node)
|
857
|
-
lxc.cgroup.devices.allow = c *:* m
|
858
|
-
lxc.cgroup.devices.allow = b *:* m
|
859
|
-
# /dev/null and zero
|
860
|
-
lxc.cgroup.devices.allow = c 1:3 rwm
|
861
|
-
lxc.cgroup.devices.allow = c 1:5 rwm
|
862
|
-
# consoles
|
863
|
-
lxc.cgroup.devices.allow = c 5:1 rwm
|
864
|
-
lxc.cgroup.devices.allow = c 5:0 rwm
|
865
|
-
#lxc.cgroup.devices.allow = c 4:0 rwm
|
866
|
-
#lxc.cgroup.devices.allow = c 4:1 rwm
|
867
|
-
# /dev/{,u}random
|
868
|
-
lxc.cgroup.devices.allow = c 1:9 rwm
|
869
|
-
lxc.cgroup.devices.allow = c 1:8 rwm
|
870
|
-
lxc.cgroup.devices.allow = c 136:* rwm
|
871
|
-
lxc.cgroup.devices.allow = c 5:2 rwm
|
872
|
-
# rtc
|
873
|
-
lxc.cgroup.devices.allow = c 254:0 rwm
|
874
|
-
#fuse
|
875
|
-
lxc.cgroup.devices.allow = c 10:229 rwm
|
876
|
-
#tun
|
877
|
-
lxc.cgroup.devices.allow = c 10:200 rwm
|
878
|
-
#full
|
879
|
-
lxc.cgroup.devices.allow = c 1:7 rwm
|
880
|
-
#hpet
|
881
|
-
lxc.cgroup.devices.allow = c 10:228 rwm
|
882
|
-
#kvm
|
883
|
-
lxc.cgroup.devices.allow = c 10:232 rwm
|
884
|
-
EOF
|
885
|
-
|
886
|
-
cat <<EOF > $path/fstab
|
887
|
-
proc proc proc nodev,noexec,nosuid 0 0
|
888
|
-
sysfs sys sysfs defaults 0 0
|
889
|
-
EOF
|
890
|
-
|
891
|
-
if [ $? -ne 0 ]; then
|
892
|
-
echo "Failed to add configuration"
|
893
|
-
return 1
|
894
|
-
fi
|
895
|
-
|
896
|
-
return 0
|
897
|
-
}
|
898
|
-
|
899
|
-
trim()
|
900
|
-
{
|
901
|
-
rootfs=$1
|
902
|
-
release=$2
|
903
|
-
|
904
|
-
# provide the lxc service
|
905
|
-
cat <<EOF > $rootfs/etc/init/lxc.conf
|
906
|
-
# fake some events needed for correct startup other services
|
907
|
-
|
908
|
-
description "Container Upstart"
|
909
|
-
|
910
|
-
start on startup
|
911
|
-
|
912
|
-
script
|
913
|
-
rm -rf /var/run/*.pid
|
914
|
-
rm -rf /var/run/network/*
|
915
|
-
/sbin/initctl emit stopped JOB=udevtrigger --no-wait
|
916
|
-
/sbin/initctl emit started JOB=udev --no-wait
|
917
|
-
end script
|
918
|
-
EOF
|
919
|
-
|
920
|
-
# fix buggus runlevel with sshd
|
921
|
-
cat <<EOF > $rootfs/etc/init/ssh.conf
|
922
|
-
# ssh - OpenBSD Secure Shell server
|
923
|
-
#
|
924
|
-
# The OpenSSH server provides secure shell access to the system.
|
925
|
-
|
926
|
-
description "OpenSSH server"
|
927
|
-
|
928
|
-
start on filesystem
|
929
|
-
stop on runlevel [!2345]
|
930
|
-
|
931
|
-
expect fork
|
932
|
-
respawn
|
933
|
-
respawn limit 10 5
|
934
|
-
umask 022
|
935
|
-
# replaces SSHD_OOM_ADJUST in /etc/default/ssh
|
936
|
-
oom never
|
937
|
-
|
938
|
-
pre-start script
|
939
|
-
test -x /usr/sbin/sshd || { stop; exit 0; }
|
940
|
-
test -e /etc/ssh/sshd_not_to_be_run && { stop; exit 0; }
|
941
|
-
test -c /dev/null || { stop; exit 0; }
|
942
|
-
|
943
|
-
mkdir -p -m0755 /var/run/sshd
|
944
|
-
end script
|
945
|
-
|
946
|
-
# if you used to set SSHD_OPTS in /etc/default/ssh, you can change the
|
947
|
-
# 'exec' line here instead
|
948
|
-
exec /usr/sbin/sshd
|
949
|
-
EOF
|
950
|
-
|
951
|
-
cat <<EOF > $rootfs/etc/init/console.conf
|
952
|
-
# console - getty
|
953
|
-
#
|
954
|
-
# This service maintains a console on tty1 from the point the system is
|
955
|
-
# started until it is shut down again.
|
956
|
-
|
957
|
-
start on stopped rc RUNLEVEL=[2345]
|
958
|
-
stop on runlevel [!2345]
|
959
|
-
|
960
|
-
respawn
|
961
|
-
exec /sbin/getty -8 38400 /dev/console
|
962
|
-
EOF
|
963
|
-
|
964
|
-
cat <<EOF > $rootfs/lib/init/fstab
|
965
|
-
# /lib/init/fstab: cleared out for bare-bones lxc
|
966
|
-
EOF
|
967
|
-
|
968
|
-
# reconfigure some services
|
969
|
-
if [ -z "$LANG" ]; then
|
970
|
-
chroot $rootfs locale-gen en_US.UTF-8
|
971
|
-
chroot $rootfs update-locale LANG=en_US.UTF-8
|
972
|
-
else
|
973
|
-
chroot $rootfs locale-gen $LANG
|
974
|
-
chroot $rootfs update-locale LANG=$LANG
|
975
|
-
fi
|
976
|
-
|
977
|
-
# remove pointless services in a container
|
978
|
-
chroot $rootfs /usr/sbin/update-rc.d -f ondemand remove
|
979
|
-
|
980
|
-
chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls u*.conf); do mv $f $f.orig; done'
|
981
|
-
chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls tty[2-9].conf); do mv $f $f.orig; done'
|
982
|
-
chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls plymouth*.conf); do mv $f $f.orig; done'
|
983
|
-
chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls hwclock*.conf); do mv $f $f.orig; done'
|
984
|
-
chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls module*.conf); do mv $f $f.orig; done'
|
985
|
-
|
986
|
-
# if this isn't lucid, then we need to twiddle the network upstart bits :(
|
987
|
-
if [ $release != "lucid" ]; then
|
988
|
-
sed -i 's/^.*emission handled.*$/echo Emitting lo/' $rootfs/etc/network/if-up.d/upstart
|
989
|
-
fi
|
990
|
-
}
|
991
|
-
|
992
|
-
post_process()
|
993
|
-
{
|
994
|
-
rootfs=$1
|
995
|
-
release=$2
|
996
|
-
trim_container=$3
|
997
|
-
|
998
|
-
if [ $trim_container -eq 1 ]; then
|
999
|
-
trim $rootfs $release
|
1000
|
-
elif [ ! -f $rootfs/etc/init/container-detect.conf ]; then
|
1001
|
-
# Make sure we have a working resolv.conf
|
1002
|
-
cresolvonf="${rootfs}/etc/resolv.conf"
|
1003
|
-
mv $cresolvonf ${cresolvonf}.lxcbak
|
1004
|
-
cat /etc/resolv.conf > ${cresolvonf}
|
1005
|
-
|
1006
|
-
# for lucid, if not trimming, then add the ubuntu-virt
|
1007
|
-
# ppa and install lxcguest
|
1008
|
-
if [ $release = "lucid" ]; then
|
1009
|
-
chroot $rootfs apt-get install --force-yes -y python-software-properties
|
1010
|
-
chroot $rootfs add-apt-repository ppa:ubuntu-virt/ppa
|
1011
|
-
fi
|
1012
|
-
|
1013
|
-
chroot $rootfs apt-get update
|
1014
|
-
chroot $rootfs apt-get install --force-yes -y lxcguest
|
1015
|
-
|
1016
|
-
# Restore old resolv.conf
|
1017
|
-
rm -f ${cresolvonf}
|
1018
|
-
mv ${cresolvonf}.lxcbak ${cresolvonf}
|
1019
|
-
fi
|
1020
|
-
|
1021
|
-
# If the container isn't running a native architecture, setup multiarch
|
1022
|
-
if [ -x "$(ls -1 ${rootfs}/usr/bin/qemu-*-static 2>/dev/null)" ]; then
|
1023
|
-
dpkg_version=$(chroot $rootfs dpkg-query -W -f='${Version}' dpkg)
|
1024
|
-
if chroot $rootfs dpkg --compare-versions $dpkg_version ge "1.16.2"; then
|
1025
|
-
chroot $rootfs dpkg --add-architecture ${hostarch}
|
1026
|
-
else
|
1027
|
-
mkdir -p ${rootfs}/etc/dpkg/dpkg.cfg.d
|
1028
|
-
echo "foreign-architecture ${hostarch}" > ${rootfs}/etc/dpkg/dpkg.cfg.d/lxc-multiarch
|
1029
|
-
fi
|
1030
|
-
|
1031
|
-
# Save existing value of MIRROR and SECURITY_MIRROR
|
1032
|
-
DEFAULT_MIRROR=$MIRROR
|
1033
|
-
DEFAULT_SECURITY_MIRROR=$SECURITY_MIRROR
|
1034
|
-
|
1035
|
-
# Write a new sources.list containing both native and multiarch entries
|
1036
|
-
> ${rootfs}/etc/apt/sources.list
|
1037
|
-
write_sourceslist $rootfs $arch "native"
|
1038
|
-
|
1039
|
-
MIRROR=$DEFAULT_MIRROR
|
1040
|
-
SECURITY_MIRROR=$DEFAULT_SECURITY_MIRROR
|
1041
|
-
write_sourceslist $rootfs $hostarch "multiarch"
|
1042
|
-
|
1043
|
-
# Finally update the lists and install upstart using the host architecture
|
1044
|
-
chroot $rootfs apt-get update
|
1045
|
-
chroot $rootfs apt-get install --force-yes -y --no-install-recommends upstart:${hostarch} mountall:${hostarch} iproute:${hostarch} isc-dhcp-client:${hostarch}
|
1046
|
-
fi
|
1047
|
-
|
1048
|
-
# rmdir /dev/shm for containers that have /run/shm
|
1049
|
-
# I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did
|
1050
|
-
# get bind mounted to the host's /run/shm. So try to rmdir
|
1051
|
-
# it, and in case that fails move it out of the way.
|
1052
|
-
if [ ! -L $rootfs/dev/shm ] && [ -d $rootfs/run/shm ] && [ -e $rootfs/dev/shm ]; then
|
1053
|
-
mv $rootfs/dev/shm $rootfs/dev/shm.bak
|
1054
|
-
ln -s /run/shm $rootfs/dev/shm
|
1055
|
-
fi
|
1056
|
-
}
|
1057
|
-
|
1058
|
-
usage()
|
1059
|
-
{
|
1060
|
-
cat <<EOF
|
1061
|
-
$1 -h|--help [-a|--arch] [--trim] [-d|--debug]
|
1062
|
-
[-F | --flush-cache] [-r|--release <release>] [ -S | --auth-key <keyfile>]
|
1063
|
-
release: the ubuntu release (e.g. precise): defaults to host release on ubuntu, otherwise uses latest LTS
|
1064
|
-
trim: make a minimal (faster, but not upgrade-safe) container
|
1065
|
-
arch: the container architecture (e.g. amd64): defaults to host arch
|
1066
|
-
auth-key: SSH Public key file to inject into container
|
1067
|
-
EOF
|
1068
|
-
return 0
|
1069
|
-
}
|
1070
|
-
|
1071
|
-
options=$(getopt -o a:b:hp:r:xn:FS:d -l arch:,help,path:,release:,trim,name:,flush-cache,auth-key:,debug -- "$@")
|
1072
|
-
if [ $? -ne 0 ]; then
|
1073
|
-
usage $(basename $0)
|
1074
|
-
exit 1
|
1075
|
-
fi
|
1076
|
-
eval set -- "$options"
|
1077
|
-
|
1078
|
-
release=precise # Default to the last Ubuntu LTS release for non-Ubuntu systems
|
1079
|
-
if [ -f /etc/lsb-release ]; then
|
1080
|
-
. /etc/lsb-release
|
1081
|
-
if [ "$DISTRIB_ID" = "Ubuntu" ]; then
|
1082
|
-
release=$DISTRIB_CODENAME
|
1083
|
-
fi
|
1084
|
-
fi
|
1085
|
-
|
1086
|
-
bindhome=
|
1087
|
-
arch=$(arch)
|
1088
|
-
|
1089
|
-
# Code taken from debootstrap
|
1090
|
-
if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then
|
1091
|
-
arch=`/usr/bin/dpkg --print-architecture`
|
1092
|
-
elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then
|
1093
|
-
arch=`/usr/bin/udpkg --print-architecture`
|
1094
|
-
else
|
1095
|
-
arch=$(arch)
|
1096
|
-
if [ "$arch" = "i686" ]; then
|
1097
|
-
arch="i386"
|
1098
|
-
elif [ "$arch" = "x86_64" ]; then
|
1099
|
-
arch="amd64"
|
1100
|
-
elif [ "$arch" = "armv7l" ]; then
|
1101
|
-
arch="armel"
|
1102
|
-
fi
|
1103
|
-
fi
|
1104
|
-
|
1105
|
-
debug=0
|
1106
|
-
trim_container=0
|
1107
|
-
hostarch=$arch
|
1108
|
-
flushcache=0
|
1109
|
-
while true
|
1110
|
-
do
|
1111
|
-
case "$1" in
|
1112
|
-
-h|--help) usage $0 && exit 0;;
|
1113
|
-
-p|--path) path=$2; shift 2;;
|
1114
|
-
-n|--name) name=$2; shift 2;;
|
1115
|
-
-F|--flush-cache) flushcache=1; shift 1;;
|
1116
|
-
-r|--release) release=$2; shift 2;;
|
1117
|
-
-a|--arch) arch=$2; shift 2;;
|
1118
|
-
-x|--trim) trim_container=1; shift 1;;
|
1119
|
-
-S|--auth-key) auth_key=$2; shift 2;;
|
1120
|
-
-d|--debug) debug=1; shift 1;;
|
1121
|
-
--) shift 1; break ;;
|
1122
|
-
*) break ;;
|
1123
|
-
esac
|
1124
|
-
done
|
1125
|
-
|
1126
|
-
if [ $debug -eq 1 ]; then
|
1127
|
-
set -x
|
1128
|
-
fi
|
1129
|
-
|
1130
|
-
if [ "$arch" == "i686" ]; then
|
1131
|
-
arch=i386
|
1132
|
-
fi
|
1133
|
-
|
1134
|
-
if [ $hostarch = "i386" -a $arch = "amd64" ]; then
|
1135
|
-
echo "can't create amd64 container on i386"
|
1136
|
-
exit 1
|
1137
|
-
fi
|
1138
|
-
|
1139
|
-
type debootstrap
|
1140
|
-
if [ $? -ne 0 ]; then
|
1141
|
-
echo "'debootstrap' command is missing"
|
1142
|
-
exit 1
|
1143
|
-
fi
|
1144
|
-
|
1145
|
-
if [ -z "$path" ]; then
|
1146
|
-
echo "'path' parameter is required"
|
1147
|
-
exit 1
|
1148
|
-
fi
|
1149
|
-
|
1150
|
-
if [ "$(id -u)" != "0" ]; then
|
1151
|
-
echo "This script should be run as 'root'"
|
1152
|
-
exit 1
|
1153
|
-
fi
|
1154
|
-
|
1155
|
-
rootfs=$path/rootfs
|
1156
|
-
|
1157
|
-
install_ubuntu $rootfs $release $flushcache
|
1158
|
-
if [ $? -ne 0 ]; then
|
1159
|
-
echo "failed to install ubuntu $release"
|
1160
|
-
exit 1
|
1161
|
-
fi
|
1162
|
-
|
1163
|
-
configure_ubuntu $rootfs $name $release
|
1164
|
-
if [ $? -ne 0 ]; then
|
1165
|
-
echo "failed to configure ubuntu $release for a container"
|
1166
|
-
exit 1
|
1167
|
-
fi
|
1168
|
-
|
1169
|
-
copy_configuration $path $rootfs $name $arch $release
|
1170
|
-
if [ $? -ne 0 ]; then
|
1171
|
-
echo "failed write configuration file"
|
1172
|
-
exit 1
|
1173
|
-
fi
|
1174
|
-
|
1175
|
-
post_process $rootfs $release $trim_container
|
1176
|
-
|
1177
|
-
finalize_user
|
1178
|
-
|
1179
|
-
TEMPLATE
|
1180
|
-
File.open(".tmp.lxc-pauper.conf",'w') do |f|
|
1181
|
-
f.puts @template
|
612
|
+
def lxc_pauper_template
|
613
|
+
require 'lxc_template'
|
614
|
+
File.open(".tmp.lxc-pauper.conf",'w') do |f|
|
615
|
+
f.puts Template.lxc
|
616
|
+
end
|
617
|
+
tmpl_dir = File.exist?('/usr/lib/lxc/templates') ? '/usr/lib/lxc/templates' : '/usr/share/lxc/templates'
|
618
|
+
system "sudo mv .tmp.lxc-pauper.conf #{tmpl_dir}/lxc-pauper"
|
619
|
+
system "sudo chmod +x #{tmpl_dir}/lxc-pauper"
|
1182
620
|
end
|
1183
|
-
tmpl_dir = File.exist?('/usr/lib/lxc/templates') ? '/usr/lib/lxc/templates' : '/usr/share/lxc/templates'
|
1184
|
-
system "sudo mv .tmp.lxc-pauper.conf #{tmpl_dir}/lxc-pauper"
|
1185
|
-
system "sudo chmod +x #{tmpl_dir}/lxc-pauper"
|
1186
|
-
end
|
1187
621
|
|
1188
622
|
class Config
|
1189
623
|
attr_reader :config
|
@@ -1197,7 +631,15 @@ end
|
|
1197
631
|
:shares => [],
|
1198
632
|
:subnet => '172.16.254',
|
1199
633
|
:chef_options => {},
|
1200
|
-
:dev_domain => nil
|
634
|
+
:dev_domain => nil,
|
635
|
+
:chef_download_url => {
|
636
|
+
:lucid => 'https://opscode-omnibus-packages.s3.amazonaws.com/ubuntu/10.04/x86_64',
|
637
|
+
:precise => 'https://opscode-omnibus-packages.s3.amazonaws.com/ubuntu/12.04/x86_64',
|
638
|
+
},
|
639
|
+
:chef_deb_name => {
|
640
|
+
:lucid => 'chef_11.0.0-1.ubuntu.10.04_amd64.deb',
|
641
|
+
:precise => 'chef_11.10.4-1.ubuntu.12.04_amd64.deb',
|
642
|
+
},
|
1201
643
|
}
|
1202
644
|
if File.exists? pauperfile
|
1203
645
|
pauperpath = File.dirname(pauperfile)
|
@@ -1251,12 +693,12 @@ end
|
|
1251
693
|
@config[:chef_server_url] = url
|
1252
694
|
end
|
1253
695
|
|
1254
|
-
def chef_download_url(url)
|
1255
|
-
@config[:chef_download_url] = url
|
696
|
+
def chef_download_url(url, release='lucid')
|
697
|
+
@config[:chef_download_url][Pauper.grok_release(release)] = url
|
1256
698
|
end
|
1257
699
|
|
1258
|
-
def chef_deb_name(name)
|
1259
|
-
@config[:chef_deb_name] = name
|
700
|
+
def chef_deb_name(name, release='lucid')
|
701
|
+
@config[:chef_deb_name][Pauper.grok_release(release)] = name
|
1260
702
|
end
|
1261
703
|
|
1262
704
|
def validation_key_path(path)
|
@@ -1295,7 +737,8 @@ end
|
|
1295
737
|
@pretty_name = pretty_name
|
1296
738
|
@config = {
|
1297
739
|
:run_list => [],
|
1298
|
-
:chef_options => {}
|
740
|
+
:chef_options => {},
|
741
|
+
:release => :lucid,
|
1299
742
|
}
|
1300
743
|
instance_eval &block
|
1301
744
|
end
|
@@ -1323,6 +766,10 @@ end
|
|
1323
766
|
def cpus(count)
|
1324
767
|
@config[:cpus] = count
|
1325
768
|
end
|
769
|
+
|
770
|
+
def release(release_s)
|
771
|
+
@config[:release] = Pauper.grok_release(release_s)
|
772
|
+
end
|
1326
773
|
end
|
1327
774
|
end
|
1328
775
|
end
|