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.
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 bootstrap
43
- raise "Base already exists!" if vm_exists?("base")
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 = "#{@pauper_config.config[:subnet]}.2"
46
- ssh_clean_known_hosts('base', ip)
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 base -t pauper -f /var/lib/lxc/lxc.conf -- -a amd64 --auth-key #{public_ssh_key} -r lucid")
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('base')
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('base')
60
- prepare_vm_network('base',ip)
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/base/rootfs/ bash -c 'wget #{@pauper_config.config[:chef_download_url]}/#{@pauper_config.config[:chef_deb_name]} && dpkg -i #{@pauper_config.config[:chef_deb_name]}; rm #{@pauper_config.config[:chef_deb_name]}'"
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('base')
99
+ start_node(base_name)
67
100
  sleep 3
68
101
 
69
- chef_node = "base#{@pauper_config.config[:node_suffix]}"
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('base')
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 prepare_fstab(node_name)
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
- @pauper_config.config[:shares].each do |share_name, guest_path, host_path, options|
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/base/rootfs#{guest_path}"
164
+ cmd "sudo mkdir -p /var/lib/lxc/#{base_name}/rootfs#{guest_path}"
124
165
  end
125
- cmd "sudo mkdir -p /var/cache/lxc/lucid/cache/apt/partial"
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
- puts "Cloning base..."
138
- clone_base(node_name)
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
- if node_name == 'base'
211
- ip = @pauper_config.config[:subnet] + '.2'
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}/base #{DEFAULT_VM_PATH}/#{node_name}"
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/base/#{node_name}/g\" /var/lib/lxc/#{node_name}/rootfs/etc/hostname /var/lib/lxc/#{node_name}/rootfs/etc/chef/client.rb"
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
- def lxc_pauper_template
557
- @template = <<TEMPLATE
558
- #!/bin/bash
559
-
560
- #
561
- # template script for generating ubuntu container for LXC
562
- #
563
- # This script consolidates and extends the existing lxc ubuntu scripts
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