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.
- data/CHANGELOG.md +11 -0
- data/README.md +90 -27
- data/lib/vagabond/actions/create.rb +16 -15
- data/lib/vagabond/actions/destroy.rb +18 -7
- data/lib/vagabond/actions/freeze.rb +9 -4
- data/lib/vagabond/actions/provision.rb +20 -8
- data/lib/vagabond/actions/rebuild.rb +18 -0
- data/lib/vagabond/actions/ssh.rb +8 -3
- data/lib/vagabond/actions/start.rb +18 -0
- data/lib/vagabond/actions/status.rb +23 -6
- data/lib/vagabond/actions/thaw.rb +9 -4
- data/lib/vagabond/actions/up.rb +10 -16
- data/lib/vagabond/commands.rb +40 -11
- data/lib/vagabond/cookbooks/lxc/libraries/lxc.rb +57 -25
- data/lib/vagabond/cookbooks/lxc/providers/container.rb +1 -0
- data/lib/vagabond/cookbooks/lxc/resources/container.rb +1 -0
- data/lib/vagabond/cookbooks/vagabond/attributes/default.rb +10 -0
- data/lib/vagabond/cookbooks/vagabond/files/default/lxc-centos +453 -0
- data/lib/vagabond/cookbooks/vagabond/recipes/default.rb +30 -3
- data/lib/vagabond/helpers.rb +18 -0
- data/lib/vagabond/internal_configuration.rb +18 -13
- data/lib/vagabond/knife.rb +36 -0
- data/lib/vagabond/server.rb +88 -81
- data/lib/vagabond/vagabond.rb +20 -15
- data/lib/vagabond/version.rb +1 -1
- data/vagabond-0.1.0.gem +0 -0
- metadata +8 -3
- data/lib/vagabond/cookbooks/vagabond/recipes/create.rb +0 -3
data/lib/vagabond/actions/up.rb
CHANGED
@@ -2,24 +2,18 @@ module Vagabond
|
|
2
2
|
module Actions
|
3
3
|
module Up
|
4
4
|
def up
|
5
|
-
if(
|
6
|
-
|
7
|
-
|
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
|
-
|
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
|
data/lib/vagabond/commands.rb
CHANGED
@@ -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
|
-
|
12
|
-
|
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-
|
30
|
+
:long => '--force-configure',
|
17
31
|
:boolean => true,
|
18
32
|
:default => false
|
19
33
|
)
|
20
34
|
|
21
35
|
option(:disable_solo,
|
22
|
-
:long => '--disable-
|
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
|
52
|
-
|
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
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
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.
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
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", :
|
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"
|