vagabond 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/CHANGELOG.md +2 -0
  2. data/README.md +94 -0
  3. data/bin/vagabond +6 -0
  4. data/lib/vagabond.rb +1 -0
  5. data/lib/vagabond/actions/create.rb +29 -0
  6. data/lib/vagabond/actions/destroy.rb +31 -0
  7. data/lib/vagabond/actions/freeze.rb +14 -0
  8. data/lib/vagabond/actions/provision.rb +31 -0
  9. data/lib/vagabond/actions/ssh.rb +13 -0
  10. data/lib/vagabond/actions/status.rb +29 -0
  11. data/lib/vagabond/actions/thaw.rb +14 -0
  12. data/lib/vagabond/actions/up.rb +27 -0
  13. data/lib/vagabond/bootstraps/server.erb +62 -0
  14. data/lib/vagabond/commands.rb +58 -0
  15. data/lib/vagabond/config.rb +7 -0
  16. data/lib/vagabond/cookbooks/lxc/CHANGELOG.md +21 -0
  17. data/lib/vagabond/cookbooks/lxc/Gemfile +3 -0
  18. data/lib/vagabond/cookbooks/lxc/Gemfile.lock +132 -0
  19. data/lib/vagabond/cookbooks/lxc/README.md +83 -0
  20. data/lib/vagabond/cookbooks/lxc/attributes/default.rb +26 -0
  21. data/lib/vagabond/cookbooks/lxc/files/default/knife_lxc +228 -0
  22. data/lib/vagabond/cookbooks/lxc/libraries/lxc.rb +279 -0
  23. data/lib/vagabond/cookbooks/lxc/libraries/lxc_expanded_resources.rb +40 -0
  24. data/lib/vagabond/cookbooks/lxc/libraries/lxc_file_config.rb +81 -0
  25. data/lib/vagabond/cookbooks/lxc/metadata.rb +11 -0
  26. data/lib/vagabond/cookbooks/lxc/providers/config.rb +82 -0
  27. data/lib/vagabond/cookbooks/lxc/providers/container.rb +342 -0
  28. data/lib/vagabond/cookbooks/lxc/providers/fstab.rb +71 -0
  29. data/lib/vagabond/cookbooks/lxc/providers/interface.rb +99 -0
  30. data/lib/vagabond/cookbooks/lxc/providers/service.rb +53 -0
  31. data/lib/vagabond/cookbooks/lxc/recipes/containers.rb +13 -0
  32. data/lib/vagabond/cookbooks/lxc/recipes/default.rb +45 -0
  33. data/lib/vagabond/cookbooks/lxc/recipes/install_dependencies.rb +15 -0
  34. data/lib/vagabond/cookbooks/lxc/recipes/knife.rb +37 -0
  35. data/lib/vagabond/cookbooks/lxc/resources/#container.rb# +28 -0
  36. data/lib/vagabond/cookbooks/lxc/resources/config.rb +19 -0
  37. data/lib/vagabond/cookbooks/lxc/resources/container.rb +28 -0
  38. data/lib/vagabond/cookbooks/lxc/resources/fstab.rb +11 -0
  39. data/lib/vagabond/cookbooks/lxc/resources/interface.rb +10 -0
  40. data/lib/vagabond/cookbooks/lxc/resources/service.rb +5 -0
  41. data/lib/vagabond/cookbooks/lxc/templates/default/client.rb.erb +13 -0
  42. data/lib/vagabond/cookbooks/lxc/templates/default/default-lxc.erb +3 -0
  43. data/lib/vagabond/cookbooks/lxc/templates/default/fstab.erb +5 -0
  44. data/lib/vagabond/cookbooks/lxc/templates/default/interface.erb +21 -0
  45. data/lib/vagabond/cookbooks/lxc/test/kitchen/Kitchenfile +7 -0
  46. data/lib/vagabond/cookbooks/lxc/test/kitchen/cookbooks/lxc_test/metadata.rb +2 -0
  47. data/lib/vagabond/cookbooks/lxc/test/kitchen/cookbooks/lxc_test/recipes/centos_lxc.rb +0 -0
  48. data/lib/vagabond/cookbooks/lxc/test/kitchen/cookbooks/lxc_test/recipes/chef-bootstrap.rb +0 -0
  49. data/lib/vagabond/cookbooks/lxc/test/kitchen/cookbooks/lxc_test/recipes/lxc_files.rb +0 -0
  50. data/lib/vagabond/cookbooks/lxc/test/kitchen/cookbooks/lxc_test/recipes/lxc_templates.rb +0 -0
  51. data/lib/vagabond/cookbooks/lxc/test/kitchen/cookbooks/lxc_test/recipes/ubuntu_lxc.rb +0 -0
  52. data/lib/vagabond/cookbooks/vagabond/attributes/default.rb +2 -0
  53. data/lib/vagabond/cookbooks/vagabond/libraries/vagabond.rb +10 -0
  54. data/lib/vagabond/cookbooks/vagabond/metadata.rb +6 -0
  55. data/lib/vagabond/cookbooks/vagabond/recipes/create.rb +3 -0
  56. data/lib/vagabond/cookbooks/vagabond/recipes/default.rb +30 -0
  57. data/lib/vagabond/internal_configuration.rb +147 -0
  58. data/lib/vagabond/server.rb +158 -0
  59. data/lib/vagabond/vagabond.rb +109 -0
  60. data/lib/vagabond/vagabondfile.rb +34 -0
  61. data/lib/vagabond/version.rb +10 -0
  62. data/vagabond.gemspec +18 -0
  63. metadata +125 -0
