toft 0.0.2

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/toft.rb ADDED
@@ -0,0 +1,38 @@
1
+ require 'toft/node_controller'
2
+ require 'toft/file_checker'
3
+ require 'toft/chef/chef_attributes'
4
+ require 'toft/chef/chef_runner'
5
+
6
+ module Toft
7
+ class << self
8
+ attr_accessor :cookbook_path, :role_path
9
+ end
10
+
11
+ def create_node(hostname, ip)
12
+ NodeController.instance.create_node(hostname, ip)
13
+ end
14
+
15
+ def find(hostname)
16
+ NodeController.instance.nodes[hostname]
17
+ end
18
+
19
+ def destroy_node(hostname)
20
+ NodeController.instance.destroy_node(hostname)
21
+ end
22
+
23
+ def node_count
24
+ NodeController.instance.nodes.size
25
+ end
26
+ end
27
+
28
+ class NilClass
29
+ def blank?
30
+ true
31
+ end
32
+ end
33
+
34
+ class String
35
+ def blank?
36
+ empty?
37
+ end
38
+ end
@@ -0,0 +1,11 @@
1
+ echo "deb http://apt.opscode.com/ `lsb_release -cs`-0.10 main" | tee /etc/apt/sources.list.d/opscode.list
2
+
3
+ mkdir -p /etc/apt/trusted.gpg.d
4
+ gpg --keyserver keys.gnupg.net --recv-keys 83EF826A
5
+ gpg --export packages@opscode.com | tee /etc/apt/trusted.gpg.d/opscode-keyring.gpg > /dev/null
6
+ apt-get update
7
+ apt-get install ucf --force-yes -y
8
+ yes | apt-get install opscode-keyring --force-yes -y # permanent upgradeable keyring
9
+
10
+ export DEBIAN_FRONTEND=noninteractive
11
+ apt-get install chef --force-yes -qy
@@ -0,0 +1,79 @@
1
+ function load_rvm {
2
+ cat <<-EOF >> ~/.profile
3
+ [[ -s ~/.rvm/scripts/rvm ]] && . ~/.rvm/scripts/rvm
4
+ EOF
5
+ . ~/.profile
6
+ }
7
+
8
+ function install_rvm {
9
+ log "installing rvm"
10
+ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
11
+ echo 'export rvm_project_rvmrc=1' >> $HOME/.rvmrc
12
+ load_rvm
13
+ }
14
+
15
+ function check_rvm {
16
+ load_rvm
17
+ hash rvm || install_rvm
18
+ log "rvm installed"
19
+ }
20
+
21
+ function fix_rvm_readline_for_macos_tiger {
22
+ if [[ `uname` == 'Darwin' ]] && [[ `uname -r` == 11* ]]; then
23
+ (cd "$HOME/.rvm/src/readline-6.0" && \
24
+ sed -i "" -e"s/darwin\[89\]\*\|darwin10\*/darwin\[89\]\*\|darwin1\[01\]\*/g" support/shobj-conf && \
25
+ ./configure --prefix="$HOME/.rvm/usr/" && \
26
+ make clean && \
27
+ make && \
28
+ make install)
29
+ fi
30
+ }
31
+
32
+ function install_xslt {
33
+ [[ -d "$HOME/.rvm/usr/include/libxslt" ]] || \
34
+ ( cd /tmp && \
35
+ rm -rf libxslt-1.1.26 && \
36
+ wget -c ftp://xmlsoft.org/libxml2/libxslt-1.1.26.tar.gz && \
37
+ tar -zxvf libxslt-1.1.26.tar.gz && \
38
+ cd libxslt-1.1.26 && \
39
+ ./configure --prefix="$HOME/.rvm/usr" --with-libxml-prefix="$HOME/.rvm/usr" && \
40
+ make && \
41
+ make install )
42
+ }
43
+
44
+ function install_ruby {
45
+ log "installing ruby"
46
+ rvm pkg install libxml2 && \
47
+ rvm pkg install openssl && \
48
+ rvm pkg install ncurses && \
49
+ rvm pkg install readline && \
50
+ fix_rvm_readline_for_macos_tiger && \
51
+ install_xslt && \
52
+ rvm install ruby-1.8.7-p352 -C "--with-readline-dir=$HOME/.rvm/usr --with-xml-dir=$HOME/.rvm/usr --with-openssl-dir=$HOME/.rvm/usr" && \
53
+ rvm use 1.8.7-p352 &&
54
+ }
55
+
56
+ function check_ruby {
57
+ rvm list | grep 1.8.7-p352 > /dev/null || install_ruby
58
+ log "ruby installed"
59
+ }
60
+
61
+ function install_bundler {
62
+ log "installing bundler"
63
+ gem sources | grep "http://rubygems.org/" || gem sources -a http://rubygems.org/ && \
64
+ gem sources | grep "http://gems.rubyforge.org/" || gem sources -a http://gems.rubyforge.org/ && \
65
+ gem install bundler --no-ri --no-rdoc
66
+ }
67
+
68
+ function check_bundler {
69
+ which bundle | grep 1.8.7-p352 > /dev/null || install_bundler
70
+ log "bundler installed"
71
+ }
72
+
73
+ function ruby_environment {
74
+ check_rvm && \
75
+ check_ruby && \
76
+ check_bundler
77
+ }
78
+
79
+ ruby_environment
@@ -0,0 +1 @@
1
+ default[:network][:gateway_ip] = "192.168.20.1"
@@ -0,0 +1,61 @@
1
+ #!/bin/bash
2
+
3
+ cache="/var/cache/lxc/ubuntu"
4
+ suite=lucid
5
+
6
+ arch=$(arch)
7
+ if [ "$arch" == "x86_64" ]; then
8
+ arch=amd64
9
+ fi
10
+
11
+ if [ "$arch" == "i686" ]; then
12
+ arch=i386
13
+ fi
14
+
15
+ if [ -e "$cache/$suite-$arch.tar.gz" ]; then
16
+ echo "Cache rootfs already exists!"
17
+ exit 0
18
+ fi
19
+
20
+ chef_packages=ruby,rubygems1.8,ruby-dev,libopenssl-ruby,build-essential,wget,ssl-cert
21
+ packages=dialog,apt,apt-utils,resolvconf,iproute,inetutils-ping,dhcp3-client,ssh,lsb-release,wget,gpgv,gnupg,sudo,$chef_packages
22
+
23
+ # check the mini ubuntu was not already downloaded
24
+ mkdir -p "$cache/partial-$arch"
25
+ if [ $? -ne 0 ]; then
26
+ echo "Failed to create '$cache/partial-$arch' directory"
27
+ exit 1
28
+ fi
29
+
30
+ # download a mini ubuntu into a cache
31
+ echo "Downloading ubuntu minimal ..."
32
+ debootstrap --verbose --variant=minbase --components=main,universe --arch=$arch --include=$packages $suite $cache/partial-$arch
33
+ if [ $? -ne 0 ]; then
34
+ echo "Failed to download the rootfs, aborting."
35
+ exit 1
36
+ fi
37
+
38
+ mv "$cache/partial-$arch" "$cache/rootfs-$arch"
39
+ echo "Download complete."
40
+
41
+ # install chef
42
+ cat <<EOF > "$cache/rootfs-$arch/tmp/install-chef-ubuntu.sh"
43
+ echo "deb http://apt.opscode.com/ $suite-0.10 main" | tee /etc/apt/sources.list.d/opscode.list
44
+
45
+ mkdir -p /etc/apt/trusted.gpg.d
46
+ gpg --keyserver keys.gnupg.net --recv-keys 83EF826A
47
+ gpg --export packages@opscode.com | tee /etc/apt/trusted.gpg.d/opscode-keyring.gpg > /dev/null
48
+ apt-get update
49
+ apt-get install ucf --force-yes -y
50
+ yes | apt-get install opscode-keyring --force-yes -y # permanent upgradeable keyring
51
+
52
+ export DEBIAN_FRONTEND=noninteractive
53
+ apt-get install chef --force-yes -qy
54
+ EOF
55
+ chroot "$cache/rootfs-$arch" bash /tmp/install-chef-ubuntu.sh
56
+
57
+ # compress root image
58
+ (cd $cache/rootfs-$arch && tar zcf $suite-$arch.tar.gz .)
59
+ mv $cache/rootfs-$arch/$suite-$arch.tar.gz $cache
60
+
61
+
@@ -0,0 +1,42 @@
1
+ %w{lxc bridge-utils debootstrap}.each do |pkg|
2
+ package "#{pkg}"
3
+ end
4
+
5
+ bash "set up networking" do
6
+ code <<-EOH
7
+ brctl addbr br0
8
+ ifconfig br0 #{node.network.gateway_ip} netmask 255.255.255.0 up
9
+ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
10
+ sysctl -w net.ipv4.ip_forward=1
11
+ EOH
12
+ not_if "ip link ls dev br0"
13
+ end
14
+
15
+ directory "/cgroup" do
16
+ action :create
17
+ end
18
+
19
+ mount "/cgroup" do
20
+ device "cgroup"
21
+ fstype "cgroup"
22
+ pass 0
23
+ action [:mount, :enable]
24
+ end
25
+
26
+ template "/usr/lib/lxc/templates/lxc-lucid-chef" do
27
+ source "lxc-lucid-chef"
28
+ mode "0755"
29
+ action :create
30
+ end
31
+
32
+ cookbook_file "/usr/local/bin/lxc-create-ubuntu-image" do
33
+ source "lxc-create-ubuntu-image"
34
+ mode "0755"
35
+ end
36
+
37
+ bash "create ubuntu rootfs image ... this will take a while" do
38
+ code <<-EOH
39
+ /usr/local/bin/lxc-create-ubuntu-image
40
+ EOH
41
+ end
42
+
@@ -0,0 +1,328 @@
1
+ #!/bin/bash
2
+
3
+ configure_ubuntu()
4
+ {
5
+ rootfs=$1
6
+ hostname=$2
7
+
8
+ # add host root ssh access
9
+ mkdir $rootfs/root/.ssh
10
+ chmod 0600 $rootfs/root/.ssh
11
+ cat <<-EOF > $rootfs/root/.ssh/authorized_keys
12
+ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDCguB7XL3ARzLZYLsIMZe4UUO371m+H5C6V8MhtmSlgXtgHDo7eZhNSm5zCeoyGd32OKeLxuxCCEkXfDDF1aa2a6twcASE3pmWNdnBS7auiOH4P7g+eQ4Aw9v7DdESbIVgHF/NDiAEFFdmApYNM3oCX2FhEVNVKxkkIokUr4axYFJzmJ6Xoi5Sd8JtPC85FZVXqDucZDnHQlOcCkbSo0UOmsWQGwtu8eUHoDeUG0dB8ntb9xlBeLctdrAPhuFYCX8IfFkdcakkzv61ETPbKE6g9wdTDC/TEep7/AHGYmarziRnwKiVOL1jnE1coOJLqy8wOC3dKGmRZy9D4sTc+FRV root insecure public key
13
+ EOF
14
+
15
+ # copy host resolve
16
+ rm $rootfs/etc/resolv.conf
17
+ cp /etc/resolv.conf $rootfs/etc/resolv.conf
18
+
19
+ # add default route to host
20
+ cat <<EOF > $rootfs/etc/rc.local
21
+ #!/bin/sh -e
22
+ route add default gw <%= node.network.gateway_ip %>
23
+ exit 0
24
+ EOF
25
+
26
+ # disable selinux in ubuntu
27
+ mkdir -p $rootfs/selinux
28
+ echo 0 > $rootfs/selinux/enforce
29
+
30
+ # set the hostname
31
+ cat <<EOF > $rootfs/etc/hostname
32
+ $hostname
33
+ EOF
34
+ # set minimal hosts
35
+ cat <<EOF > $rootfs/etc/hosts
36
+ 127.0.0.1 localhost $hostname
37
+ EOF
38
+
39
+ # provide the lxc service
40
+ cat <<EOF > $rootfs/etc/init/lxc.conf
41
+ # fake some events needed for correct startup other services
42
+
43
+ description "Container Upstart"
44
+
45
+ start on startup
46
+
47
+ script
48
+ rm -rf /var/run/*.pid
49
+ rm -rf /var/run/network/*
50
+ /sbin/initctl emit stopped JOB=udevtrigger --no-wait
51
+ /sbin/initctl emit started JOB=udev --no-wait
52
+ end script
53
+ EOF
54
+
55
+ # fix buggus runlevel with sshd
56
+ cat <<EOF > $rootfs/etc/init/ssh.conf
57
+ # ssh - OpenBSD Secure Shell server
58
+ #
59
+ # The OpenSSH server provides secure shell access to the system.
60
+
61
+ description "OpenSSH server"
62
+
63
+ start on filesystem
64
+ stop on runlevel [!2345]
65
+
66
+ expect fork
67
+ respawn
68
+ respawn limit 10 5
69
+ umask 022
70
+ # replaces SSHD_OOM_ADJUST in /etc/default/ssh
71
+ oom never
72
+
73
+ pre-start script
74
+ test -x /usr/sbin/sshd || { stop; exit 0; }
75
+ test -e /etc/ssh/sshd_not_to_be_run && { stop; exit 0; }
76
+ test -c /dev/null || { stop; exit 0; }
77
+
78
+ mkdir -p -m0755 /var/run/sshd
79
+ end script
80
+
81
+ # if you used to set SSHD_OPTS in /etc/default/ssh, you can change the
82
+ # 'exec' line here instead
83
+ exec /usr/sbin/sshd
84
+ EOF
85
+
86
+ cat <<EOF > $rootfs/etc/init/console.conf
87
+ # console - getty
88
+ #
89
+ # This service maintains a console on tty1 from the point the system is
90
+ # started until it is shut down again.
91
+
92
+ start on stopped rc RUNLEVEL=[2345]
93
+ stop on runlevel [!2345]
94
+
95
+ respawn
96
+ exec /sbin/getty -8 38400 /dev/console
97
+ EOF
98
+
99
+ cat <<EOF > $rootfs/lib/init/fstab
100
+ # /lib/init/fstab: lxc system fstab
101
+ none /spu spufs gid=spu,optional 0 0
102
+ none /tmp none defaults 0 0
103
+ none /var/lock tmpfs nodev,noexec,nosuid,showthrough 0 0
104
+ none /lib/init/rw tmpfs mode=0755,nosuid,optional 0 0
105
+ EOF
106
+
107
+
108
+
109
+ # reconfigure some services
110
+ if [ -z "$LANG" ]; then
111
+ chroot $rootfs locale-gen en_US.UTF-8
112
+ chroot $rootfs update-locale LANG=en_US.UTF-8
113
+ else
114
+ chroot $rootfs locale-gen $LANG
115
+ chroot $rootfs update-locale LANG=$LANG
116
+ fi
117
+
118
+ # remove pointless services in a container
119
+ chroot $rootfs /usr/sbin/update-rc.d -f ondemand remove
120
+
121
+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls u*.conf); do mv $f $f.orig; done'
122
+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls tty[2-9].conf); do mv $f $f.orig; done'
123
+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls plymouth*.conf); do mv $f $f.orig; done'
124
+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls hwclock*.conf); do mv $f $f.orig; done'
125
+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls module*.conf); do mv $f $f.orig; done'
126
+
127
+ echo "Set root password to 'root'"
128
+ echo "root:root" | chroot $rootfs chpasswd
129
+
130
+ return 0
131
+ }
132
+
133
+ copy_ubuntu()
134
+ {
135
+ cache=$1
136
+ arch=$2
137
+ rootfs=$3
138
+
139
+ # make a local copy of the miniubuntu
140
+ echo -n "Extracting rootfs image to $rootfs ..."
141
+ mkdir $rootfs
142
+ tar zxf $cache/lucid-$arch.tar.gz -C $rootfs || return 1
143
+ return 0
144
+ }
145
+
146
+ install_ubuntu()
147
+ {
148
+ cache="/var/cache/lxc/ubuntu"
149
+ rootfs=$1
150
+ mkdir -p /var/lock/subsys/
151
+ (
152
+ flock -n -x 200
153
+ if [ $? -ne 0 ]; then
154
+ echo "Cache repository is busy."
155
+ return 1
156
+ fi
157
+
158
+ arch=$(arch)
159
+ if [ "$arch" == "x86_64" ]; then
160
+ arch=amd64
161
+ fi
162
+
163
+ if [ "$arch" == "i686" ]; then
164
+ arch=i386
165
+ fi
166
+
167
+ echo "Checking image cache in $cache/rootfs-$arch ... "
168
+ if [ ! -e "$cache/rootfs-$arch" ]; then
169
+ if [ $? -ne 0 ]; then
170
+ echo "Failed to download 'ubuntu base'"
171
+ return 1
172
+ fi
173
+ fi
174
+
175
+ copy_ubuntu $cache $arch $rootfs
176
+ if [ $? -ne 0 ]; then
177
+ echo "Failed to copy rootfs"
178
+ return 1
179
+ fi
180
+
181
+ return 0
182
+
183
+ ) 200>/var/lock/subsys/lxc
184
+
185
+ return $?
186
+ }
187
+
188
+ copy_configuration()
189
+ {
190
+ path=$1
191
+ rootfs=$2
192
+ name=$3
193
+
194
+ cat <<EOF >> $path/config
195
+ lxc.utsname = $name
196
+
197
+ lxc.tty = 4
198
+ lxc.pts = 1024
199
+ lxc.rootfs = $rootfs
200
+ lxc.mount = $path/fstab
201
+
202
+ lxc.cgroup.devices.deny = a
203
+ # /dev/null and zero
204
+ lxc.cgroup.devices.allow = c 1:3 rwm
205
+ lxc.cgroup.devices.allow = c 1:5 rwm
206
+ # consoles
207
+ lxc.cgroup.devices.allow = c 5:1 rwm
208
+ lxc.cgroup.devices.allow = c 5:0 rwm
209
+ lxc.cgroup.devices.allow = c 4:0 rwm
210
+ lxc.cgroup.devices.allow = c 4:1 rwm
211
+ # /dev/{,u}random
212
+ lxc.cgroup.devices.allow = c 1:9 rwm
213
+ lxc.cgroup.devices.allow = c 1:8 rwm
214
+ lxc.cgroup.devices.allow = c 136:* rwm
215
+ lxc.cgroup.devices.allow = c 5:2 rwm
216
+ # rtc
217
+ lxc.cgroup.devices.allow = c 254:0 rwm
218
+ EOF
219
+
220
+ cat <<EOF > $path/fstab
221
+ proc $rootfs/proc proc nodev,noexec,nosuid 0 0
222
+ devpts $rootfs/dev/pts devpts defaults 0 0
223
+ sysfs $rootfs/sys sysfs defaults 0 0
224
+ EOF
225
+
226
+ if [ $? -ne 0 ]; then
227
+ echo "Failed to add configuration"
228
+ return 1
229
+ fi
230
+
231
+ return 0
232
+ }
233
+
234
+ clean()
235
+ {
236
+ cache="/var/cache/lxc/ubuntu"
237
+
238
+ if [ ! -e $cache ]; then
239
+ exit 0
240
+ fi
241
+
242
+ # lock, so we won't purge while someone is creating a repository
243
+ (
244
+ flock -n -x 200
245
+ if [ $? != 0 ]; then
246
+ echo "Cache repository is busy."
247
+ exit 1
248
+ fi
249
+
250
+ echo -n "Purging the download cache..."
251
+ rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
252
+ exit 0
253
+
254
+ ) 200>/var/lock/subsys/lxc
255
+ }
256
+
257
+ usage()
258
+ {
259
+ cat <<EOF
260
+ $1 -h|--help -p|--path=<path> --clean
261
+ EOF
262
+ return 0
263
+ }
264
+
265
+ options=$(getopt -o hp:n:c -l help,path:,name:,clean -- "$@")
266
+ if [ $? -ne 0 ]; then
267
+ usage $(basename $0)
268
+ exit 1
269
+ fi
270
+ eval set -- "$options"
271
+
272
+ while true
273
+ do
274
+ case "$1" in
275
+ -h|--help) usage $0 && exit 0;;
276
+ -p|--path) path=$2; shift 2;;
277
+ -n|--name) name=$2; shift 2;;
278
+ -c|--clean) clean=$2; shift 2;;
279
+ --) shift 1; break ;;
280
+ *) break ;;
281
+ esac
282
+ done
283
+
284
+ if [ ! -z "$clean" -a -z "$path" ]; then
285
+ clean || exit 1
286
+ exit 0
287
+ fi
288
+
289
+ type debootstrap
290
+ if [ $? -ne 0 ]; then
291
+ echo "'debootstrap' command is missing"
292
+ exit 1
293
+ fi
294
+
295
+ if [ -z "$path" ]; then
296
+ echo "'path' parameter is required"
297
+ exit 1
298
+ fi
299
+
300
+ if [ "$(id -u)" != "0" ]; then
301
+ echo "This script should be run as 'root'"
302
+ exit 1
303
+ fi
304
+
305
+ rootfs=$path/rootfs
306
+
307
+ install_ubuntu $rootfs
308
+ if [ $? -ne 0 ]; then
309
+ echo "failed to install ubuntu"
310
+ exit 1
311
+ fi
312
+
313
+ configure_ubuntu $rootfs $name
314
+ if [ $? -ne 0 ]; then
315
+ echo "failed to configure ubuntu for a container"
316
+ exit 1
317
+ fi
318
+
319
+ copy_configuration $path $rootfs $name
320
+ if [ $? -ne 0 ]; then
321
+ echo "failed write configuration file"
322
+ exit 1
323
+ fi
324
+
325
+ if [ ! -z $clean ]; then
326
+ clean || exit 1
327
+ exit 0
328
+ fi
@@ -0,0 +1,4 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+ $:.unshift(File.dirname(__FILE__))
3
+
4
+ require 'toft/chef/chef_attributes'
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+ require 'cucumber/ast/table'
3
+
4
+ describe "ChefAttributes" do
5
+ it "should parse chef dot connected attributes" do
6
+ ca = Toft::ChefAttributes.new(Cucumber::Ast::Table.new([[]]))
7
+ ca.add_attribute "one.two.three", "some"
8
+ ca.add_attribute "one.four", "another"
9
+ ca.attributes["one"]["two"]["three"].should == "some"
10
+ ca.attributes["one"]["four"].should == "another"
11
+ end
12
+
13
+ it "should parse cucumber chef attributes ast table" do
14
+ table = Cucumber::Ast::Table.new([
15
+ ["key", "value"],
16
+ ["one.four", "one"],
17
+ ["one.two.three", "some"]
18
+ ])
19
+ ca = Toft::ChefAttributes.new(table)
20
+ ca.attributes["one"]["four"].should == "one"
21
+ ca.attributes["one"]["two"]["three"].should == "some"
22
+ end
23
+
24
+ it "should return json" do
25
+ table = Cucumber::Ast::Table.new([
26
+ ["key", "value"],
27
+ ["one.four", "one"],
28
+ ["one.two.three", "some"]
29
+ ])
30
+ ca = Toft::ChefAttributes.new(table)
31
+ ca.to_json.should == "{\"one\":{\"two\":{\"three\":\"some\"},\"four\":\"one\"}}"
32
+ end
33
+ end