vagabond 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,24 +2,18 @@ module Vagabond
2
2
  module Actions
3
3
  module Up
4
4
  def up
5
- if(@lxc.exists?)
6
- ui.warn "Existing container found for: #{name}. Starting..."
7
- do_start
5
+ if(lxc.exists?)
6
+ if(lxc.running?)
7
+ ui.error "Node already exists and is running: #{name}"
8
+ else
9
+ ui.info "#{ui.color('Vagabond:', :bold)} Starting node: #{ui.color(name, :green)}"
10
+ lxc.start
11
+ ui.info ui.color(' -> STARTED', :green)
12
+ end
8
13
  else
9
- do_start
10
- end
11
- end
12
-
13
- private
14
-
15
- def do_start
16
- if(lxc.running?)
17
- ui.error "LXC: #{name} is already running!"
18
- else
19
- do_create
20
- ui.info "LXC: #{name} has been started!"
21
- do_provision unless Config[:disable_auto_provision]
14
+ create
22
15
  end
16
+ do_provision unless Config[:disable_auto_provision]
23
17
  end
24
18
 
25
19
  end
@@ -1,25 +1,39 @@
1
1
  require 'mixlib/cli'
2
+ require 'chef/log'
2
3
  require 'vagabond/config'
3
4
  require 'vagabond/vagabond'
4
5
  require 'vagabond/server'
6
+ require 'vagabond/knife'
5
7
 
6
8
  module Vagabond
7
9
  class Commands
8
10
 
9
11
  include Mixlib::CLI
12
+
13
+ DEFAULT_ACTIONS = Actions.constants.map do |konst|
14
+ const = Actions.const_get(konst)
15
+ const.public_instance_methods(false) if const.is_a?(Module)
16
+ end.flatten.sort
10
17
 
11
- VALID_COMMANDS = %w(
12
- up destroy provision status freeze thaw ssh server
18
+ banner(
19
+ (
20
+ %w(Nodes:) + DEFAULT_ACTIONS.map{ |cmd|
21
+ "\tvagabond #{cmd} NODE [options]"
22
+ }.compact + %w(Server:) + (DEFAULT_ACTIONS + Server.public_instance_methods(false)).sort.map{ |cmd|
23
+ next if cmd == 'server'
24
+ "\tvagabond server #{cmd} [options]"
25
+ }.compact + ['Knife:', "\tvagabond knife COMMAND [knife_options]"] + %w(Options:)
26
+ ).join("\n")
13
27
  )
14
-
28
+
15
29
  option(:force_solo,
16
- :long => '--force-solo',
30
+ :long => '--force-configure',
17
31
  :boolean => true,
18
32
  :default => false
19
33
  )
20
34
 
21
35
  option(:disable_solo,
22
- :long => '--disable-solo',
36
+ :long => '--disable-configure',
23
37
  :boolean => true,
24
38
  :default => false
25
39
  )
@@ -40,18 +54,33 @@ module Vagabond
40
54
  :boolean => true,
41
55
  :default => false
42
56
  )
57
+
58
+ option(:debug,
59
+ :long => '--debug',
60
+ :boolean => true,
61
+ :default => false
62
+ )
63
+
64
+ option(:color,
65
+ :long => '--color',
66
+ :boolean => true
67
+ )
43
68
 
44
69
  def run!(argv)
70
+ # Turn off Chef logging since we will deal with
71
+ # our own output
72
+ Chef::Log.init('/dev/null')
45
73
  parse_options
46
74
  name_args = parse_options(argv)
47
- unless(VALID_COMMANDS.include?(name_args.first))
48
- raise ArgumentError.new('Invalid command provided!')
49
- end
50
75
  Config.merge!(config)
51
- if(name_args.first.to_s == 'server')
52
- Server.new(name_args.shift, name_args).execute
76
+ Config[:debug] = STDOUT if Config[:debug]
77
+ case name_args.first.to_s
78
+ when 'server'
79
+ Server.new(name_args.shift, name_args).send(:execute)
80
+ when 'knife'
81
+ Knife.new(name_args.shift, name_args).send(:execute)
53
82
  else
54
- Vagabond.new(name_args.shift, name_args).execute
83
+ Vagabond.new(name_args.shift, name_args).send(:execute)
55
84
  end
56
85
  end
57
86
  end