@@ -0,0 +1,21 @@
1
+ ## v0.1.0
2
+ * Abstracted out packages for cross-platform support later.
3
+ * Added the 'containers' recipe to create containers for the members of the node['lxc']['containers'] hash
4
+ * Add support for use of the apt::cacher-client settings if a proxy is in use.
5
+ * chef_enabled defaults to false on lxc_containers
6
+ * Better idempotency checks when building new containers
7
+ * Refactoring of lxc_service
8
+ * Container based commands run via knife::ssh providing proper logging feedback
9
+ * New networking related attributes added to lxc_container for easy basic network setups
10
+
11
+ ## v0.0.3
12
+ * Remove resource for deprecated template
13
+
14
+ ## v0.0.2
15
+ * Cleanup current config and container LWRPs
16
+ * Add new LWRPs (fstab and interface)
17
+ * Add better configuration build to prevent false updates
18
+ * Thanks to Sean Porter (https://github.com/portertech) for help debugging LWRP updates
19
+
20
+ ## v0.0.1
21
+ * Initial release
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gem 'test-kitchen'
@@ -0,0 +1,132 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ archive-tar-minitar (0.5.2)
5
+ builder (3.1.4)
6
+ bunny (0.7.9)
7
+ chef (10.18.2)
8
+ bunny (>= 0.6.0, < 0.8.0)
9
+ erubis
10
+ highline (>= 1.6.9)
11
+ json (>= 1.4.4, <= 1.6.1)
12
+ mixlib-authentication (>= 1.3.0)
13
+ mixlib-cli (>= 1.1.0)
14
+ mixlib-config (>= 1.1.2)
15
+ mixlib-log (>= 1.3.0)
16
+ mixlib-shellout
17
+ moneta (< 0.7.0)
18
+ net-ssh (~> 2.2.2)
19
+ net-ssh-multi (~> 1.1.0)
20
+ ohai (>= 0.6.0)
21
+ rest-client (>= 1.0.4, < 1.7.0)
22
+ treetop (~> 1.4.9)
23
+ uuidtools
24
+ yajl-ruby (~> 1.1)
25
+ childprocess (0.3.8)
26
+ ffi (~> 1.0, >= 1.0.11)
27
+ coderay (1.0.9)
28
+ erubis (2.7.0)
29
+ excon (0.18.3)
30
+ ffi (1.4.0)
31
+ fog (1.9.0)
32
+ builder
33
+ excon (~> 0.14)
34
+ formatador (~> 0.2.0)
35
+ mime-types
36
+ multi_json (~> 1.0)
37
+ net-scp (~> 1.0.4)
38
+ net-ssh (>= 2.1.3)
39
+ nokogiri (~> 1.5.0)
40
+ ruby-hmac
41
+ foodcritic (1.7.0)
42
+ erubis
43
+ gherkin (~> 2.11.1)
44
+ gist (~> 3.1.0)
45
+ nokogiri (~> 1.5.4)
46
+ pry (~> 0.9.8.4)
47
+ rak (~> 1.4)
48
+ treetop (~> 1.4.10)
49
+ yajl-ruby (~> 1.1.0)
50
+ formatador (0.2.4)
51
+ gherkin (2.11.5)
52
+ json (>= 1.4.6)
53
+ gist (3.1.1)
54
+ hashr (0.0.22)
55
+ highline (1.6.15)
56
+ i18n (0.6.1)
57
+ ipaddress (0.8.0)
58
+ json (1.5.5)
59
+ librarian (0.0.26)
60
+ archive-tar-minitar (>= 0.5.2)
61
+ chef (>= 0.10)
62
+ highline
63
+ thor (~> 0.15)
64
+ log4r (1.1.10)
65
+ method_source (0.7.1)
66
+ mime-types (1.21)
67
+ mixlib-authentication (1.3.0)
68
+ mixlib-log
69
+ mixlib-cli (1.2.2)
70
+ mixlib-config (1.1.2)
71
+ mixlib-log (1.4.1)
72
+ mixlib-shellout (1.1.0)
73
+ moneta (0.6.0)
74
+ multi_json (1.6.1)
75
+ net-scp (1.0.4)
76
+ net-ssh (>= 1.99.1)
77
+ net-ssh (2.2.2)
78
+ net-ssh-gateway (1.1.0)
79
+ net-ssh (>= 1.99.1)
80
+ net-ssh-multi (1.1)
81
+ net-ssh (>= 2.1.4)
82
+ net-ssh-gateway (>= 0.99.0)
83
+ nokogiri (1.5.6)
84
+ ohai (6.16.0)
85
+ ipaddress
86
+ mixlib-cli
87
+ mixlib-config
88
+ mixlib-log
89
+ mixlib-shellout
90
+ systemu
91
+ yajl-ruby
92
+ polyglot (0.3.3)
93
+ pry (0.9.8.4)
94
+ coderay (~> 1.0.5)
95
+ method_source (~> 0.7.1)
96
+ slop (>= 2.4.4, < 3)
97
+ rak (1.4)
98
+ rest-client (1.6.7)
99
+ mime-types (>= 1.16)
100
+ ruby-hmac (0.4.0)
101
+ slop (2.4.4)
102
+ systemu (2.5.2)
103
+ test-kitchen (0.7.0)
104
+ fog
105
+ foodcritic (>= 1.4.0)
106
+ hashr (~> 0.0.20)
107
+ highline (>= 1.6.9)
108
+ librarian (~> 0.0.20)
109
+ mixlib-cli (~> 1.2.2)
110
+ vagrant (~> 1.0.2)
111
+ yajl-ruby (~> 1.1.0)
112
+ thor (0.17.0)
113
+ treetop (1.4.12)
114
+ polyglot
115
+ polyglot (>= 0.3.1)
116
+ uuidtools (2.1.3)
117
+ vagrant (1.0.6)
118
+ archive-tar-minitar (= 0.5.2)
119
+ childprocess (~> 0.3.1)
120
+ erubis (~> 2.7.0)
121
+ i18n (~> 0.6.0)
122
+ json (~> 1.5.1)
123
+ log4r (~> 1.1.9)
124
+ net-scp (~> 1.0.4)
125
+ net-ssh (~> 2.2.2)
126
+ yajl-ruby (1.1.0)
127
+
128
+ PLATFORMS
129
+ ruby
130
+
131
+ DEPENDENCIES
132
+ test-kitchen
@@ -0,0 +1,83 @@
1
+ ## LXC
2
+
3
+ Manage linux containers with Chef.
4
+
5
+ ### Recipes
6
+
7
+ #### default
8
+
9
+ Installs the packages and configuration files needed for lxc on the server. If
10
+ the node uses apt-cacher-ng as a client, the server will be reused when building
11
+ containers.
12
+
13
+ #### install_dependencies
14
+
15
+ Installs the packages needed to support lxc's containers.
16
+
17
+ #### containers
18
+
19
+ This recipe creates all of the containers defined in the `['lxc']['containers']`
20
+ hash. Here is an example of an `example` container:
21
+
22
+ ```ruby
23
+ node['lxc']['containers']['example'] = {
24
+ 'template' => 'ubuntu',
25
+ 'trim' => , false,
26
+ 'debug' => , true
27
+ }
28
+ ```
29
+
30
+ You may set `trim` and `debug` to `true` if you need them (default is `false`).
31
+
32
+ Backing store file system and template options are not yet supported.
33
+
34
+ #### knife
35
+
36
+ Install and manage containers via the knife-remotelxc plugin.
37
+
38
+ ### Example
39
+
40
+ ```ruby
41
+ include_recipe 'lxc'
42
+
43
+ lxc_container 'my_container' do
44
+ action :create
45
+ validation_client 'my-validator'
46
+ server_uri 'https://api.opscode.com/organizations/myorg'
47
+ validator_pem content_from_encrypted_dbag
48
+ run_list ['role[base]']
49
+ chef_enabled true
50
+ end
51
+
52
+ lxc_container 'my_container_clone' do
53
+ action :clone
54
+ base_container 'my_container'
55
+ chef_enabled true
56
+ end
57
+
58
+ lxc_service 'my_container_clone' do
59
+ action :start
60
+ end
61
+ ```
62
+
63
+ Containers do not have to be Chef enabled but it does make them
64
+ extremely easy to configure. If you want the Omnibus installer
65
+ cached, you can set the attribute
66
+
67
+ ```ruby
68
+ node['omnibus_updater']['cache_omnibus_installer'] = true
69
+ ```
70
+
71
+ in a role or environment (default is false). The `lxc_container`
72
+ resource also provides `initialize_commands` which an array of
73
+ commands can be provided that will be run after the container is
74
+ created.
75
+
76
+ ### Repository:
77
+
78
+ * https://github.com/hw-cookbooks/lxc
79
+
80
+ ### Contributors
81
+
82
+ * Sean Porter (https://github.com/portertech)
83
+ * Matt Ray (https://github.com/mattray)
@@ -0,0 +1,26 @@
1
+ default[:lxc][:start_ipaddress] = nil
2
+ default[:lxc][:validator_pem] = nil
3
+ default[:lxc][:auto_start] = true
4
+ default[:lxc][:bridge] = 'lxcbr0'
5
+ default[:lxc][:use_bridge] = true
6
+ default[:lxc][:addr] = '10.0.3.1'
7
+ default[:lxc][:netmask] = '255.255.255.0'
8
+ default[:lxc][:network] = '10.0.3.0/24'
9
+ default[:lxc][:dhcp_range] = '10.0.3.2,10.0.3.254'
10
+ default[:lxc][:dhcp_max] = '253'
11
+ default[:lxc][:shutdown_timeout] = 120
12
+ default[:lxc][:allowed_types] = %w(debian ubuntu fedora)
13
+ default[:lxc][:container_directory] = '/var/lib/lxc'
14
+ default[:lxc][:dnsmasq_lease_file] = '/var/lib/misc/dnsmasq.leases'
15
+
16
+ default[:lxc][:knife] = {}
17
+ default[:lxc][:knife][:static_range] = ''
18
+ default[:lxc][:knife][:static_ips] = []
19
+
20
+ default[:lxc][:user_pass][:debian] = {:username => 'root', :password => 'root'}
21
+ default[:lxc][:user_pass][:ubuntu] = {:username => 'ubuntu', :password => 'ubuntu'}
22
+ default[:lxc][:user_pass][:fedora] = {:username => 'root', :password => 'root'}
23
+
24
+ default[:lxc][:packages] = %w(lxc)
25
+ default[:lxc][:mirror] = 'http://archive.ubuntu.com/ubuntu'
26
+ default[:lxc][:containers] = {}
@@ -0,0 +1,228 @@
1
+ #!/opt/chef/embedded/bin/ruby
2
+
3
+ require 'json'
4
+ require 'getoptlong'
5
+
6
+ LXC_HOME = '/var/lib/lxc'
7
+
8
+ opts = GetoptLong.new(
9
+ ['--help', '-h', GetoptLong::NO_ARGUMENT],
10
+ ['--version', '-v', GetoptLong::NO_ARGUMENT],
11
+ ['--template', '-t', GetoptLong::REQUIRED_ARGUMENT]
12
+ )
13
+
14
+ # Default
15
+ template = 'ubuntu'
16
+
17
+ opts.each do |opt, arg|
18
+ case opt
19
+ when '--help'
20
+ show_usage
21
+ exit 0
22
+ when '--version'
23
+ show_version
24
+ exit 0
25
+ when '--template'
26
+ template = arg
27
+ raise 'Unsupported template provided' unless %w(debian fedora ubuntu).include?(template)
28
+ end
29
+ end
30
+
31
+ def conf
32
+ @c ||= JSON.load(File.read('/etc/knife-lxc/config.json'))
33
+ end
34
+
35
+ def lxc_exists?(lxc_name)
36
+ current_names = Dir.glob(File.join(LXC_HOME, '*')).map{|c| File.basename(c)}
37
+ current_names.include?(lxc_name)
38
+ end
39
+
40
+ def ensure_name_availability!(name)
41
+ raise 'Name already in use' if lxc_exists?(name)
42
+ end
43
+
44
+ def available_ips
45
+ # TODO: Add range calculation
46
+ range = conf['address']['range']
47
+ if(range.to_s.empty?)
48
+ range = (range.split('-').first.split('.').last..range.split('-').last).map{|oct|
49
+ "#{range.split('-').first.split('.').slice(0,3).join('.')}.#{oct}"
50
+ }
51
+ else
52
+ range = []
53
+ end
54
+ (conf['addresses']['static'] + range).compact
55
+ end
56
+
57
+ def used_ips
58
+ Dir.glob(File.join(LXC_HOME, '*')).map{ |ctn|
59
+ File.readlines(File.join(ctn, 'rootfs', 'etc', 'network', 'interfaces')).detect{ |line|
60
+ line.include?('address')
61
+ }.to_s.split(' ').last.to_s.strip
62
+ }.reject{ |addr|
63
+ addr.empty?
64
+ }
65
+ end
66
+
67
+ def update_container_ip(name)
68
+ new_ip = (available_ips - used_ips).pop
69
+ raise 'no ips available' unless new_ip
70
+ update_network_interfaces(name, new_ip)
71
+ new_ip
72
+ end
73
+
74
+ def update_network_interfaces(name, address)
75
+ default_nm = '255.255.255.0'
76
+ (parts = address.split('.')).last.replace('1')
77
+ default_gw = parts.join('.')
78
+ File.open(File.join(LXC_HOME, name, 'rootfs', 'etc', 'network', 'interfaces'), 'w') do |file|
79
+ file.puts "auto lo eth0"
80
+ file.puts "iface lo inet loopback"
81
+ file.puts "iface eth0 inet static"
82
+ file.puts " address #{address}"
83
+ file.puts " gateway #{conf['gateway'] || default_gw}"
84
+ file.puts " netmask #{conf['netmask'] || default_nm}"
85
+ end
86
+ end
87
+
88
+ def sudoable_ubuntu(name)
89
+ path = File.join(LXC_HOME, name, 'rootfs', 'etc', 'sudoers')
90
+ content = File.readlines(path).map do |line|
91
+ if(line.start_with?('%sudo'))
92
+ '%sudo ALL=(ALL) NOPASSWD:ALL'
93
+ else
94
+ line
95
+ end
96
+ end
97
+ File.open(path, 'w') do |file|
98
+ file.write(content.join("\n"))
99
+ end
100
+ end
101
+
102
+ def clone_container(name, template)
103
+ %x{lxc-clone -o #{template}_base -n #{name}}
104
+ end
105
+
106
+ def start_container(name)
107
+ %x{lxc-start -n #{name} -d}
108
+ %x{lxc-wait -n #{name} -s RUNNING}
109
+ end
110
+
111
+ def stop_container(name)
112
+ %x{lxc-shutdown -n #{name} -d}
113
+ %x{lxc-wait -n #{name} -s STOPPED}
114
+ end
115
+
116
+ def create_lxc(lxc_name, template)
117
+ ensure_name_availability!(lxc_name)
118
+ clone_container(lxc_name, template)
119
+ address = update_container_ip(lxc_name)
120
+ # TODO: Update debian and fedora to use sudo user and remove root login
121
+ if(lxc_name == 'ubuntu')
122
+ sudoable_ubuntu(lxc_name)
123
+ end
124
+ start_container(lxc_name)
125
+ puts "LXC Node #{lxc_name} available at: #{address}"
126
+ end
127
+
128
+ def lxc_address(name)
129
+ if(File.exists?(int = File.join(LXC_HOME, name, 'rootfs', 'etc', 'network', 'interfaces')))
130
+ addr = File.readlines(int).detect{|l|l.include?('address')}.to_s.split(' ').last.to_s.strip
131
+ addr.empty? ? 'dynamic' : addr
132
+ else
133
+ 'dynamic'
134
+ end
135
+ end
136
+
137
+ def lxc_type(name)
138
+ base = File.join(LXC_HOME, name, 'rootfs', 'etc')
139
+ if(File.exists?(lsb = File.join(base, 'lsb-release')))
140
+ File.readlines(lsb).last.split('=').last.strip.gsub('"', '')
141
+ elsif(File.exists?(sys_rel = File.join(base, 'system-release')))
142
+ File.readlines(sys_rel).first.strip
143
+ elsif(File.exists?(deb_ver = File.join(base, 'debian_version')))
144
+ "Debain #{File.read(deb_ver).strip}"
145
+ else
146
+ 'UNKNOWN'
147
+ end
148
+ end
149
+
150
+ def list_lxcs
151
+ info = Hash[
152
+ *Dir.glob(File.join(LXC_HOME, '*')).map{|dir|
153
+ key = File.basename(dir)
154
+ [key, {:address => lxc_address(key), :type => lxc_type(key)}]
155
+ }.sort{|a,b|
156
+ a.first <=> b.first
157
+ }.flatten
158
+ ]
159
+ info.each do |name, info|
160
+ puts "#{name}"
161
+ puts " Type: #{info[:type]}"
162
+ puts " Address: #{info[:address]}"
163
+ end
164
+ end
165
+
166
+ def info_lxc(lxc_name)
167
+ puts "#{lxc_name}"
168
+ puts " Type: #{lxc_type(lxc_name)}"
169
+ puts " Address: #{lxc_address(lxc_name)}"
170
+ end
171
+
172
+ def delete_lxc(lxc_name)
173
+ %x{lxc-stop -n #{lxc_name}}
174
+ %x{lxc-wait -n #{lxc_name} -s STOPPED}
175
+ %x{lxc-destroy -n #{lxc_name}}
176
+ end
177
+
178
+ action = ARGV.first.to_s
179
+
180
+ case action
181
+ when 'create'
182
+ lxc_name = ARGV[1]
183
+ create_lxc(lxc_name, template)
184
+ when 'list'
185
+ list_lxcs
186
+ when 'info'
187
+ lxc_name = ARGV[1]
188
+ if(lxc_exists?(lxc_name))
189
+ info_lxc(lxc_name)
190
+ else
191
+ $stderr.puts "Requested container does not exist: #{lxc_name}"
192
+ exit 2
193
+ end
194
+ when 'start'
195
+ lxc_name = ARGV[1]
196
+ if(lxc_exists?(lxc_name))
197
+ print "Starting container #{lxc_name}... "
198
+ start_lxc(lxc_name)
199
+ puts 'started'
200
+ else
201
+ $stderr.puts "Requested container does not exist: #{lxc_name}"
202
+ exit 2
203
+ end
204
+ when 'stop'
205
+ lxc_name = ARGV[1]
206
+ if(lxc_exists?(lxc_name))
207
+ print "Stopping container #{lxc_name}... "
208
+ stop_lxc(lxc_name)
209
+ puts 'stopped'
210
+ else
211
+ $stderr.puts "Requested container does not exist: #{lxc_name}"
212
+ exit 2
213
+ end
214
+ when 'delete'
215
+ lxc_name = ARGV[1]
216
+ if(lxc_exists?(lxc_name))
217
+ print "Deleting LXC #{lxc_name}... "
218
+ destroy_lxc(lxc_name)
219
+ puts 'done'
220
+ else
221
+ $stderr.puts "Requested container does not exist: #{lxc_name}"
222
+ exit 2
223
+ end
224
+ else
225
+ $stderr.puts "ERROR: Unknown action: #{action}"
226
+ exit 1
227
+ end
228
+