pauper 0.0.12 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +54 -10
- data/bin/pauper +29 -0
- data/lib/dhcpd.rb +1 -1
- data/lib/libvirt.rb +80 -0
- data/lib/lxc.rb +53 -0
- data/lib/pauper.rb +172 -112
- metadata +8 -6
- data/lib/client.rb.erb +0 -7
data/README
CHANGED
@@ -1,12 +1,56 @@
|
|
1
|
-
To
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
To setup a dev environment
|
2
|
+
|
3
|
+
Install 11.10
|
4
|
+
|
5
|
+
sudo apt-get install build-essential aptitude lxc bridge-utils libvirt-bin ruby openssh-server curl libssl-dev libxml2-dev libxslt-dev git-core libreadline6-dev
|
6
|
+
|
7
|
+
Install rvm
|
8
|
+
|
9
|
+
See https://rvm.io/
|
10
|
+
rvm install 1.9.3
|
11
|
+
rvm use 1.9.3 --default
|
12
|
+
source ~/.profile
|
13
|
+
|
14
|
+
gem install ohai chef
|
15
|
+
|
16
|
+
Setup .ssh, .chef, .gitconfig
|
17
|
+
https://gist.github.com/eb11025e7c0e53ef58be
|
18
|
+
|
19
|
+
mkdir fastly
|
20
|
+
cd fastly
|
21
|
+
git clone git@github.com:fastly/Chef.git
|
22
|
+
git clone git@github.com:macros/Pauper.git
|
23
|
+
git clone git@github.com:fastly/pauper-env.git
|
24
|
+
# Customizations for lxc
|
25
|
+
https://gist.github.com/d15219c4edcf0f112c1c
|
26
|
+
|
27
|
+
git clone git@github.com:fastly/Heavenly.git
|
28
|
+
touch Heavenly/heavenly.log
|
29
|
+
chmod 777 Heavenly/heavenly.log
|
30
|
+
git clone git@github.com:fastly/Northstar.git
|
31
|
+
mv Northstar northstar
|
32
|
+
git clone git@github.com:fastly/Sierra.git
|
33
|
+
git clone git@github.com:fastly/conduction.git
|
34
|
+
git clone git@github.com:fastly/Website.git
|
35
|
+
|
36
|
+
cd Pauper
|
37
|
+
gem build pauper.gemspec
|
38
|
+
gem install pauper-0.0.6.gem
|
39
|
+
knife environment create <username>-dev
|
40
|
+
(If knife cant be found, try 'source ~/.rvm/scripts/rvm')
|
41
|
+
|
42
|
+
cd ../pauper-env
|
43
|
+
pauper bootstrap
|
44
|
+
pauper start
|
45
|
+
pauper setup
|
46
|
+
|
47
|
+
* Assumes ssh user/pass in container is root as setup by lxc (TODO)
|
48
|
+
|
49
|
+
pauper bootstrap
|
50
|
+
pauper start <node>
|
51
|
+
pauper setup <node>
|
52
|
+
pauper stop <node>
|
53
|
+
|
54
|
+
The base node can be run, not normally started
|
11
55
|
|
12
56
|
DONE!
|
data/bin/pauper
CHANGED
@@ -5,6 +5,12 @@ require 'thor'
|
|
5
5
|
require 'pauper'
|
6
6
|
|
7
7
|
class CLI < Thor
|
8
|
+
desc "bootstrap", "Initialize the base image"
|
9
|
+
def bootstrap
|
10
|
+
pauper = Pauper.new
|
11
|
+
pauper.bootstrap
|
12
|
+
end
|
13
|
+
|
8
14
|
desc "destroy [NODENAME]", "Completely destroy a VM"
|
9
15
|
def destroy(node_name=nil)
|
10
16
|
pauper = Pauper.new
|
@@ -35,6 +41,29 @@ class CLI < Thor
|
|
35
41
|
end
|
36
42
|
end
|
37
43
|
|
44
|
+
desc "resume [NODENAME]", "Resume a VM"
|
45
|
+
def resume(node_name=nil)
|
46
|
+
pauper = Pauper.new
|
47
|
+
if node_name
|
48
|
+
pauper.resume(node_name)
|
49
|
+
else
|
50
|
+
pauper.resume_all
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
desc "suspend [NODENAME]", "Suspends a VM"
|
56
|
+
def suspend(node_name=nil)
|
57
|
+
pauper = Pauper.new
|
58
|
+
if node_name
|
59
|
+
pauper.suspend(node_name)
|
60
|
+
else
|
61
|
+
pauper.suspend_all
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
|
38
67
|
desc "setup [NODENAME]", "Refresh configs and run Chef on a VM"
|
39
68
|
def setup(node_name=nil)
|
40
69
|
pauper = Pauper.new
|
data/lib/dhcpd.rb
CHANGED
data/lib/libvirt.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
class LIBVIRT
|
2
|
+
attr_reader :subnet
|
3
|
+
attr_reader :ip
|
4
|
+
|
5
|
+
CONF_FILE = "/etc/libvirt/qemu/networks/pauper.xml"
|
6
|
+
|
7
|
+
def initialize(subnet)
|
8
|
+
@subnet = subnet
|
9
|
+
@ip = @subnet + '.1'
|
10
|
+
@template = ERB.new <<EOF
|
11
|
+
<network>
|
12
|
+
<name>pauper</name>
|
13
|
+
<bridge name="pauperbr%d" />
|
14
|
+
<forward/>
|
15
|
+
<ip address="<%= ip %>" netmask="255.255.255.0">
|
16
|
+
<dhcp>
|
17
|
+
<range start="<%= subnet %>.100" stop="<%= subnet %>.200" />
|
18
|
+
</dhcp>
|
19
|
+
</ip>
|
20
|
+
</network>
|
21
|
+
EOF
|
22
|
+
end
|
23
|
+
|
24
|
+
def enable
|
25
|
+
write_config
|
26
|
+
unless active?
|
27
|
+
unless loaded?
|
28
|
+
load_config
|
29
|
+
end
|
30
|
+
start_network
|
31
|
+
# The bridge needs a bit to settle
|
32
|
+
sleep 3
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def interface
|
37
|
+
`sudo virsh net-info pauper | grep Bridge`.split(%r{\s+})[1]
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def write_config
|
42
|
+
config_data = @template.result(OpenStruct.new(:ip => @ip, :subnet => @subnet).send(:binding))
|
43
|
+
File.open(".tmp.pauper.xml",'w') do |f|
|
44
|
+
f.puts config_data
|
45
|
+
end
|
46
|
+
|
47
|
+
system("sudo mv .tmp.pauper.xml #{CONF_FILE}")
|
48
|
+
end
|
49
|
+
|
50
|
+
def load_config
|
51
|
+
system("sudo virsh net-define #{CONF_FILE}")
|
52
|
+
end
|
53
|
+
|
54
|
+
def unload_config
|
55
|
+
system("sudo virsh net-undefine pauper")
|
56
|
+
end
|
57
|
+
|
58
|
+
def start_network
|
59
|
+
system("sudo rm /var/lib/misc/dnsmasq.leases")
|
60
|
+
system("sudo virsh net-start pauper >> pauper.log 2>&1")
|
61
|
+
end
|
62
|
+
|
63
|
+
def stop_network
|
64
|
+
system("sudo virsh net-destroy pauper >> pauper.log 2>&1")
|
65
|
+
end
|
66
|
+
|
67
|
+
def active?
|
68
|
+
virsh = `sudo virsh net-info pauper | grep '^Active.*yes$'`
|
69
|
+
unless virsh == ""
|
70
|
+
return true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def loaded?
|
75
|
+
virsh = `sudo virsh net-info pauper | grep '^Name.*pauper$'`
|
76
|
+
unless virsh == ""
|
77
|
+
return true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/lxc.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
class LXC
|
4
|
+
attr_accessor :interface
|
5
|
+
attr_accessor :mac
|
6
|
+
attr_reader :node_name
|
7
|
+
|
8
|
+
def initialize(node_name)
|
9
|
+
@node_name = node_name
|
10
|
+
@filename = "/var/lib/lxc/#{node_name}/config"
|
11
|
+
@mac = ''
|
12
|
+
@interface = ''
|
13
|
+
@template = ERB.new <<EOF
|
14
|
+
lxc.utsname = <%= node_name %>
|
15
|
+
lxc.pts = 1024
|
16
|
+
lxc.tty = 4
|
17
|
+
lxc.cgroup.cpu.shares = 512
|
18
|
+
lxc.rootfs = /var/lib/lxc/<%= node_name %>/rootfs
|
19
|
+
lxc.mount = /var/lib/lxc/<%= node_name %>/fstab
|
20
|
+
lxc.network.type = veth
|
21
|
+
lxc.network.name = eth0
|
22
|
+
lxc.network.link = <%= interface %>
|
23
|
+
lxc.network.hwaddr = <%= mac %>
|
24
|
+
lxc.network.flags = up
|
25
|
+
lxc.cgroup.devices.deny = a
|
26
|
+
lxc.cgroup.devices.allow = c 1:3 rwm
|
27
|
+
lxc.cgroup.devices.allow = c 1:5 rwm
|
28
|
+
lxc.cgroup.devices.allow = c 5:1 rwm
|
29
|
+
lxc.cgroup.devices.allow = c 5:0 rwm
|
30
|
+
lxc.cgroup.devices.allow = c 4:0 rwm
|
31
|
+
lxc.cgroup.devices.allow = c 4:1 rwm
|
32
|
+
lxc.cgroup.devices.allow = c 1:9 rwm
|
33
|
+
lxc.cgroup.devices.allow = c 1:8 rwm
|
34
|
+
lxc.cgroup.devices.allow = c 136:* rwm
|
35
|
+
lxc.cgroup.devices.allow = c 5:2 rwm
|
36
|
+
lxc.cgroup.devices.allow = b 7:0 rwm
|
37
|
+
lxc.cgroup.devices.allow = c 254:0 rwm
|
38
|
+
lxc.cgroup.devices.allow = c 108:0 rwm
|
39
|
+
lxc.cgroup.devices.allow = c 10:229 rwm
|
40
|
+
lxc.cgroup.devices.allow = c 10:200 rwm
|
41
|
+
EOF
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def save(filename=@filename)
|
46
|
+
config_data = @template.result(OpenStruct.new(:node_name => @node_name,
|
47
|
+
:mac => @mac, :interface => @interface ).send(:binding))
|
48
|
+
File.open(".tmp.lxc.conf",'w') do |f|
|
49
|
+
f.puts config_data
|
50
|
+
end
|
51
|
+
system "sudo mv .tmp.lxc.conf #{@filename}"
|
52
|
+
end
|
53
|
+
end
|
data/lib/pauper.rb
CHANGED
@@ -7,74 +7,123 @@ require 'fileutils'
|
|
7
7
|
require 'erb'
|
8
8
|
require 'ostruct'
|
9
9
|
|
10
|
-
require '
|
11
|
-
require '
|
10
|
+
require 'lxc'
|
11
|
+
require 'libvirt'
|
12
12
|
require 'hosts'
|
13
13
|
|
14
14
|
class Pauper
|
15
15
|
DEFAULT_PAUPERFILE = './Pauperfile'
|
16
|
-
DEFAULT_VM_PATH = File.expand_path('
|
17
|
-
|
18
|
-
VMWARE_PATH = '/Library/Application Support/VMware Fusion'
|
19
|
-
DHCPD_CONF_PATH = "#{VMWARE_PATH}/vmnet8/dhcpd.conf"
|
16
|
+
DEFAULT_VM_PATH = File.expand_path('/var/lib/lxc/')
|
20
17
|
|
21
18
|
def initialize(pauperfile=DEFAULT_PAUPERFILE)
|
22
19
|
@pauper_config = Pauper::Config.new(DEFAULT_PAUPERFILE)
|
20
|
+
network = LIBVIRT.new(@pauper_config.config[:subnet])
|
21
|
+
network.enable
|
22
|
+
@pauper_config.config[:bridge] = network.interface
|
23
23
|
end
|
24
24
|
|
25
25
|
def bootstrap
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
raise "Base already exists!" if vm_exists?("base")
|
27
|
+
system("sudo touch /var/lib/lxc/lxc.conf")
|
28
|
+
system("sudo lxc-create -n base -t ubuntu -f /var/lib/lxc/lxc.conf -- -a amd64 -r lucid")
|
29
|
+
mac = generate_mac
|
30
|
+
ip = "#{@pauper_config.config[:subnet]}.2"
|
31
|
+
|
32
|
+
lxc = LXC.new('base')
|
33
|
+
lxc.interface = @pauper_config.config[:bridge]
|
34
|
+
lxc.mac = mac
|
35
|
+
lxc.save
|
36
|
+
|
37
|
+
prepare_fstab('base')
|
38
|
+
prepare_vm_network('base',ip)
|
39
|
+
prepare_base_cache
|
40
|
+
|
41
|
+
puts "Installing chef.."
|
42
|
+
start_node('base')
|
43
|
+
chef_node = "base#{@pauper_config.config[:node_suffix]}"
|
44
|
+
|
45
|
+
cmd "knife bootstrap --bootstrap-version chef-full -N #{chef_node} -E #{@pauper_config.config[:chef_environment]} -x #{@pauper_config.config[:ssh_user]} -P #{@pauper_config.config[:ssh_password]} -r \"#{@pauper_config.config[:default_run_list].join(",")}\" #{ip}"
|
46
|
+
stop_node('base')
|
47
|
+
end
|
48
|
+
|
49
|
+
def prepare_fstab(node_name)
|
50
|
+
File.open('.tmp.fstab','w') do |f|
|
51
|
+
@pauper_config.config[:shares].each do |share_name, guest_path, host_path, options|
|
52
|
+
f.puts "#{host_path} #{DEFAULT_VM_PATH}/#{node_name}/rootfs/#{guest_path} none defaults,bind 0 0"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
system "sudo mv .tmp.fstab #{DEFAULT_VM_PATH}/#{node_name}/fstab"
|
56
|
+
end
|
57
|
+
|
58
|
+
def prepare_vm_network(node_name,ip)
|
59
|
+
host_ip = "#{@pauper_config.config[:subnet]}.1"
|
60
|
+
File.open('.tmp.interfaces', 'w') do |f|
|
61
|
+
f.puts "auto lo"
|
62
|
+
f.puts "iface lo inet loopback"
|
63
|
+
f.puts ""
|
64
|
+
f.puts "auto eth0"
|
65
|
+
f.puts "iface eth0 inet static"
|
66
|
+
f.puts " address #{ip}"
|
67
|
+
f.puts " netmask 255.255.255.0"
|
68
|
+
f.puts " gateway #{host_ip}"
|
69
|
+
end
|
70
|
+
File.open('.tmp.resolv.conf', 'w') do |f|
|
71
|
+
f.puts "nameserver #{host_ip}"
|
72
|
+
end
|
73
|
+
system "sudo mv .tmp.interfaces #{DEFAULT_VM_PATH}/#{node_name}/rootfs/etc/network/interfaces"
|
74
|
+
system "sudo mv .tmp.resolv.conf #{DEFAULT_VM_PATH}/#{node_name}/rootfs/etc/resolv.conf"
|
75
|
+
end
|
76
|
+
|
77
|
+
def prepare_base_cache
|
78
|
+
@pauper_config.config[:shares].each do |share_name, guest_path, host_path, options|
|
79
|
+
cmd "sudo mkdir -p #{host_path}"
|
80
|
+
cmd "sudo mkdir -p /var/lib/lxc/base/rootfs#{guest_path}"
|
81
|
+
end
|
82
|
+
cmd "sudo mkdir -p /var/cache/lxc/lucid/cache/apt/partial"
|
30
83
|
end
|
31
84
|
|
85
|
+
def reconfigure_ssh(node_name)
|
86
|
+
cmd "sudo chroot /var/lib/lxc/#{node_name}/rootfs/ /usr/sbin/dpkg-reconfigure openssh-server"
|
87
|
+
end
|
88
|
+
|
32
89
|
def create(node_name)
|
33
90
|
node_config = get_node_config(node_name)
|
34
91
|
|
35
92
|
raise "VM already exists!" if vm_exists?(node_name)
|
36
93
|
|
37
|
-
puts "Cloning
|
38
|
-
|
39
|
-
|
40
|
-
puts "Updating machine configuration..."
|
94
|
+
puts "Cloning base..."
|
95
|
+
clone_base(node_name)
|
41
96
|
mac = generate_mac
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
dhcpd = DHCPD.new(DHCPD_CONF_PATH)
|
54
|
-
ip = node_ip(node_config)
|
55
|
-
|
56
|
-
dhcpd.config[node_name] = {
|
57
|
-
'hardware ethernet' => mac,
|
58
|
-
'fixed-address' => ip
|
59
|
-
}
|
60
|
-
dhcpd.save
|
61
|
-
|
62
|
-
puts "Restarting dhcpd..."
|
63
|
-
dhcpd.restart
|
64
|
-
|
97
|
+
ip = "#{@pauper_config.config[:subnet]}.#{node_config.config[:last_octet]}"
|
98
|
+
|
99
|
+
lxc = LXC.new(node_name)
|
100
|
+
lxc.interface = @pauper_config.config[:bridge]
|
101
|
+
lxc.mac = mac
|
102
|
+
lxc.save
|
103
|
+
|
104
|
+
prepare_fstab(node_name)
|
105
|
+
prepare_vm_network(node_name,ip)
|
106
|
+
reconfigure_ssh(node_name)
|
65
107
|
puts "Starting..."
|
66
108
|
start_node(node_name)
|
67
|
-
|
109
|
+
sleep 3
|
68
110
|
setup(node_name)
|
69
111
|
end
|
70
112
|
|
71
113
|
def setup(node_name)
|
72
114
|
node_config = get_node_config(node_name)
|
73
|
-
|
115
|
+
config = @pauper_config.config
|
74
116
|
puts "Setting up #{node_name}..."
|
75
|
-
|
76
|
-
|
77
|
-
|
117
|
+
client_erb = ERB.new <<EOF
|
118
|
+
node_name "<%= chef_node %>"
|
119
|
+
chef_server_url "<%= config[:chef_server_url] %>"
|
120
|
+
validation_client_name "<%= config[:validation_client_name] %>"
|
121
|
+
environment "<%= config[:chef_environment] %>"
|
122
|
+
verbose_logging false
|
123
|
+
json_attribs "/etc/chef/client-config.json"
|
124
|
+
EOF
|
125
|
+
chef_node = "#{node_name}#{config[:node_suffix]}"
|
126
|
+
client_rb_data = client_erb.result(OpenStruct.new(:config => config, :chef_node => chef_node).send(:binding))
|
78
127
|
tmp_client_rb_path = ".tmp.#{node_name}.client.rb"
|
79
128
|
File.open(tmp_client_rb_path,'w') do |f|
|
80
129
|
f.puts client_rb_data
|
@@ -83,69 +132,59 @@ class Pauper
|
|
83
132
|
ip = node_ip(node_config)
|
84
133
|
|
85
134
|
chef_attribs = {
|
86
|
-
:run_list =>
|
135
|
+
:run_list => config[:default_run_list] + node_config.config[:run_list],
|
87
136
|
:ip => {
|
88
137
|
:private => ip,
|
89
138
|
:private_netmask => '255.255.255.0'
|
90
139
|
}
|
91
|
-
}.merge(
|
140
|
+
}.merge(config[:chef_options]).merge(node_config.config[:chef_options])
|
92
141
|
|
93
142
|
puts "Uploading Chef files..."
|
94
|
-
Net::SCP.start ip,
|
143
|
+
Net::SCP.start ip, config[:ssh_user], :password => config[:ssh_password] do |scp|
|
95
144
|
scp.upload! tmp_client_rb_path, "client.rb"
|
96
|
-
scp.upload!
|
145
|
+
scp.upload! config[:validation_key_path], "validation.pem"
|
97
146
|
scp.upload! StringIO.new(chef_attribs.to_json), "client-config.json"
|
98
147
|
end
|
99
148
|
|
100
149
|
FileUtils.rm(tmp_client_rb_path)
|
101
150
|
|
102
|
-
enable_shared_folders node_name
|
103
|
-
@pauper_config.config[:shares].each do |share_name, guest_path, host_path, options|
|
104
|
-
cmd "mkdir -p #{host_path}"
|
105
|
-
share_folder node_name, share_name, host_path
|
106
|
-
end
|
107
|
-
|
108
151
|
puts "Connecting over SSH..."
|
109
|
-
Net::SSH.start ip,
|
110
|
-
ssh_exec ssh, "
|
111
|
-
ssh_exec ssh, "
|
112
|
-
|
113
|
-
ssh_exec ssh, "sudo mkdir /etc/chef"
|
114
|
-
|
115
|
-
@pauper_config.config[:shares].each do |share_name, guest_path, host_path, options|
|
116
|
-
ssh_exec ssh, "sudo mkdir -p #{File.dirname(guest_path)} && sudo ln -sf /mnt/hgfs/#{share_name} #{guest_path}"
|
117
|
-
end
|
118
|
-
|
119
|
-
ssh_exec ssh, "sudo mv client.rb /etc/chef/"
|
120
|
-
ssh_exec ssh, "sudo mv validation.pem /etc/chef/"
|
121
|
-
ssh_exec ssh, "sudo mv client-config.json /etc/chef/"
|
152
|
+
Net::SSH.start ip, config[:ssh_user], :password => config[:ssh_password] do |ssh|
|
153
|
+
ssh_exec ssh, "mv client.rb /etc/chef/"
|
154
|
+
ssh_exec ssh, "mv client-config.json /etc/chef/"
|
122
155
|
|
123
|
-
ssh.exec! "
|
156
|
+
ssh.exec! "/usr/bin/chef-client" do |channel, stream, data|
|
124
157
|
print data
|
125
158
|
end
|
126
159
|
end
|
127
160
|
end
|
128
|
-
|
161
|
+
|
129
162
|
def destroy(node_name)
|
130
|
-
|
163
|
+
if node_name == 'base'
|
164
|
+
ip = @pauper_config.config[:subnet] + '.2'
|
165
|
+
else
|
166
|
+
node_config = get_node_config(node_name)
|
167
|
+
ip = node_ip(node_config)
|
168
|
+
end
|
131
169
|
|
132
170
|
if vm_exists?(node_name)
|
133
171
|
stop_node(node_name)
|
134
172
|
|
173
|
+
chef_node = "#{node_name}#{@pauper_config.config[:node_suffix]}"
|
135
174
|
puts "Removing #{node_name} from Chef..."
|
136
|
-
`knife node delete #{
|
137
|
-
`knife client delete #{
|
175
|
+
`knife node delete #{chef_node} -y`
|
176
|
+
`knife client delete #{chef_node} -y`
|
138
177
|
|
139
178
|
puts "Destroying #{node_name}..."
|
140
|
-
|
179
|
+
cmd "sudo lxc-destroy -n '#{node_name}' >> pauper.log 2>&1"
|
180
|
+
cmd "ssh-keygen -R '#{node_name}' >> pauper.log 2>&1"
|
181
|
+
cmd "ssh-keygen -R '#{ip}' >> pauper.log 2>&1"
|
141
182
|
else
|
142
183
|
puts "#{node_name} hasn't even been created yet, thusly you can't destroy it!"
|
143
184
|
end
|
144
185
|
end
|
145
186
|
|
146
187
|
def stop(node_name)
|
147
|
-
node_config = get_node_config(node_name)
|
148
|
-
|
149
188
|
if vm_running?(node_name)
|
150
189
|
puts "Stopping #{node_name}..."
|
151
190
|
stop_node(node_name)
|
@@ -155,8 +194,6 @@ class Pauper
|
|
155
194
|
end
|
156
195
|
|
157
196
|
def start(node_name)
|
158
|
-
node_config = get_node_config(node_name)
|
159
|
-
|
160
197
|
if vm_running?(node_name)
|
161
198
|
puts "Dude, #{node_name} is already running!"
|
162
199
|
elsif vm_exists?(node_name)
|
@@ -168,6 +205,25 @@ class Pauper
|
|
168
205
|
end
|
169
206
|
end
|
170
207
|
|
208
|
+
|
209
|
+
def resume(node_name)
|
210
|
+
if vm_frozen?(node_name)
|
211
|
+
puts "Resuming #{node_name}..."
|
212
|
+
resume_node(node_name)
|
213
|
+
else
|
214
|
+
puts "wtf, #{node_name} is not suspended."
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def suspend(node_name)
|
219
|
+
if vm_frozen?(node_name)
|
220
|
+
puts "Dude, #{node_name} is already suspended!"
|
221
|
+
else
|
222
|
+
puts "Suspending #{node_name}..."
|
223
|
+
suspend_node(node_name)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
171
227
|
def write_hosts
|
172
228
|
puts "Writing /etc/hosts file..."
|
173
229
|
hosts = Hosts.new
|
@@ -188,6 +244,16 @@ class Pauper
|
|
188
244
|
@pauper_config.config[:nodes].each { |n| stop(n.name) }
|
189
245
|
end
|
190
246
|
|
247
|
+
def resume_all
|
248
|
+
puts "Resuming all nodes..."
|
249
|
+
@pauper_config.config[:nodes].each { |n| resume(n.name) }
|
250
|
+
end
|
251
|
+
|
252
|
+
def suspend_all
|
253
|
+
puts "Suspending all nodes..."
|
254
|
+
@pauper_config.config[:nodes].each { |n| suspend(n.name) }
|
255
|
+
end
|
256
|
+
|
191
257
|
def destroy_all
|
192
258
|
puts "Destroying all nodes..."
|
193
259
|
@pauper_config.config[:nodes].each { |n| destroy(n.name) }
|
@@ -202,12 +268,7 @@ class Pauper
|
|
202
268
|
|
203
269
|
def node_ip(node_config)
|
204
270
|
return node_config.config[:ip] if node_config.config[:ip]
|
205
|
-
|
206
|
-
@subnet ||= begin
|
207
|
-
dhcpd = DHCPD.new(DHCPD_CONF_PATH)
|
208
|
-
dhcpd.subnet
|
209
|
-
end
|
210
|
-
|
271
|
+
@subnet = @pauper_config.config[:subnet]
|
211
272
|
return @subnet + '.' + node_config.config[:last_octet]
|
212
273
|
end
|
213
274
|
|
@@ -221,15 +282,6 @@ class Pauper
|
|
221
282
|
print ssh.exec!(cmd)
|
222
283
|
end
|
223
284
|
|
224
|
-
def enable_shared_folders(node_name)
|
225
|
-
cmd "'#{VMWARE_PATH}/vmrun' enableSharedFolders '#{node_name_to_vmx(node_name)}'"
|
226
|
-
end
|
227
|
-
|
228
|
-
def share_folder(node_name, share_name, path)
|
229
|
-
cmd "'#{VMWARE_PATH}/vmrun' removeSharedFolder '#{node_name_to_vmx(node_name)}' '#{share_name}'"
|
230
|
-
cmd "'#{VMWARE_PATH}/vmrun' addSharedFolder '#{node_name_to_vmx(node_name)}' '#{share_name}' '#{path}'"
|
231
|
-
end
|
232
|
-
|
233
285
|
def get_node_config(node_name)
|
234
286
|
node_config = @pauper_config.get_node(node_name)
|
235
287
|
raise "Alas, I don't know about a node named #{node_name.inspect}..." unless node_config
|
@@ -241,31 +293,42 @@ class Pauper
|
|
241
293
|
end
|
242
294
|
|
243
295
|
def vm_running?(node_name)
|
244
|
-
`'#{
|
296
|
+
`sudo lxc-info -n '#{node_name}'`.include?("RUNNING")
|
245
297
|
end
|
246
298
|
|
247
|
-
def
|
248
|
-
|
299
|
+
def vm_frozen?(node_name)
|
300
|
+
`sudo lxc-info -n '#{node_name}'`.include?("FROZEN")
|
249
301
|
end
|
250
302
|
|
251
|
-
def
|
252
|
-
|
303
|
+
def clone_base(node_name)
|
304
|
+
cmd "sudo cp -ax #{DEFAULT_VM_PATH}/base #{DEFAULT_VM_PATH}/#{node_name}"
|
305
|
+
cmd "sudo rm #{DEFAULT_VM_PATH}/#{node_name}/rootfs/etc/chef/client.pem"
|
306
|
+
cmd "sudo rm #{DEFAULT_VM_PATH}/#{node_name}/rootfs/etc/ssh/ssh*key*"
|
307
|
+
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"
|
253
308
|
end
|
254
309
|
|
255
|
-
def
|
256
|
-
|
310
|
+
def vm_config(node_name)
|
311
|
+
LXC.new("#{DEFAULT_VM_PATH}/#{node_name}/config")
|
257
312
|
end
|
258
313
|
|
259
314
|
def start_node(node_name)
|
260
|
-
cmd "
|
315
|
+
cmd "sudo lxc-start -d -n '#{node_name}' >> pauper.log 2>&1"
|
261
316
|
end
|
262
317
|
|
263
318
|
def stop_node(node_name)
|
264
|
-
cmd "
|
319
|
+
cmd "sudo lxc-stop -n '#{node_name}' >> pauper.log 2>&1"
|
320
|
+
end
|
321
|
+
|
322
|
+
def resume_node(node_name)
|
323
|
+
cmd "sudo lxc-unfreeze -n '#{node_name}' >> pauper.log 2>&1"
|
324
|
+
end
|
325
|
+
|
326
|
+
def suspend_node(node_name)
|
327
|
+
cmd "sudo lxc-freeze -n '#{node_name}' >> pauper.log 2>&1"
|
265
328
|
end
|
266
329
|
|
267
330
|
def generate_mac
|
268
|
-
"
|
331
|
+
"ce:71:52:" + 3.times.map { ("%2s" % rand(256).to_s(16)).gsub(' ','0') }.join(':').upcase
|
269
332
|
end
|
270
333
|
|
271
334
|
# not actually universal - doesn't fucking matter
|
@@ -277,14 +340,8 @@ class Pauper
|
|
277
340
|
}.join('-')
|
278
341
|
end
|
279
342
|
|
280
|
-
def node_name_to_vmx(node_name)
|
281
|
-
vmxes = Dir[File.join(node_name_to_vm_path(node_name), '*.vmx')]
|
282
|
-
raise "Can't find a vmx file in #{node_name_to_vm_path(node_name)}" unless vmxes[0]
|
283
|
-
vmxes[0]
|
284
|
-
end
|
285
|
-
|
286
343
|
def node_name_to_vm_path(node_name)
|
287
|
-
File.join(DEFAULT_VM_PATH, "#{node_name}
|
344
|
+
File.join(DEFAULT_VM_PATH, "#{node_name}/config")
|
288
345
|
end
|
289
346
|
|
290
347
|
def template_vm_path
|
@@ -301,7 +358,7 @@ class Pauper
|
|
301
358
|
:ssh_password => 'password',
|
302
359
|
:run_list => [],
|
303
360
|
:shares => [],
|
304
|
-
:
|
361
|
+
:subnet => '172.16.254',
|
305
362
|
:chef_options => {}
|
306
363
|
}
|
307
364
|
instance_eval File.read(pauperfile)
|
@@ -311,7 +368,6 @@ class Pauper
|
|
311
368
|
@config[:nodes].detect { |n| n.name == node_name }
|
312
369
|
end
|
313
370
|
|
314
|
-
|
315
371
|
def ssh_user(user)
|
316
372
|
@config[:ssh_user] = user
|
317
373
|
end
|
@@ -320,12 +376,16 @@ class Pauper
|
|
320
376
|
@config[:ssh_password] = pass
|
321
377
|
end
|
322
378
|
|
379
|
+
def subnet(net)
|
380
|
+
@config[:subnet] = net
|
381
|
+
end
|
382
|
+
|
323
383
|
def vmx(vmx_file)
|
324
384
|
@config[:vmx] = File.expand_path(vmx_file)
|
325
385
|
end
|
326
386
|
|
327
387
|
def node(name, &block)
|
328
|
-
@config[:nodes] << Node.new(name
|
388
|
+
@config[:nodes] << Node.new(name, name, &block)
|
329
389
|
end
|
330
390
|
|
331
391
|
def ram(megabytes)
|
@@ -361,11 +421,11 @@ class Pauper
|
|
361
421
|
end
|
362
422
|
|
363
423
|
def share(share_name, guest_path, host_path, options={})
|
364
|
-
@config[:shares] << [share_name, guest_path,
|
424
|
+
@config[:shares] << [share_name, guest_path, host_path, options]
|
365
425
|
end
|
366
426
|
|
367
427
|
def node_suffix(suffix)
|
368
|
-
@config[:
|
428
|
+
@config[:node_suffix] = suffix
|
369
429
|
end
|
370
430
|
|
371
431
|
class Node
|
metadata
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pauper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.12
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tyler McMullen
|
14
|
+
- Jason Cook
|
14
15
|
autorequire:
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date:
|
19
|
+
date: 2012-06-08 00:00:00 -07:00
|
19
20
|
default_executable:
|
20
21
|
dependencies:
|
21
22
|
- !ruby/object:Gem::Dependency
|
@@ -74,7 +75,7 @@ dependencies:
|
|
74
75
|
version: "0"
|
75
76
|
type: :runtime
|
76
77
|
version_requirements: *id004
|
77
|
-
description: Inspired by Vagrant but much much simpler. Also uses
|
78
|
+
description: Inspired by Vagrant but much much simpler. Also uses LXC, instead of Virtualbox.
|
78
79
|
email:
|
79
80
|
- tyler@fastly.com
|
80
81
|
executables:
|
@@ -85,9 +86,10 @@ extra_rdoc_files: []
|
|
85
86
|
|
86
87
|
files:
|
87
88
|
- bin/pauper
|
88
|
-
- lib/client.rb.erb
|
89
89
|
- lib/dhcpd.rb
|
90
90
|
- lib/hosts.rb
|
91
|
+
- lib/libvirt.rb
|
92
|
+
- lib/lxc.rb
|
91
93
|
- lib/pauper.rb
|
92
94
|
- lib/vmx.rb
|
93
95
|
- README
|
data/lib/client.rb.erb
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
# Managed by Pauper
|
2
|
-
|
3
|
-
node_name "<%= node_config.name %>"
|
4
|
-
chef_server_url "<%= config[:chef_server_url] %>"
|
5
|
-
validation_client_name "<%= config[:validation_client_name] %>"
|
6
|
-
environment "<%= config[:chef_environment] %>"
|
7
|
-
json_attribs "/etc/chef/client-config.json"
|