@@ -107,25 +107,27 @@ class Lxc
107
107
  # retries:: Number of discovery attempt (3 second sleep intervals)
108
108
  # Returns container IP
109
109
  def container_ip(retries=0, raise_on_fail=false)
110
- retries.to_i.times do
111
- ip = hw_detected_address || leased_address || lxc_stored_address
110
+ (retries.to_i + 1).times do
111
+ ip = proc_detected_address || hw_detected_address || leased_address || lxc_stored_address
112
112
  return ip if ip && self.class.connection_alive?(ip)
113
113
  Chef::Log.warn "LXC IP discovery: Failed to detect live IP"
114
- sleep(3)
114
+ sleep(3) if retries > 0
115
115
  end
116
116
  raise "Failed to detect live IP address for container: #{name}" if raise_on_fail
117
117
  end
118
118
 
119
119
  # Container address via lxc config file
120
120
  def lxc_stored_address
121
- ip = File.readlines(container_config).detect{|line|
122
- line.include?('ipv4')
123
- }.to_s.split('=').last.to_s.strip
124
- if(ip.to_s.empty?)
125
- nil
126
- else
127
- Chef::Log.info "LXC Discovery: Found container address via storage: #{ip}"
128
- ip
121
+ if(File.exists?(container_config))
122
+ ip = File.readlines(container_config).detect{|line|
123
+ line.include?('ipv4')
124
+ }.to_s.split('=').last.to_s.strip
125
+ if(ip.to_s.empty?)
126
+ nil
127
+ else
128
+ Chef::Log.info "LXC Discovery: Found container address via storage: #{ip}"
129
+ ip
130
+ end
129
131
  end
130
132
  end
131
133
 
@@ -151,19 +153,36 @@ class Lxc
151
153
  def hw_detected_address
152
154
  hw = File.readlines(container_config).detect{|line|
153
155
  line.include?('hwaddr')
154
- }.to_s.split('=').last.to_s.strip
155
- running? # need to do a list!
156
- ip = File.readlines('/proc/net/arp').detect{|line|
157
- line.include?(hw)
158
- }.to_s.split(' ').first.to_s.strip
159
- if(ip.to_s.empty?)
160
- nil
161
- else
162
- Chef::Log.info "LXC Discovery: Found container address via HW addr: #{ip}"
163
- ip
156
+ }.to_s.split('=').last.to_s.downcase
157
+ if(File.exists?(container_config) && !hw.empty?)
158
+ running? # need to do a list!
159
+ ip = File.readlines('/proc/net/arp').detect{|line|
160
+ line.downcase.include?(hw)
161
+ }.to_s.split(' ').first.to_s.strip
162
+ if(ip.to_s.empty?)
163
+ nil
164
+ else
165
+ Chef::Log.info "LXC Discovery: Found container address via HW addr: #{ip}"
166
+ ip
167
+ end
164
168
  end
165
169
  end
166
-
170
+
171
+ def proc_detected_address(base='/run/netns')
172
+ if(pid != -1)
173
+ Dir.mktmpdir do |t_dir|
174
+ name = File.basename(t_dir)
175
+ path = File.join(base, name)
176
+ system("#{sudo}mkdir -p #{base}")
177
+ system("#{sudo}ln -s /proc/#{pid}/ns/net #{path}")
178
+ res = %x{#{sudo}ip netns exec #{name} ip -4 addr show scope global | grep inet}
179
+ system("#{sudo}rm -f #{path}")
180
+ ip = res.strip.split(' ')[1].to_s.sub(%r{/.*$}, '').strip
181
+ ip.empty? ? nil : ip
182
+ end
183
+ end
184
+ end
185
+
167
186
  def sudo
168
187
  self.class.sudo
169
188
  end
@@ -189,6 +208,14 @@ class Lxc
189
208
  File.join(container_rootfs, path)
190
209
  end
191
210
 
211
+ def state
212
+ self.class.info(name)[:state]
213
+ end
214
+
215
+ def pid
216
+ self.class.info(name)[:pid]
217
+ end
218
+
192
219
  # Start the container
193
220
  def start
194
221
  run_command("#{sudo}lxc-start -n #{name} -d")
@@ -216,7 +243,11 @@ class Lxc
216
243
  # Shutdown the container
217
244
  def shutdown
218
245
  run_command("#{sudo}lxc-shutdown -n #{name}")
219
- run_command("#{sudo}lxc-wait -n #{name} -s STOPPED", :allow_failure_retry => 2)
246
+ run_command("#{sudo}lxc-wait -n #{name} -s STOPPED", :allow_failure => true, :timeout => 10)
247
+ if(running?)
248
+ container_command('shutdown -h now')
249
+ run_command("#{sudo}lxc-wait -n #{name} -s STOPPED")
250
+ end
220
251
  end
221
252
 
222
253
  def knife_container(cmd, ip)
@@ -239,11 +270,12 @@ class Lxc
239
270
  begin
240
271
  shlout = Mixlib::ShellOut.new(cmd,
241
272
  :logger => Chef::Log.logger,
242
- :live_stream => STDOUT
273
+ :live_stream => STDOUT,
274
+ :timeout => args[:timeout] || 1200
243
275
  )
244
276
  shlout.run_command
245
277
  shlout.error!
246
- rescue Mixlib::ShellOut::ShellCommandFailed, CommandFailed
278
+ rescue Mixlib::ShellOut::ShellCommandFailed, CommandFailed, Mixlib::ShellOut::CommandTimeout
247
279
  if(args[:allow_failure])
248
280
  true
249
281
  elsif(retries > 0)
@@ -30,6 +30,7 @@ action :create do
30
30
  #### Create container
31
31
  execute "lxc create[#{new_resource.name}]" do
32
32
  command "lxc-create -n #{new_resource.name} -t #{new_resource.template} -- #{new_resource.template_opts.to_a.flatten.join(' ')}"
33
+ environment new_resource.create_environment
33
34
  only_if do
34
35
  !new_resource._lxc.exists? && new_resource.updated_by_last_action(true)
35
36
  end
@@ -23,6 +23,7 @@ attribute :initialize_commands, :kind_of => Array, :default => []
23
23
  attribute :new_container, :kind_of => [TrueClass, FalseClass], :default => false
24
24
  attribute :template, :kind_of => String, :default => 'ubuntu'
25
25
  attribute :template_opts, :kind_of => Hash, :default => {}
26
+ attribute :create_environment, :kind_of => Hash, :default => {}
26
27
  attribute :_lxc
27
28
  # TODO: We should ultimately have support for all these templates
28
29
  #attribute :template, :equal_to => %w(busybox debian fedora opensuse sshd ubuntu ubuntu-cloud), :default => 'ubuntu'
@@ -1,2 +1,12 @@
1
1
  default[:vagabond][:bases][:ubuntu_1204][:template_options] = {'--release' => 'precise'}
2
2
  default[:vagabond][:bases][:ubuntu_1210][:template_options] = {'--release' => 'quantal'}
3
+ default[:vagabond][:bases][:centos_58][:template] = 'centos'
4
+ default[:vagabond][:bases][:centos_58][:template_options] = {'--release' => '5', '--releaseminor' => '8'}
5
+ default[:vagabond][:bases][:centos_63][:template] = 'centos'
6
+ default[:vagabond][:bases][:centos_63][:template_options] = {'--release' => '6', '--releaseminor' => '3'}
7
+ default[:vagabond][:bases][:centos_64][:template] = 'centos'
8
+ default[:vagabond][:bases][:centos_64][:template_options] = {'--release' => '6', '--releaseminor' => '4'}
9
+ default[:vagabond][:bases][:debian_6][:template] = 'debian'
10
+ default[:vagabond][:bases][:debian_6][:create_environment] = {'SUITE' => 'squeeze'}
11
+ default[:vagabond][:bases][:debian_7][:template] = 'debian'
12
+ default[:vagabond][:bases][:debian_7][:create_environment] = {'SUITE' => 'wheezy'}
@@ -0,0 +1,453 @@
1
+ #!/bin/bash
2
+
3
+ #
4
+ # template script for generating CentOS container for LXC
5
+ #
6
+
7
+ #
8
+ # lxc: linux Container library
9
+
10
+ # Authors:
11
+ # Daniel Lezcano <daniel.lezcano@free.fr>
12
+ # Ramez Hanna <rhanna@informatiq.org>
13
+
14
+ # This library is free software; you can redistribute it and/or
15
+ # modify it under the terms of the GNU Lesser General Public
16
+ # License as published by the Free Software Foundation; either
17
+ # version 2.1 of the License, or (at your option) any later version.
18
+
19
+ # This library is distributed in the hope that it will be useful,
20
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
21
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22
+ # Lesser General Public License for more details.
23
+
24
+ # You should have received a copy of the GNU Lesser General Public
25
+ # License along with this library; if not, write to the Free Software
26
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
+
28
+ #Configurations
29
+ arch=$(arch)
30
+ cache_base=/var/cache/lxc/centos/$arch
31
+ default_path=/var/lib/lxc
32
+ root_password=password
33
+
34
+ # is this centos?
35
+ [ -f /etc/redhat-release ] && is_centos=true
36
+
37
+ if [ "$arch" = "i686" ]; then
38
+ arch=i386
39
+ fi
40
+
41
+ configure_centos()
42
+ {
43
+
44
+ # disable selinux in centos
45
+ mkdir -p $rootfs_path/selinux
46
+ echo 0 > $rootfs_path/selinux/enforce
47
+
48
+ # configure the network using the dhcp
49
+ cat <<EOF > ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0
50
+ DEVICE=eth0
51
+ BOOTPROTO=dhcp
52
+ ONBOOT=yes
53
+ TYPE=Ethernet
54
+ USERCTL=yes
55
+ PEERDNS=yes
56
+ IPV6INIT=no
57
+ EOF
58
+
59
+ # set the dns
60
+ # TODO: Probably remove this
61
+ cat > $rootfs_path/etc/resolv.conf << END
62
+ # Google public DNS
63
+ nameserver 8.8.8.8
64
+ nameserver 8.8.4.4
65
+ END
66
+
67
+
68
+ # set the hostname
69
+ cat <<EOF > ${rootfs_path}/etc/sysconfig/network
70
+ NETWORKING=yes
71
+ HOSTNAME=${name}
72
+ EOF
73
+
74
+ # set minimal hosts
75
+ cat <<EOF > $rootfs_path/etc/hosts
76
+ 127.0.0.1 localhost $name
77
+ ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
78
+ EOF
79
+
80
+ sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.sysinit
81
+ sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.d/rc.sysinit
82
+ # don't mount devpts, for pete's sake
83
+ sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.sysinit
84
+ sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.d/rc.sysinit
85
+
86
+ sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.d/rc.sysinit
87
+ sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.d/rc.sysinit
88
+ sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.d/rc.sysinit
89
+
90
+ sed -i 's/^#baseurl/baseurl/g' ${rootfs_path}/etc/yum.repos.d/CentOS-Base.repo
91
+ sed -i "s/\$releasever/$release.$releaseminor/g" ${rootfs_path}/etc/yum.repos.d/CentOS-Base.repo
92
+ sed -i '115,126s/^/#/' ${rootfs_path}/etc/rc.d/init.d/halt
93
+
94
+ chroot ${rootfs_path} chkconfig udev-post off
95
+ chroot ${rootfs_path} chkconfig network on
96
+
97
+ dev_path="${rootfs_path}/dev"
98
+ rm -rf $dev_path
99
+ mkdir -p $dev_path
100
+ mknod -m 666 ${dev_path}/null c 1 3
101
+ mknod -m 666 ${dev_path}/zero c 1 5
102
+ mknod -m 666 ${dev_path}/random c 1 8
103
+ mknod -m 666 ${dev_path}/urandom c 1 9
104
+ mkdir -m 755 ${dev_path}/pts
105
+ mkdir -m 1777 ${dev_path}/shm
106
+ mknod -m 666 ${dev_path}/tty c 5 0
107
+ mknod -m 666 ${dev_path}/tty0 c 4 0
108
+ mknod -m 666 ${dev_path}/tty1 c 4 1
109
+ mknod -m 666 ${dev_path}/tty2 c 4 2
110
+ mknod -m 666 ${dev_path}/tty3 c 4 3
111
+ mknod -m 666 ${dev_path}/tty4 c 4 4
112
+ mknod -m 600 ${dev_path}/console c 5 1
113
+ mknod -m 666 ${dev_path}/full c 1 7
114
+ mknod -m 600 ${dev_path}/initctl p
115
+ mknod -m 666 ${dev_path}/ptmx c 5 2
116
+
117
+ echo "setting root passwd to $root_password"
118
+ echo "root:$root_password" | chroot $rootfs_path chpasswd
119
+
120
+ # specifying this in the initial packages doesn't always work.
121
+ # echo "installing centos-release package"
122
+ # if [ ! -f ${rootfs_path}/etc/resolv.conf ]; then
123
+ # cp /etc/resolv.conf ${rootfs_path}/etc/resolv.conf
124
+ # remove_resolv=1
125
+ # fi
126
+ # chroot ${rootfs_path} rpm --rebuilddb
127
+ # chroot ${rootfs_path} yum --releasever=${release} -y install centos-release
128
+ # if [ ! -z $remove_resolv ]; then
129
+ # rm ${rootfs_path}/etc/resolv.conf
130
+ # fi
131
+
132
+ # silence some needless startup errors
133
+ touch ${rootfs_path}/etc/fstab
134
+
135
+ # give us a console on /dev/console
136
+ sed -i 's/ACTIVE_CONSOLES=.*$/ACTIVE_CONSOLES="\/dev\/console \/dev\/tty[1-4]"/' \
137
+ ${rootfs_path}/etc/sysconfig/init
138
+
139
+ return 0
140
+ }
141
+
142
+ download_centos()
143
+ {
144
+
145
+ # check the mini centos was not already downloaded
146
+ INSTALL_ROOT=$cache/partial
147
+ mkdir -p $INSTALL_ROOT
148
+ if [ $? -ne 0 ]; then
149
+ echo "Failed to create '$INSTALL_ROOT' directory"
150
+ return 1
151
+ fi
152
+
153
+ # download a mini centos into a cache
154
+ echo "Downloading centos minimal ..."
155
+ YUM="yum --installroot $INSTALL_ROOT -y --nogpgcheck"
156
+ PKG_LIST="yum initscripts passwd rsyslog vim-minimal dhclient chkconfig"
157
+ PKG_LIST="$PKG_LIST rootfiles policycoreutils centos-release openssh-server avahi"
158
+ MIRRORLIST_URL="http://mirrorlist.centos.org/?release=$release.$releaseminor&arch=$arch&repo=os"
159
+
160
+ DOWNLOAD_OK=no
161
+ for trynumber in 1 2 3; do
162
+ [ $trynumber != 1 ] && echo "Trying again..."
163
+ MIRROR_URL=$(curl -s -S -f "$MIRRORLIST_URL" | head -n2 | tail -n1)
164
+ if [ $? -ne 0 ] || [ -z "$MIRROR_URL" ]; then
165
+ echo "Failed to get a mirror"
166
+ continue
167
+ fi
168
+ RELEASE_URL="$MIRROR_URL/Packages/centos-release-$release-$releaseminor.el6.centos.9.$arch.rpm"
169
+ echo "Fetching from $RELEASE_URL"
170
+ curl -f "$RELEASE_URL" > $INSTALL_ROOT/centos-release-$release-$releaseminor.centos.$arch.rpm
171
+ if [ $? -ne 0 ]; then
172
+ echo "Failed to download centos release rpm"
173
+ continue
174
+ fi
175
+ DOWNLOAD_OK=yes
176
+ break
177
+ done
178
+ if [ $DOWNLOAD_OK != yes ]; then
179
+ echo "Aborting"
180
+ return 1
181
+ fi
182
+
183
+ mkdir -p $INSTALL_ROOT/var/lib/rpm
184
+ rpm --root $INSTALL_ROOT --initdb
185
+ rpm --root $INSTALL_ROOT -ivh $INSTALL_ROOT/centos-release-$release-$releaseminor.centos.$arch.rpm
186
+ $YUM install $PKG_LIST
187
+ chroot $INSTALL_ROOT rm -f /var/lib/rpm/__*
188
+ chroot $INSTALL_ROOT rpm --rebuilddb
189
+
190
+ if [ $? -ne 0 ]; then
191
+ echo "Failed to download the rootfs, aborting."
192
+ return 1
193
+ fi
194
+
195
+ mv "$INSTALL_ROOT" "$cache/rootfs"
196
+ echo "Download complete."
197
+
198
+ return 0
199
+ }
200
+
201
+ copy_centos()
202
+ {
203
+
204
+ # make a local copy of the minicentos
205
+ echo -n "Copying rootfs to $rootfs_path ..."
206
+ #cp -a $cache/rootfs-$arch $rootfs_path || return 1
207
+ # i prefer rsync (no reason really)
208
+ mkdir -p $rootfs_path
209
+ rsync -a $cache/rootfs/ $rootfs_path/
210
+ return 0
211
+ }
212
+
213
+ update_centos()
214
+ {
215
+ # chroot $cache/rootfs yum -y update
216
+ echo "Updates disabled"
217
+ }
218
+
219
+ install_centos()
220
+ {
221
+ mkdir -p /var/lock/subsys/
222
+ (
223
+ flock -x 200
224
+ if [ $? -ne 0 ]; then
225
+ echo "Cache repository is busy."
226
+ return 1
227
+ fi
228
+
229
+ echo "Checking cache download in $cache/rootfs ... "
230
+ if [ ! -e "$cache/rootfs" ]; then
231
+ download_centos
232
+ if [ $? -ne 0 ]; then
233
+ echo "Failed to download 'centos base'"
234
+ return 1
235
+ fi
236
+ else
237
+ echo "Cache found. Updating..."
238
+ update_centos
239
+ if [ $? -ne 0 ]; then
240
+ echo "Failed to update 'centos base', continuing with last known good cache"
241
+ else
242
+ echo "Update finished"
243
+ fi
244
+ fi
245
+
246
+ echo "Copy $cache/rootfs to $rootfs_path ... "
247
+ copy_centos
248
+ if [ $? -ne 0 ]; then
249
+ echo "Failed to copy rootfs"
250
+ return 1
251
+ fi
252
+
253
+ return 0
254
+
255
+ ) 200>/var/lock/subsys/lxc
256
+
257
+ return $?
258
+ }
259
+
260
+ copy_configuration()
261
+ {
262
+
263
+ mkdir -p $config_path
264
+ cat <<EOF >> $config_path/config
265
+ lxc.utsname = $name
266
+ lxc.tty = 4
267
+ lxc.pts = 1024
268
+ lxc.rootfs = $rootfs_path
269
+ lxc.mount = $config_path/fstab
270
+
271
+ # uncomment the next line to run the container unconfined:
272
+ #lxc.aa_profile = unconfined
273
+
274
+ #cgroups
275
+ lxc.cgroup.devices.deny = a
276
+ # /dev/null and zero
277
+ lxc.cgroup.devices.allow = c 1:3 rwm
278
+ lxc.cgroup.devices.allow = c 1:5 rwm
279
+ # consoles
280
+ lxc.cgroup.devices.allow = c 5:1 rwm
281
+ lxc.cgroup.devices.allow = c 5:0 rwm
282
+ lxc.cgroup.devices.allow = c 4:0 rwm
283
+ lxc.cgroup.devices.allow = c 4:1 rwm
284
+ # /dev/{,u}random
285
+ lxc.cgroup.devices.allow = c 1:9 rwm
286
+ lxc.cgroup.devices.allow = c 1:8 rwm
287
+ lxc.cgroup.devices.allow = c 136:* rwm
288
+ lxc.cgroup.devices.allow = c 5:2 rwm
289
+ # rtc
290
+ lxc.cgroup.devices.allow = c 254:0 rwm
291
+ EOF
292
+
293
+ cat <<EOF > $config_path/fstab
294
+ proc proc proc nodev,noexec,nosuid 0 0
295
+ sysfs sys sysfs defaults 0 0
296
+ EOF
297
+ if [ $? -ne 0 ]; then
298
+ echo "Failed to add configuration"
299
+ return 1
300
+ fi
301
+
302
+ return 0
303
+ }
304
+
305
+ clean()
306
+ {
307
+
308
+ if [ ! -e $cache ]; then
309
+ exit 0
310
+ fi
311
+
312
+ # lock, so we won't purge while someone is creating a repository
313
+ (
314
+ flock -x 200
315
+ if [ $? != 0 ]; then
316
+ echo "Cache repository is busy."
317
+ exit 1
318
+ fi
319
+
320
+ echo -n "Purging the download cache for Centos-$release-$releaseminor..."
321
+ rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
322
+ exit 0
323
+
324
+ ) 200>/var/lock/subsys/lxc
325
+ }
326
+
327
+ usage()
328
+ {
329
+ cat <<EOF
330
+ usage:
331
+ $1 -n|--name=<container_name>
332
+ [-p|--path=<path>] [-c|--clean] [-R|--release=<Centos_release>] [-A|--arch=<arch of the container>]
333
+ [-h|--help]
334
+ Mandatory args:
335
+ -n,--name container name, used to as an identifier for that container from now on
336
+ Optional args:
337
+ -p,--path path to where the container rootfs will be created, defaults to /var/lib/lxc. The container config will go under /var/lib/lxc in that case
338
+ -c,--clean clean the cache
339
+ -R,--release Centos release for the new container. if the host is Fedora, then it will defaultto the host's release.
340
+ -m,--release-minor Minor release number for the new containar
341
+ -A,--arch NOT USED YET. Define what arch the container will be [i686,x86_64]
342
+ -h,--help print this help
343
+ EOF
344
+ return 0
345
+ }
346
+
347
+ options=$(getopt -o hp:n:cR:m: -l help,path:,name:,clean,release:,releaseminor: -- "$@")
348
+ if [ $? -ne 0 ]; then
349
+ usage $(basename $0)
350
+ exit 1
351
+ fi
352
+ eval set -- "$options"
353
+
354
+ while true
355
+ do
356
+ case "$1" in
357
+ -h|--help) usage $0 && exit 0;;
358
+ -p|--path) path=$2; shift 2;;
359
+ -n|--name) name=$2; shift 2;;
360
+ -c|--clean) clean=$2; shift 2;;
361
+ -R|--release) release=$2; shift 2;;
362
+ -m|--releaseminor) releaseminor=$2; shift 2;;
363
+ --) shift 1; break ;;
364
+ *) break ;;
365
+ esac
366
+ done
367
+
368
+ if [ ! -z "$clean" -a -z "$path" ]; then
369
+ clean || exit 1
370
+ exit 0
371
+ fi
372
+
373
+ needed_pkgs=""
374
+ type yum >/dev/null 2>&1
375
+ if [ $? -ne 0 ]; then
376
+ needed_pkgs="yum $needed_pkgs"
377
+ fi
378
+
379
+ type curl >/dev/null 2>&1
380
+ if [ $? -ne 0 ]; then
381
+ needed_pkgs="curl $needed_pkgs"
382
+ fi
383
+
384
+ if [ -n "$needed_pkgs" ]; then
385
+ echo "Missing commands: $needed_pkgs"
386
+ echo "Please install these using \"sudo apt-get install $needed_pkgs\""
387
+ exit 1
388
+ fi
389
+
390
+ if [ -z "$path" ]; then
391
+ path=$default_path
392
+ fi
393
+
394
+ if [ -z "$release" ]; then
395
+ if [ "$is_centos" ]; then
396
+ release=$(cat /etc/centos-release |awk '/^Fedora/ {print $3}')
397
+ else
398
+ echo "This is not a centos host and release missing, defaulting to 6.3. use -R|--release to specify release"
399
+ release=6
400
+ fi
401
+ fi
402
+
403
+ if [ -z "$releaseminor" ]; then
404
+ releaseminor=3
405
+ fi
406
+
407
+ if [ "$(id -u)" != "0" ]; then
408
+ echo "This script should be run as 'root'"
409
+ exit 1
410
+ fi
411
+
412
+
413
+ rootfs_path=$path/rootfs
414
+ config_path=$default_path/$name
415
+ cache=$cache_base/$release
416
+
417
+ revert()
418
+ {
419
+ echo "Interrupted, so cleaning up"
420
+ lxc-destroy -n $name
421
+ # maybe was interrupted before copy config
422
+ rm -rf $path/$name
423
+ rm -rf $default_path/$name
424
+ echo "exiting..."
425
+ exit 1
426
+ }
427
+
428
+ trap revert SIGHUP SIGINT SIGTERM
429
+
430
+ copy_configuration
431
+ if [ $? -ne 0 ]; then
432
+ echo "failed write configuration file"
433
+ exit 1
434
+ fi
435
+
436
+ install_centos
437
+ if [ $? -ne 0 ]; then
438
+ echo "failed to install centos"
439
+ exit 1
440
+ fi
441
+
442
+ configure_centos
443
+ if [ $? -ne 0 ]; then
444
+ echo "failed to configure centos for a container"
445
+ exit 1
446
+ fi
447
+
448
+
449
+ if [ ! -z $clean ]; then
450
+ clean || exit 1
451
+ exit 0
452
+ fi
453
+ echo "container rootfs and config created"