vagabond 0.1.0 → 0.1.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.
@@ -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"