dev-lxc 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.
@@ -0,0 +1,137 @@
1
+ require "yaml"
2
+ require 'dev-lxc'
3
+ require 'thor'
4
+
5
+ module DevLXC::CLI
6
+ class Cluster < Thor
7
+ no_commands{
8
+ def get_cluster(config_option)
9
+ config = "dev-lxc.yaml" if File.exists?("dev-lxc.yaml")
10
+ config = config_option unless config_option.nil?
11
+ raise "A cluster config file must be provided" if config.nil?
12
+ ::DevLXC::ChefCluster.new(YAML.load(IO.read(config)))
13
+ end
14
+ }
15
+
16
+ desc "init [TOPOLOGY]", "Provide a cluster config file"
17
+ def init(topology=nil)
18
+ topologies = %w(open-source standalone tier)
19
+ if topology.nil? || ! topologies.include?(topology)
20
+ topologies_with_index = topologies.map.with_index{ |a, i| [i+1, *a]}
21
+ print_table topologies_with_index
22
+ selection = ask("Which cluster topology do you want to use?", :limited_to => topologies_with_index.map{|c| c[0].to_s})
23
+ topology = topologies[selection.to_i - 1]
24
+ end
25
+ puts IO.read("#{File.dirname(__FILE__)}/../../files/configs/#{topology}.yaml")
26
+ end
27
+
28
+ desc "status", "Show status of a cluster's Chef servers"
29
+ option :config, :aliases => "-c", :desc => "Specify a cluster's YAML config file. ./dev-lxc.yaml will be used by default"
30
+ def status
31
+ get_cluster(options[:config]).status
32
+ end
33
+
34
+ desc "abspath [ROOTFS_PATH]", "Returns the absolute path to a file for each Chef server in a cluster"
35
+ option :config, :aliases => "-c", :desc => "Specify a cluster's YAML config file. ./dev-lxc.yaml will be used by default"
36
+ def abspath(rootfs_path)
37
+ puts get_cluster(options[:config]).abspath(rootfs_path).join(" ")
38
+ end
39
+
40
+ desc "run_command [COMMAND]", "Runs a command in each Chef server in a cluster"
41
+ option :config, :aliases => "-c", :desc => "Specify a cluster's YAML config file. ./dev-lxc.yaml will be used by default"
42
+ def run_command(command)
43
+ get_cluster(options[:config]).run_command(command)
44
+ end
45
+
46
+ desc "start", "Start a cluster's Chef servers"
47
+ option :config, :aliases => "-c", :desc => "Specify a cluster's YAML config file. ./dev-lxc.yaml will be used by default"
48
+ def start
49
+ get_cluster(options[:config]).start
50
+ end
51
+
52
+ desc "stop", "Stop a cluster's Chef servers"
53
+ option :config, :aliases => "-c", :desc => "Specify a cluster's YAML config file. ./dev-lxc.yaml will be used by default"
54
+ def stop
55
+ get_cluster(options[:config]).stop
56
+ end
57
+
58
+ desc "destroy", "Destroy a cluster's Chef servers"
59
+ option :config, :aliases => "-c", :desc => "Specify a cluster's YAML config file. ./dev-lxc.yaml will be used by default"
60
+ option :base, :aliases => "-b", :type => :boolean, :desc => "Destroy the cluster's base containers also"
61
+ def destroy
62
+ cluster = get_cluster(options[:config])
63
+ cluster.destroy
64
+ cluster.destroy_base_containers if options[:base]
65
+ end
66
+ end
67
+
68
+ class Server < Thor
69
+ no_commands{
70
+ def get_server(name, config_option)
71
+ config = "dev-lxc.yaml" if File.exists?("dev-lxc.yaml")
72
+ config = config_option unless config_option.nil?
73
+ raise "A cluster config file must be provided" if config.nil?
74
+ ::DevLXC::ChefServer.new(name, YAML.load(IO.read(config)))
75
+ end
76
+ }
77
+
78
+ desc "status [NAME]", "Show status of a cluster's Chef server"
79
+ option :config, :aliases => "-c", :desc => "Specify a cluster's YAML config file. ./dev-lxc.yaml will be used by default"
80
+ def status(name)
81
+ get_server(name, options[:config]).status
82
+ end
83
+
84
+ desc "abspath [NAME] [ROOTFS_PATH]", "Returns the absolute path to a file in a cluster's Chef server"
85
+ option :config, :aliases => "-c", :desc => "Specify a cluster's YAML config file. ./dev-lxc.yaml will be used by default"
86
+ def abspath(name, rootfs_path)
87
+ puts get_server(name, options[:config]).abspath(rootfs_path)
88
+ end
89
+
90
+ desc "run_command [NAME] [COMMAND]", "Runs a command in a cluster's Chef server"
91
+ option :config, :aliases => "-c", :desc => "Specify a cluster's YAML config file. ./dev-lxc.yaml will be used by default"
92
+ def run_command(name, command)
93
+ get_server(name, options[:config]).run_command(command)
94
+ end
95
+
96
+ desc "start [NAME]", "Start a cluster's Chef server"
97
+ option :config, :aliases => "-c", :desc => "Specify a cluster's YAML config file. ./dev-lxc.yaml will be used by default"
98
+ def start(name)
99
+ get_server(name, options[:config]).start
100
+ end
101
+
102
+ desc "stop [NAME]", "Stop a cluster's Chef server"
103
+ option :config, :aliases => "-c", :desc => "Specify a cluster's YAML config file. ./dev-lxc.yaml will be used by default"
104
+ def stop(name)
105
+ get_server(name, options[:config]).stop
106
+ end
107
+
108
+ desc "destroy [NAME]", "Destroy a cluster's Chef server"
109
+ option :config, :aliases => "-c", :desc => "Specify a cluster's YAML config file. ./dev-lxc.yaml will be used by default"
110
+ option :base, :aliases => "-b", :type => :boolean, :desc => "Destroy the server's base containers also"
111
+ def destroy(name)
112
+ server = get_server(name, options[:config])
113
+ server.destroy
114
+ server.destroy_base_containers if options[:base]
115
+ end
116
+ end
117
+
118
+ class DevLXC < Thor
119
+ desc "create [BASE_PLATFORM]", "Create a base platform"
120
+ def create(base_platform=nil)
121
+ base_platforms = %w(b-ubuntu-1004 b-ubuntu-1204 b-centos-5 b-centos-6)
122
+ if base_platform.nil? || ! base_platforms.include?(base_platform)
123
+ base_platforms_with_index = base_platforms.map.with_index{ |a, i| [i+1, *a]}
124
+ print_table base_platforms_with_index
125
+ selection = ask("Which base platform do you want to create?", :limited_to => base_platforms_with_index.map{|c| c[0].to_s})
126
+ base_platform = base_platforms[selection.to_i - 1]
127
+ end
128
+ ::DevLXC.create_base_platform(base_platform)
129
+ end
130
+
131
+ desc "cluster SUBCOMMAND ...ARGS", "manage Chef cluster"
132
+ subcommand "cluster", Cluster
133
+
134
+ desc "server SUBCOMMAND ...ARGS", "manage Chef server"
135
+ subcommand "server", Server
136
+ end
137
+ end
@@ -0,0 +1,62 @@
1
+ module DevLXC
2
+ class Container < LXC::Container
3
+ def start
4
+ raise "Container #{self.name} does not exist." unless self.defined?
5
+ puts "Starting container #{self.name}"
6
+ super
7
+ wait(:running, 3)
8
+ puts "Waiting for #{self.name} container's network"
9
+ ips = nil
10
+ 30.times do
11
+ ips = self.ip_addresses
12
+ break unless ips.empty?
13
+ sleep 1
14
+ end
15
+ raise "Container #{self.name} network is not available." if ips.empty?
16
+ end
17
+
18
+ def stop
19
+ puts "Stopping container #{self.name}"
20
+ super
21
+ wait("STOPPED", 3)
22
+ end
23
+
24
+ def destroy
25
+ return unless self.defined?
26
+ stop if running?
27
+ puts "Destroying container #{self.name}"
28
+ super
29
+ end
30
+
31
+ def sync_mounts(mounts)
32
+ preserved_mounts = self.config_item("lxc.mount.entry").delete_if { |m| m.end_with?("## dev-lxc ##") }
33
+ self.clear_config_item('lxc.mount.entries')
34
+ self.set_config_item("lxc.mount.entry", preserved_mounts)
35
+ mounts.each do |mount|
36
+ raise "Mount source #{mount.split.first} does not exist." unless File.exists?(mount.split.first)
37
+ puts "Adding mount entry #{mount}"
38
+ self.set_config_item("lxc.mount.entry", "#{mount} none bind,optional,create=dir 0 0 ## dev-lxc ##")
39
+ end
40
+ self.save_config
41
+ end
42
+
43
+ def run_command(command)
44
+ raise "Container #{self.name} must be running first" unless running?
45
+ attach({:wait => true, :stdin => STDIN, :stdout => STDOUT, :stderr => STDERR}) do
46
+ LXC.run_command(command)
47
+ end
48
+ end
49
+
50
+ def install_package(package_path)
51
+ raise "File #{package_path} does not exist in container #{self.name}" unless run_command("test -e #{package_path}")
52
+ puts "Installing #{package_path} in container #{self.name}"
53
+ case File.extname(package_path)
54
+ when ".deb"
55
+ install_command = "dpkg -D10 -i #{package_path}"
56
+ when ".rpm"
57
+ install_command = "rpm -Uvh #{package_path}"
58
+ end
59
+ run_command(install_command)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,3 @@
1
+ module DevLXC
2
+ VERSION = "0.1.2"
3
+ end
data/lib/dev-lxc.rb ADDED
@@ -0,0 +1,79 @@
1
+ require "fileutils"
2
+ require "digest/sha1"
3
+ require "lxc"
4
+ require "dev-lxc/container"
5
+ require "dev-lxc/chef-server"
6
+ require "dev-lxc/chef-cluster"
7
+
8
+ module DevLXC
9
+ def self.create_base_platform(base_platform_name)
10
+ base_platform = DevLXC::Container.new(base_platform_name)
11
+ if base_platform.defined?
12
+ puts "Using existing container #{base_platform.name}"
13
+ return base_platform
14
+ end
15
+ puts "Creating container #{base_platform.name}"
16
+ case base_platform.name
17
+ when "b-ubuntu-1004"
18
+ base_platform.create("download", "btrfs", 0, ["-d", "ubuntu", "-r", "lucid", "-a", "amd64"])
19
+ when "b-ubuntu-1204"
20
+ base_platform.create("download", "btrfs", 0, ["-d", "ubuntu", "-r", "precise", "-a", "amd64"])
21
+ when "b-centos-5"
22
+ base_platform.create("centos", "btrfs", 0, ["-R", "5"])
23
+ when "b-centos-6"
24
+ base_platform.create("download", "btrfs", 0, ["-d", "centos", "-r", "6", "-a", "amd64"])
25
+ end
26
+ hwaddr = '00:16:3e:' + Digest::SHA1.hexdigest(Time.now.to_s).slice(0..5).unpack('a2a2a2').join(':')
27
+ puts "Setting #{base_platform.name} container's lxc.network.0.hwaddr to #{hwaddr}"
28
+ base_platform.set_config_item("lxc.network.0.hwaddr", hwaddr)
29
+ base_platform.save_config
30
+ base_platform.start
31
+ puts "Installing packages in container #{base_platform.name}"
32
+ case base_platform.name
33
+ when "b-ubuntu-1004"
34
+ base_platform.run_command("apt-get update")
35
+ base_platform.run_command("apt-get install -y standard^ server^ vim-nox emacs23-nox curl tree")
36
+ when "b-ubuntu-1204"
37
+ base_platform.run_command("apt-get update")
38
+ base_platform.run_command("apt-get install -y standard^ server^ vim-nox emacs23-nox tree")
39
+ when "b-centos-5", "b-centos-6"
40
+ base_platform.run_command("yum install -y @base @core vim-enhanced emacs-nox tree")
41
+ end
42
+ base_platform.stop
43
+ return base_platform
44
+ end
45
+
46
+ def self.assign_ip_address(ipaddress, container_name, hwaddr)
47
+ puts "Assigning IP address #{ipaddress} to #{container_name} container's lxc.network.hwaddr #{hwaddr}"
48
+ search_file_delete_line("/etc/lxc/dhcp-hosts.conf", /(^#{hwaddr}|,#{ipaddress}$)/)
49
+ append_line_to_file("/etc/lxc/dhcp-hosts.conf", "#{hwaddr},#{ipaddress}\n")
50
+ reload_dnsmasq
51
+ end
52
+
53
+ def self.create_dns_record(api_fqdn, container_name, ipaddress)
54
+ dns_record = "#{ipaddress} #{container_name} #{api_fqdn}\n"
55
+ puts "Creating DNS record: #{dns_record}"
56
+ search_file_delete_line("/etc/lxc/addn-hosts.conf", /^#{ipaddress}\s/)
57
+ append_line_to_file("/etc/lxc/addn-hosts.conf", dns_record)
58
+ reload_dnsmasq
59
+ end
60
+
61
+ def self.reload_dnsmasq
62
+ system("pkill -HUP dnsmasq")
63
+ end
64
+
65
+ def self.search_file_delete_line(file_name, regex)
66
+ IO.write(file_name, IO.readlines(file_name).delete_if {|line| line.match(Regexp.new(regex))}.join)
67
+ end
68
+
69
+ def self.append_line_to_file(file_name, line)
70
+ content = IO.readlines(file_name)
71
+ content[-1] = content[-1].chomp + "\n"
72
+ content << line
73
+ IO.write(file_name, content.join)
74
+ end
75
+
76
+ def self.search_file_replace(file_name, regex, replace)
77
+ IO.write(file_name, IO.readlines(file_name).map {|line| line.gsub(Regexp.new(regex), replace)}.join)
78
+ end
79
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dev-lxc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jeremiah Snapp
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-03-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: thor
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: ruby-lxc
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.0.1
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.0.1
78
+ description: A tool for creating Chef server clusters using LXC containers
79
+ email:
80
+ - jeremiah@getchef.com
81
+ executables:
82
+ - dev-lxc
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - .gitignore
87
+ - Gemfile
88
+ - LICENSE
89
+ - README.md
90
+ - Rakefile
91
+ - bin/dev-lxc
92
+ - dev-lxc.gemspec
93
+ - files/configs/ha.yaml
94
+ - files/configs/open-source.yaml
95
+ - files/configs/standalone.yaml
96
+ - files/configs/tier.yaml
97
+ - files/create_users/create_users.rb
98
+ - files/create_users/default.rb
99
+ - files/create_users/knife.rb.erb
100
+ - lib/dev-lxc.rb
101
+ - lib/dev-lxc/chef-cluster.rb
102
+ - lib/dev-lxc/chef-server.rb
103
+ - lib/dev-lxc/cli.rb
104
+ - lib/dev-lxc/container.rb
105
+ - lib/dev-lxc/version.rb
106
+ homepage: https://github.com/jeremiahsnapp/dev-lxc
107
+ licenses:
108
+ - Apache2
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 1.8.23
128
+ signing_key:
129
+ specification_version: 3
130
+ summary: A tool for creating Chef server clusters using LXC containers
131
+ test_files: []
132
+ has_rdoc: