mccloud 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.gitignore +5 -0
  2. data/.rvmrc +4 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +74 -0
  5. data/README.md +123 -0
  6. data/Rakefile +5 -0
  7. data/bin/mccloud +116 -0
  8. data/lib/mccloud.rb +2 -0
  9. data/lib/mccloud/command/boot.rb +12 -0
  10. data/lib/mccloud/command/bootstrap.rb +31 -0
  11. data/lib/mccloud/command/command.rb +21 -0
  12. data/lib/mccloud/command/destroy.rb +19 -0
  13. data/lib/mccloud/command/halt.rb +19 -0
  14. data/lib/mccloud/command/init.rb +7 -0
  15. data/lib/mccloud/command/multi.rb +53 -0
  16. data/lib/mccloud/command/provision.rb +28 -0
  17. data/lib/mccloud/command/reload.rb +11 -0
  18. data/lib/mccloud/command/server.rb +30 -0
  19. data/lib/mccloud/command/ssh.rb +46 -0
  20. data/lib/mccloud/command/status.rb +31 -0
  21. data/lib/mccloud/command/suspend.rb +15 -0
  22. data/lib/mccloud/command/up.rb +65 -0
  23. data/lib/mccloud/config.rb +47 -0
  24. data/lib/mccloud/configurator/lb.rb +26 -0
  25. data/lib/mccloud/configurator/mccloud.rb +13 -0
  26. data/lib/mccloud/configurator/vm.rb +37 -0
  27. data/lib/mccloud/generators.rb +28 -0
  28. data/lib/mccloud/provisioner/chef_solo.rb +149 -0
  29. data/lib/mccloud/provisioner/puppet.rb +39 -0
  30. data/lib/mccloud/provisioner/vagrant/base.rb +63 -0
  31. data/lib/mccloud/provisioner/vagrant/chef.rb +130 -0
  32. data/lib/mccloud/provisioner/vagrant/chef_server.rb +103 -0
  33. data/lib/mccloud/provisioner/vagrant/chef_solo.rb +142 -0
  34. data/lib/mccloud/provisioner/vagrant/puppet.rb +137 -0
  35. data/lib/mccloud/provisioner/vagrant/puppet_server.rb +55 -0
  36. data/lib/mccloud/provisioner/vagrant/shell.rb +52 -0
  37. data/lib/mccloud/session.rb +199 -0
  38. data/lib/mccloud/templates/Mccloudfilet +44 -0
  39. data/lib/mccloud/type/forwarding.rb +11 -0
  40. data/lib/mccloud/type/lb.rb +34 -0
  41. data/lib/mccloud/type/vm.rb +46 -0
  42. data/lib/mccloud/util/iterator.rb +21 -0
  43. data/lib/mccloud/util/platform.rb +29 -0
  44. data/lib/mccloud/util/rsync.rb +21 -0
  45. data/lib/mccloud/util/ssh.rb +167 -0
  46. data/lib/mccloud/version.rb +3 -0
  47. data/mccloud.gemspec +37 -0
  48. data/ruby-bootstrap.sh +11 -0
  49. data/ruby-bootstrap2.sh +39 -0
  50. metadata +297 -0
@@ -0,0 +1,149 @@
1
+ require 'mccloud/util/rsync'
2
+ require 'mccloud/util/ssh'
3
+ module Mccloud
4
+ module Provisioner
5
+ class ChefSolo
6
+ attr_accessor :cookbooks_path
7
+ attr_accessor :role_path
8
+ attr_accessor :provisioning_path
9
+ attr_accessor :json
10
+ attr_reader :roles
11
+ attr_accessor :node_name
12
+ attr_accessor :log_level
13
+ attr_accessor :http_proxy
14
+ attr_accessor :http_proxy_user
15
+ attr_accessor :http_proxy_pass
16
+ attr_accessor :https_proxy
17
+ attr_accessor :https_proxy_user
18
+ attr_accessor :https_proxy_pass
19
+ attr_accessor :no_proxy
20
+
21
+ def initialize
22
+ @provisioning_path="/tmp/mccloud-chef"
23
+ @json={ :instance_role => "mccloud"}
24
+ end
25
+
26
+ def run(vm)
27
+ puts "we ran mylord"
28
+ json=@json.to_json
29
+ puts json
30
+ cooks=Array.new
31
+ @cookbooks_path.each do |cook|
32
+ cooks << File.join("/tmp/"+File.basename(cook))
33
+ end
34
+ cookpath="cookbook_path [\""+cooks.join("\",\"")+"\"]"
35
+ loglevel="loglevel :debug"
36
+ configfile=['file_cache_path "/var/chef-solo"',cookpath,loglevel]
37
+ vm.instance.scp(StringIO.new(json),"/tmp/dna.json")
38
+ vm.instance.scp(StringIO.new(configfile.join("\n")),"/tmp/solo.rb")
39
+
40
+ # Share the cookbooks
41
+ cookbooks_path.each do |path|
42
+ Mccloud::Util.rsync(path,vm,vm.instance)
43
+ end
44
+
45
+ puts "Running chef-solo"
46
+ options={ :port => 22, :keys => [ vm.key ], :paranoid => false, :keys_only => true}
47
+ Mccloud::Util.ssh(vm.instance.public_ip_address,vm.user,options,"sudo chef-solo -c /tmp/solo.rb -j /tmp/dna.json -l debug")
48
+
49
+ end
50
+ # Returns the run list for the provisioning
51
+ def run_list
52
+ json[:run_list] ||= []
53
+ end
54
+ # Sets the run list to the specified value
55
+ def run_list=(value)
56
+ json[:run_list] = value
57
+ end
58
+ def add_role(name)
59
+ name = "role[#{name}]" unless name =~ /^role\[(.+?)\]$/
60
+ run_list << name
61
+ end
62
+ def add_recipe(name)
63
+ name = "recipe[#{name}]" unless name =~ /^recipe\[(.+?)\]$/
64
+ run_list << name
65
+ end
66
+
67
+ def setup_config(template, filename, template_vars)
68
+ config_file = TemplateRenderer.render(template, {
69
+ :log_level => config.log_level.to_sym,
70
+ :http_proxy => config.http_proxy,
71
+ :http_proxy_user => config.http_proxy_user,
72
+ :http_proxy_pass => config.http_proxy_pass,
73
+ :https_proxy => config.https_proxy,
74
+ :https_proxy_user => config.https_proxy_user,
75
+ :https_proxy_pass => config.https_proxy_pass,
76
+ :no_proxy => config.no_proxy
77
+ }.merge(template_vars))
78
+
79
+ # file_cache_path "/var/chef-solo"
80
+ # cookbook_path "/var/chef-solo/cookbooks"
81
+
82
+ #vm.ssh.upload!(StringIO.new(config_file), File.join(config.provisioning_path, filename))
83
+ end
84
+
85
+ def setup_json
86
+
87
+ json = Mccloud::Config.config.chef.json.to_json
88
+ #vm.ssh.upload!(StringIO.new(json), File.join(config.provisioning_path, "dna.json"))
89
+ return json
90
+ end
91
+
92
+ def prepare
93
+ share_cookbook_folders
94
+ share_role_folders
95
+ end
96
+
97
+ def provision!
98
+ verify_binary("chef-solo")
99
+ chown_provisioning_folder
100
+ setup_json
101
+ setup_solo_config
102
+ run_chef_solo
103
+ end
104
+
105
+ def share_cookbook_folders
106
+ host_cookbook_paths.each_with_index do |cookbook, i|
107
+ env.config.vm.share_folder("v-csc-#{i}", cookbook_path(i), cookbook)
108
+ end
109
+ end
110
+
111
+ def share_role_folders
112
+ host_role_paths.each_with_index do |role, i|
113
+ env.config.vm.share_folder("v-csr-#{i}", role_path(i), role)
114
+ end
115
+ end
116
+
117
+ def setup_solo_config
118
+ setup_config("chef_solo_solo", "solo.rb", {
119
+ :node_name => config.node_name,
120
+ :provisioning_path => config.provisioning_path,
121
+ :cookbooks_path => cookbooks_path,
122
+ :log_level => :debug,
123
+ :recipe_url => config.recipe_url,
124
+ :roles_path => roles_path,
125
+ })
126
+ end
127
+ def run_chef_solo
128
+ commands = ["cd #{config.provisioning_path}", "chef-solo -c solo.rb -j dna.json"]
129
+
130
+ env.ui.info I18n.t("vagrant.provisioners.chef.running_solo")
131
+ vm.ssh.execute do |ssh|
132
+ ssh.sudo!(commands) do |channel, type, data|
133
+ if type == :exit_status
134
+ ssh.check_exit_status(data, commands)
135
+ else
136
+ env.ui.info("#{data}: #{type}")
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end #Module Provisioners
143
+ end #Module Mccloud
144
+
145
+
146
+ #cookbook_path "/etc/chef/recipes/cookbooks"
147
+ #log_level :info
148
+ #file_store_path "/etc/chef/recipes/"
149
+ #file_cache_path "/etc/chef/recipes/"
@@ -0,0 +1,39 @@
1
+ require 'mccloud/util/rsync'
2
+ require 'mccloud/util/ssh'
3
+ module Mccloud
4
+ module Provisioner
5
+ class Puppet
6
+
7
+ attr_accessor :manifest_file
8
+ attr_accessor :manifests_path
9
+ attr_accessor :module_path
10
+ attr_accessor :pp_path
11
+ attr_accessor :options
12
+
13
+ def initialize
14
+ @manifest_file = nil
15
+ @manifests_path = "manifests"
16
+ @module_path = nil
17
+ @pp_path = "/tmp/vagrant-puppet"
18
+ @options = []
19
+ end
20
+
21
+ def run(vm)
22
+ # @module_paths.each do |from, to|
23
+ # Mccloud::Util.rsync(path,vm,vm.instance)
24
+ # end
25
+
26
+ # @manifests_paths.each do |from, to|
27
+ # Mccloud::Util.rsync(path,vm,vm.instance)
28
+ # end
29
+ vm.instance.ssh("mkdir -p #{@pp_path}")
30
+ vm.instance.scp(@manifest_file,"#{@pp_path}/manifest.pp")
31
+
32
+ puts "Running puppet"
33
+ options={ :port => 22, :keys => [ vm.key ], :paranoid => false, :keys_only => true}
34
+ Mccloud::Util.ssh(vm.instance.public_ip_address,vm.user,options,"sudo puppet #{@pp_path}/manifest.pp")
35
+
36
+ end
37
+ end #Class
38
+ end #Module Provisioners
39
+ end #Module Mccloud
@@ -0,0 +1,63 @@
1
+ module Vagrant
2
+ module Provisioners
3
+ # The base class for a "provisioner." A provisioner is responsible for
4
+ # provisioning a Vagrant system. This has been abstracted out to provide
5
+ # support for multiple solutions such as Chef Solo, Chef Client, and
6
+ # Puppet.
7
+ class Base
8
+ include Vagrant::Util
9
+
10
+ # The environment which provisioner is running in. This is a
11
+ # {Vagrant::Action::Environment}
12
+ attr_reader :action_env
13
+
14
+ # The configuration for this provisioner. This will be an instance of
15
+ # the `Config` class which is part of the provisioner.
16
+ attr_reader :config
17
+
18
+ # Registers a provisioner with a given shortcut. This allows that provisioner
19
+ # to be referenced with the shortcut.
20
+ #
21
+ # @param [Symbol] shortcut
22
+ def self.register(shortcut)
23
+ registered[shortcut] = self
24
+ end
25
+
26
+ # Returns the provisioner associated with the given shortcut.
27
+ def self.registered
28
+ @@registered ||= {}
29
+ end
30
+
31
+ def initialize(env, config)
32
+ @action_env = env
33
+ @config = config
34
+ end
35
+
36
+ # Returns the actual {Vagrant::Environment} which this provisioner
37
+ # represents.
38
+ #
39
+ # @return [Vagrant::Environment]
40
+ def env
41
+ action_env.env
42
+ end
43
+
44
+ # Returns the VM which this provisioner is working on.
45
+ #
46
+ # @return [Vagrant::VM]
47
+ def vm
48
+ env.vm
49
+ end
50
+
51
+ # This is the method called to "prepare" the provisioner. This is called
52
+ # before any actions are run by the action runner (see {Vagrant::Actions::Runner}).
53
+ # This can be used to setup shared folders, forward ports, etc. Whatever is
54
+ # necessary on a "meta" level.
55
+ def prepare; end
56
+
57
+ # This is the method called to provision the system. This method
58
+ # is expected to do whatever necessary to provision the system (create files,
59
+ # SSH, etc.)
60
+ def provision!; end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,130 @@
1
+ module Vagrant
2
+ module Provisioners
3
+ # This class is a base class where the common functionality shared between
4
+ # chef-solo and chef-client provisioning are stored. This is **not an actual
5
+ # provisioner**. Instead, {ChefSolo} or {ChefServer} should be used.
6
+ class Chef < Base
7
+ def prepare
8
+ raise ChefError, :invalid_provisioner
9
+ end
10
+
11
+ def verify_binary(binary)
12
+ vm.ssh.execute do |ssh|
13
+ # Checks for the existence of chef binary and error if it
14
+ # doesn't exist.
15
+ ssh.sudo!("which #{binary}", :error_class => ChefError, :_key => :chef_not_detected, :binary => binary)
16
+ end
17
+ end
18
+
19
+ def chown_provisioning_folder
20
+ vm.ssh.execute do |ssh|
21
+ ssh.sudo!("mkdir -p #{config.provisioning_path}")
22
+ ssh.sudo!("chown #{env.config.ssh.username} #{config.provisioning_path}")
23
+ end
24
+ end
25
+
26
+ def setup_config(template, filename, template_vars)
27
+ config_file = TemplateRenderer.render(template, {
28
+ :log_level => config.log_level.to_sym,
29
+ :http_proxy => config.http_proxy,
30
+ :http_proxy_user => config.http_proxy_user,
31
+ :http_proxy_pass => config.http_proxy_pass,
32
+ :https_proxy => config.https_proxy,
33
+ :https_proxy_user => config.https_proxy_user,
34
+ :https_proxy_pass => config.https_proxy_pass,
35
+ :no_proxy => config.no_proxy
36
+ }.merge(template_vars))
37
+
38
+ vm.ssh.upload!(StringIO.new(config_file), File.join(config.provisioning_path, filename))
39
+ end
40
+
41
+ def setup_json
42
+ env.ui.info I18n.t("vagrant.provisioners.chef.json")
43
+
44
+ # Set up initial configuration
45
+ data = {
46
+ :config => env.config.to_hash,
47
+ :directory => env.config.vm.shared_folders["v-root"][:guestpath],
48
+ }
49
+
50
+ # And wrap it under the "vagrant" namespace
51
+ data = { :vagrant => data }
52
+
53
+ # Merge with the "extra data" which isn't put under the
54
+ # vagrant namespace by default
55
+ data.merge!(config.json)
56
+
57
+ json = data.to_json
58
+
59
+ vm.ssh.upload!(StringIO.new(json), File.join(config.provisioning_path, "dna.json"))
60
+ end
61
+ end
62
+
63
+ class Chef < Base
64
+ class ChefError < Errors::VagrantError
65
+ error_namespace("vagrant.provisioners.chef")
66
+ end
67
+ end
68
+
69
+ class Chef < Base
70
+ # This is the configuration which is available through `config.chef`
71
+ class Config < Vagrant::Config::Base
72
+ # Shared config
73
+ attr_accessor :node_name
74
+ attr_accessor :provisioning_path
75
+ attr_accessor :log_level
76
+ attr_accessor :json
77
+ attr_accessor :http_proxy
78
+ attr_accessor :http_proxy_user
79
+ attr_accessor :http_proxy_pass
80
+ attr_accessor :https_proxy
81
+ attr_accessor :https_proxy_user
82
+ attr_accessor :https_proxy_pass
83
+ attr_accessor :no_proxy
84
+
85
+ def initialize
86
+ @provisioning_path = "/tmp/vagrant-chef"
87
+ @log_level = :info
88
+ @json = { :instance_role => "vagrant" }
89
+ @http_proxy = nil
90
+ @http_proxy_user = nil
91
+ @http_proxy_pass = nil
92
+ @https_proxy = nil
93
+ @https_proxy_user = nil
94
+ @https_proxy_pass = nil
95
+ @no_proxy = nil
96
+ end
97
+
98
+ # Returns the run list for the provisioning
99
+ def run_list
100
+ json[:run_list] ||= []
101
+ end
102
+
103
+ # Sets the run list to the specified value
104
+ def run_list=(value)
105
+ json[:run_list] = value
106
+ end
107
+
108
+ # Adds a recipe to the run list
109
+ def add_recipe(name)
110
+ name = "recipe[#{name}]" unless name =~ /^recipe\[(.+?)\]$/
111
+ run_list << name
112
+ end
113
+
114
+ # Adds a role to the run list
115
+ def add_role(name)
116
+ name = "role[#{name}]" unless name =~ /^role\[(.+?)\]$/
117
+ run_list << name
118
+ end
119
+
120
+ def instance_variables_hash
121
+ # Overridden so that the 'json' key could be removed, since its just
122
+ # merged into the config anyways
123
+ result = super
124
+ result.delete("json")
125
+ result
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,103 @@
1
+ require 'pathname'
2
+
3
+ module Vagrant
4
+ module Provisioners
5
+ # This class implements provisioning via chef-client, allowing provisioning
6
+ # with a chef server.
7
+ class ChefServer < Chef
8
+ register :chef_server
9
+
10
+ class Config < Chef::Config
11
+ attr_accessor :chef_server_url
12
+ attr_accessor :validation_key_path
13
+ attr_accessor :validation_client_name
14
+ attr_accessor :client_key_path
15
+ attr_accessor :file_cache_path
16
+ attr_accessor :file_backup_path
17
+
18
+ def initialize
19
+ super
20
+
21
+ @validation_client_name = "chef-validator"
22
+ @client_key_path = "/etc/chef/client.pem"
23
+ @file_cache_path = "/srv/chef/file_store"
24
+ @file_backup_path = "/srv/chef/cache"
25
+ end
26
+
27
+ def validate(errors)
28
+ super
29
+
30
+ errors.add(I18n.t("vagrant.config.chef.server_url_empty")) if !chef_server_url || chef_server_url.strip == ""
31
+ errors.add(I18n.t("vagrant.config.chef.validation_key_path")) if !validation_key_path
32
+ errors.add(I18n.t("vagrant.config.chef.run_list_empty")) if json[:run_list] && run_list.empty?
33
+ end
34
+ end
35
+
36
+ def prepare
37
+ raise ChefError, :server_validation_key_required if config.validation_key_path.nil?
38
+ raise ChefError, :server_validation_key_doesnt_exist if !File.file?(validation_key_path)
39
+ raise ChefError, :server_url_required if config.chef_server_url.nil?
40
+ end
41
+
42
+ def provision!
43
+ verify_binary("chef-client")
44
+ chown_provisioning_folder
45
+ create_client_key_folder
46
+ upload_validation_key
47
+ setup_json
48
+ setup_server_config
49
+ run_chef_client
50
+ end
51
+
52
+ def create_client_key_folder
53
+ env.ui.info I18n.t("vagrant.provisioners.chef.client_key_folder")
54
+ path = Pathname.new(config.client_key_path)
55
+
56
+ vm.ssh.execute do |ssh|
57
+ ssh.sudo!("mkdir -p #{path.dirname}")
58
+ end
59
+ end
60
+
61
+ def upload_validation_key
62
+ env.ui.info I18n.t("vagrant.provisioners.chef.upload_validation_key")
63
+ vm.ssh.upload!(validation_key_path, guest_validation_key_path)
64
+ end
65
+
66
+ def setup_server_config
67
+ setup_config("chef_server_client", "client.rb", {
68
+ :node_name => config.node_name,
69
+ :chef_server_url => config.chef_server_url,
70
+ :validation_client_name => config.validation_client_name,
71
+ :validation_key => guest_validation_key_path,
72
+ :client_key => config.client_key_path,
73
+ :file_cache_path => config.file_cache_path,
74
+ :file_backup_path => config.file_backup_path
75
+ })
76
+ end
77
+
78
+ def run_chef_client
79
+ commands = ["cd #{config.provisioning_path}",
80
+ "chef-client -c client.rb -j dna.json"]
81
+
82
+ env.ui.info I18n.t("vagrant.provisioners.chef.running_client")
83
+ vm.ssh.execute do |ssh|
84
+ ssh.sudo!(commands) do |channel, type, data|
85
+ if type == :exit_status
86
+ ssh.check_exit_status(data, commands)
87
+ else
88
+ env.ui.info("#{data}: #{type}")
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ def validation_key_path
95
+ File.expand_path(config.validation_key_path, env.root_path)
96
+ end
97
+
98
+ def guest_validation_key_path
99
+ File.join(config.provisioning_path, "validation.pem")
100
+ end
101
+ end
102
+ end
103
+ end