mccloud 0.0.2 → 0.0.3
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/.gitignore +9 -5
- data/Gemfile.lock +1 -1
- data/bin/mccloud +39 -30
- data/lib/mccloud/command/bootstrap.rb +1 -1
- data/lib/mccloud/command/destroy.rb +3 -3
- data/lib/mccloud/command/init.rb +503 -3
- data/lib/mccloud/command/multi.rb +7 -0
- data/lib/mccloud/command/provision.rb +5 -2
- data/lib/mccloud/command/server.rb +10 -5
- data/lib/mccloud/command/ssh.rb +7 -1
- data/lib/mccloud/command/status.rb +14 -5
- data/lib/mccloud/command/up.rb +10 -11
- data/lib/mccloud/configurator/mccloud.rb +21 -1
- data/lib/mccloud/generators.rb +16 -3
- data/lib/mccloud/provisioner/chef_solo.rb +5 -2
- data/lib/mccloud/provisioner/puppet.rb +6 -2
- data/lib/mccloud/session.rb +13 -7
- data/lib/mccloud/templates/bootstrap-centos-rubysource-1.8.7.sh +26 -0
- data/lib/mccloud/templates/bootstrap-centos-rvm-1.8.7.sh +12 -0
- data/lib/mccloud/templates/bootstrap-centos-rvm-1.9.2.sh +12 -0
- data/lib/mccloud/templates/bootstrap-centos-rvm-ree-1.8.7.sh +12 -0
- data/lib/mccloud/templates/bootstrap-custom.sh +1 -0
- data/lib/mccloud/templates/bootstrap-ubuntu-rvm-1.8.7.sh +14 -0
- data/{ruby-bootstrap.sh → lib/mccloud/templates/bootstrap-ubuntu-system.sh} +1 -2
- data/lib/mccloud/util/iterator.rb +3 -4
- data/lib/mccloud/util/sshkey.rb +74 -0
- data/lib/mccloud/version.rb +1 -1
- data/mccloud.gemspec +1 -0
- metadata +13 -7
- data/lib/mccloud/templates/Mccloudfilet +0 -44
- data/ruby-bootstrap2.sh +0 -39
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/bin/mccloud
CHANGED
@@ -18,100 +18,109 @@ class MccloudCLI < Thor
|
|
18
18
|
|
19
19
|
end
|
20
20
|
|
21
|
-
desc "init", "
|
21
|
+
desc "init", "Creates a Mccloud Config File"
|
22
22
|
method_options :force => :boolean
|
23
23
|
def init(amiId=nil)
|
24
24
|
Mccloud::Command.init(amiId,options)
|
25
25
|
end
|
26
26
|
|
27
|
-
desc "up", "
|
27
|
+
desc "up [NAME]", "Fires up a machine, bootstrap and provision"
|
28
28
|
method_options :force => :boolean
|
29
29
|
def up(selection=nil)
|
30
30
|
create_session
|
31
31
|
@session.up(selection,options)
|
32
32
|
end
|
33
33
|
|
34
|
-
desc "status", "
|
34
|
+
desc "status", "Show a status of all machines that are configured"
|
35
35
|
method_options :verbose => false
|
36
36
|
def status(selection=nil)
|
37
37
|
create_session
|
38
38
|
@session.status(selection,options)
|
39
39
|
end
|
40
40
|
|
41
|
-
desc "halt [NAME]", "
|
41
|
+
desc "halt [NAME]", "Shutdown the machine"
|
42
42
|
method_options :force => :boolean
|
43
43
|
def halt(selection=nil)
|
44
44
|
create_session
|
45
45
|
@session.halt(selection,options)
|
46
46
|
end
|
47
47
|
|
48
|
-
desc "ssh [NAME]", "
|
48
|
+
desc "ssh [NAME]", "Spawns an ssh client to the machine"
|
49
49
|
method_options :screen => :boolean
|
50
50
|
def ssh(selection=nil,command=nil)
|
51
51
|
create_session
|
52
52
|
@session.ssh(selection,command,options)
|
53
53
|
end
|
54
54
|
|
55
|
-
desc "suspend", "
|
55
|
+
desc "suspend [NAME]", "Shutdown of the machine"
|
56
56
|
method_options :force => :boolean
|
57
57
|
def suspend(selection=nil)
|
58
58
|
create_session
|
59
59
|
@session.suspend(selection,options)
|
60
60
|
end
|
61
61
|
|
62
|
-
desc "boot", "
|
63
|
-
method_options :force => :boolean
|
64
|
-
def boot(selection=nil)
|
65
|
-
create_session
|
66
|
-
@session.boot(selection,options)
|
67
|
-
end
|
62
|
+
# desc "boot", "same a"
|
63
|
+
# method_options :force => :boolean
|
64
|
+
# def boot(selection=nil)
|
65
|
+
# create_session
|
66
|
+
# @session.boot(selection,options)
|
67
|
+
# end
|
68
68
|
|
69
|
-
desc "destroy [NAME]", "
|
69
|
+
desc "destroy [NAME]", "Destroys the machine"
|
70
70
|
method_options :force => :boolean
|
71
71
|
def destroy(selection=nil)
|
72
72
|
create_session
|
73
73
|
@session.destroy(selection,options)
|
74
74
|
end
|
75
75
|
|
76
|
-
desc "reload [NAME]", "
|
76
|
+
desc "reload [NAME]", "Reboots the machine"
|
77
77
|
method_options :force => :boolean
|
78
78
|
def reload(selection=nil?)
|
79
79
|
create_session
|
80
80
|
@session.reload(selection,options)
|
81
81
|
end
|
82
82
|
|
83
|
-
desc "command [NAME] [COMMAND]", "exec a command on a box"
|
84
|
-
method_options :parallel => :boolean
|
85
|
-
def command(selection=nil,command="who am i")
|
86
|
-
create_session
|
87
|
-
@session.command(selection,command,options)
|
88
|
-
end
|
83
|
+
# desc "command [NAME] [COMMAND]", "exec a command on a box"
|
84
|
+
# method_options :parallel => :boolean
|
85
|
+
# def command(selection=nil,command="who am i")
|
86
|
+
# create_session
|
87
|
+
# @session.command(selection,command,options)
|
88
|
+
# end
|
89
89
|
|
90
|
-
desc "bootstrap [NAME]", "
|
90
|
+
desc "bootstrap [NAME]", "Executes the bootstrap sequence"
|
91
91
|
method_options :sudo => :boolean
|
92
92
|
def bootstrap(selection=nil,script="who am i")
|
93
93
|
create_session
|
94
94
|
@session.bootstrap(selection,script,options)
|
95
95
|
end
|
96
96
|
|
97
|
-
desc "multi","multi"
|
98
|
-
method_options :verbose => :boolean
|
99
|
-
def multi(selection=nil,command="who am i")
|
100
|
-
create_session
|
101
|
-
@session.multi(selection,command,options)
|
102
|
-
end
|
97
|
+
# desc "multi","multi"
|
98
|
+
# method_options :verbose => :boolean
|
99
|
+
# def multi(selection=nil,command="who am i")
|
100
|
+
# create_session
|
101
|
+
# @session.multi(selection,command,options)
|
102
|
+
# end
|
103
103
|
|
104
|
-
desc "provision", "
|
104
|
+
desc "provision [NAME]", "Runs the provisioner the machine"
|
105
105
|
def provision(selection=nil)
|
106
106
|
create_session
|
107
107
|
@session.provision(selection,options)
|
108
108
|
end
|
109
109
|
|
110
|
-
desc "server", "
|
110
|
+
desc "server", "Runs a server+ forwards network ports"
|
111
111
|
def server(selection=nil)
|
112
112
|
create_session
|
113
113
|
@session.server(selection,options)
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
117
|
-
|
117
|
+
puts
|
118
|
+
80.times { |i| printf "*" } ; puts
|
119
|
+
myversion="* Mccloud v#{Mccloud::VERSION} - alpha - use at your own risk"
|
120
|
+
puts "#{myversion}"
|
121
|
+
80.times { |i| printf "*" } ; puts
|
122
|
+
puts
|
123
|
+
|
124
|
+
|
125
|
+
MccloudCLI.start
|
126
|
+
puts
|
@@ -25,7 +25,7 @@ module Mccloud
|
|
25
25
|
#options={ :port => 22, :keys => [ vm.key ], :paranoid => false, :keys_only => true}
|
26
26
|
#Mccloud::Ssh.execute(instance.public_ip_address,vm.user,options,"sudo /tmp/bootstrap.sh")
|
27
27
|
end
|
28
|
-
multi(selection,"sudo /tmp/bootstrap.sh",options)
|
28
|
+
multi(selection,"sudo /tmp/bootstrap.sh",options.merge({ "sudo" => true}))
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -4,14 +4,14 @@ module Mccloud
|
|
4
4
|
module Command
|
5
5
|
def destroy(selection=nil,options=nil)
|
6
6
|
on_selected_machines(selection) do |id,vm|
|
7
|
-
unless vm.instance.state == "shutting-down" || vm.instance.state =="terminated"
|
8
|
-
puts "Destroying #{vm.name}
|
7
|
+
unless vm.instance.nil? || vm.instance.state == "shutting-down" || vm.instance.state =="terminated"
|
8
|
+
puts "Destroying machine #{vm.name} (#{id})"
|
9
9
|
vm.instance.destroy
|
10
10
|
|
11
11
|
vm.instance.wait_for { print "."; STDOUT.flush; state=="terminated"}
|
12
12
|
puts
|
13
13
|
else
|
14
|
-
puts "
|
14
|
+
puts "Machine #{vm.name} is already terminated"
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
data/lib/mccloud/command/init.rb
CHANGED
@@ -1,9 +1,509 @@
|
|
1
1
|
require 'mccloud/generators'
|
2
|
+
require 'highline/import'
|
3
|
+
require 'mccloud/util/sshkey'
|
4
|
+
|
5
|
+
require 'erb'
|
2
6
|
|
3
7
|
module Mccloud
|
4
8
|
module Command
|
5
|
-
|
6
|
-
|
9
|
+
include Mccloud::Util
|
10
|
+
def self.init(amiId=nil,options=nil)
|
11
|
+
|
12
|
+
trap("INT") { puts
|
13
|
+
puts ""; exit }
|
14
|
+
|
15
|
+
init_options=ARGV
|
16
|
+
|
17
|
+
puts "Welcome to the Mccloud configurator: "
|
18
|
+
init_options<< "--mcPrefix"
|
19
|
+
init_options<< "mccloud"
|
20
|
+
|
21
|
+
init_options<< "--providerId"
|
22
|
+
init_options<< "AWS"
|
23
|
+
|
24
|
+
create_fog('AWS')
|
25
|
+
|
26
|
+
template=ERB.new File.new("lib/mccloud/templates/Mccloudfile.erb").read,nil,"%"
|
27
|
+
mcPrefix="mccloud"
|
28
|
+
providerId="AWS"
|
29
|
+
mcEnvironment=select_environment
|
30
|
+
mcIdentity=select_identity
|
31
|
+
|
32
|
+
serverName=select_servername
|
33
|
+
|
34
|
+
#strip all
|
35
|
+
serverName.gsub!(/[^[:alnum:]]/, '_')
|
36
|
+
|
37
|
+
image_selection=select_image
|
38
|
+
imageId=image_selection['imageId']
|
39
|
+
userName=image_selection['userName']
|
40
|
+
imageDescription=image_selection['imageDescription']
|
41
|
+
arch=image_selection['arch']
|
42
|
+
|
43
|
+
full_bootstrapScript=image_selection['bootstrap']
|
44
|
+
copy_bootstrap(full_bootstrapScript)
|
45
|
+
bootstrapScript=File.basename("#{full_bootstrapScript}")
|
46
|
+
|
47
|
+
availabilityZone=select_zone
|
48
|
+
flavorId=select_flavor(arch)
|
49
|
+
|
50
|
+
fullIdentity=Array.new
|
51
|
+
if !mcPrefix.nil?
|
52
|
+
fullIdentity << mcPrefix
|
53
|
+
end
|
54
|
+
if mcEnvironment!=""
|
55
|
+
fullIdentity << mcEnvironment
|
56
|
+
end
|
57
|
+
if mcIdentity!=""
|
58
|
+
fullIdentity << mcIdentity
|
59
|
+
end
|
60
|
+
full_identity=fullIdentity.join("-")
|
61
|
+
|
62
|
+
securityGroup=select_security_group(full_identity)
|
63
|
+
|
64
|
+
keypair_selection=select_keypair
|
65
|
+
keyName=keypair_selection['keyName']
|
66
|
+
privateKeyPath=keypair_selection['privateKeyPath']
|
67
|
+
publicKeyPath=keypair_selection['publicKeyPath']
|
68
|
+
|
69
|
+
confirmed=false
|
70
|
+
content=template.result(binding)
|
71
|
+
if File.exists?("Mccloudfile")
|
72
|
+
confirmed=agree("\nDo you want to overwrite your existing config?: ") { |q| q.default="no"}
|
73
|
+
else
|
74
|
+
confirmed=true
|
75
|
+
end
|
76
|
+
if confirmed
|
77
|
+
puts
|
78
|
+
puts "Writing your config file Mccloudfile"
|
79
|
+
mccloudfile=File.new("Mccloudfile","w")
|
80
|
+
mccloudfile.puts(content)
|
81
|
+
mccloudfile.close
|
82
|
+
else
|
83
|
+
puts "Ok did not overwrite the config, moving along"
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
#Mccloud::Generators.run_cli Dir.pwd, File.basename(__FILE__), Mccloud::VERSION, init_options
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def self.copy_bootstrap(filename=nil)
|
93
|
+
|
94
|
+
unless filename.nil?
|
95
|
+
|
96
|
+
FileUtils.cp(filename,File.basename(filename))
|
97
|
+
puts "Copied bootstrap - #{File.basename(filename)} to your current directory"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.generate_key(comment=nil)
|
102
|
+
keyset=SSHKey.generate(:comment => comment)
|
103
|
+
return keyset
|
104
|
+
end
|
105
|
+
def self.select_image()
|
106
|
+
|
107
|
+
# Canonical
|
108
|
+
# http://uec-images.ubuntu.com/releases/10.04/release/
|
109
|
+
# http://jonathanhui.com/create-and-launch-amazon-ec2-instance-ubuntu-and-centos
|
110
|
+
|
111
|
+
suggestions=[
|
112
|
+
{ "Name" => "Ubuntu 10.10 - Maverick 64-bit (Canonical/EBS)", "ImageId" => "ami-cef405a7",
|
113
|
+
"UserName" => "ubuntu" ,"Arch" => "64", "Bootstraps" =>
|
114
|
+
[ {"Description" => "Ruby via standard .deb packages + rubygems from source + (chef,puppet) as gems", "Filename" => "bootstrap-ubuntu-system.sh"},
|
115
|
+
{"Description" => "Ruby 1.8.7 via rvm + (chef,puppet) as gems", "Filename" => "bootstrap-ubuntu-rvm-1.8.7.sh"},
|
116
|
+
{"Description" => "Empty bootstrap you can customize", "Filename" => "bootstrap-custom.sh"},
|
117
|
+
]
|
118
|
+
},
|
119
|
+
{ "Name" => "Ubuntu 10.10 - Maverick 32-bit (Canonical/EBS)", "ImageId" => "ami-ccf405a5",
|
120
|
+
"UserName" => "ubuntu" ,"Arch" => "32", "Bootstraps" =>
|
121
|
+
[ {"Description" => "Ruby via standard .deb packages + rubygems from source + (chef,puppet) as gems", "Filename" => "bootstrap-ubuntu-system.sh"},
|
122
|
+
{"Description" => "Ruby 1.8.7 via rvm + (chef,puppet) as gems", "Filename" => "bootstrap-ubuntu-rvm-1.8.7.sh"},
|
123
|
+
{"Description" => "Empty bootstrap you can customize", "Filename" => "bootstrap-custom.sh"},
|
124
|
+
|
125
|
+
]},
|
126
|
+
{ "Name" => "Ubuntu 10.04 - Lucid 64-bit (Canonical/EBS)", "ImageId" => "ami-3202f25b",
|
127
|
+
"UserName" => "ubuntu" ,"Arch" => "64", "Bootstraps" =>
|
128
|
+
[ {"Description" => "Ruby via standard .deb packages + rubygems from source + (chef,puppet) as gems", "Filename" => "bootstrap-ubuntu-system.sh"},
|
129
|
+
{"Description" => "Ruby 1.8.7 via rvm + (chef,puppet) as gems", "Filename" => "bootstrap-ubuntu-rvm-1.8.7.sh"},
|
130
|
+
{"Description" => "Empty bootstrap you can customize", "Filename" => "bootstrap-custom.sh"},
|
131
|
+
|
132
|
+
]},
|
133
|
+
{ "Name" => "Ubuntu 10.04 - Lucid 32-bit (Canonical/EBS)", "ImageId" => "ami-3e02f257",
|
134
|
+
"UserName" => "ubuntu" ,"Arch" => "32", "Bootstraps" =>
|
135
|
+
[ {"Description" => "Ruby via standard .deb packages + rubygems from source + (chef,puppet) as gems", "Filename" => "bootstrap-ubuntu-system.sh"},
|
136
|
+
{"Description" => "Ruby 1.8.7 via rvm + (chef,puppet) as gems", "Filename" => "bootstrap-ubuntu-rvm-1.8.7.sh"},
|
137
|
+
{"Description" => "Empty bootstrap you can customize", "Filename" => "bootstrap-custom.sh"},
|
138
|
+
|
139
|
+
]},
|
140
|
+
{ "Name" => "Centos 5.4 - 64-bit (Rightscale/EBS)", "ImageId" => "ami-4d42a924",
|
141
|
+
"UserName" => "root" ,"Arch" => "64", "Bootstraps" =>
|
142
|
+
[ {"Description" => "Ruby 1.8.7 from source + (chef,puppet) as gems", "Filename" => "bootstrap-centos-rubysource-1.8.7.sh"},
|
143
|
+
{"Description" => "Ruby 1.8.7 via rvm + (chef,puppet) as gems", "Filename" => "bootstrap-centos-rvm-1.8.7.sh"},
|
144
|
+
{"Description" => "Ruby REE 1.8.7 via rvm + (chef,puppet) as gems", "Filename" => "bootstrap-centos-rvm-ree-1.8.7.sh"},
|
145
|
+
|
146
|
+
{"Description" => "Ruby 1.9.2 via rvm + (chef,puppet) as gems", "Filename" => "bootstrap-centos-rvm-1.9.2.sh"},
|
147
|
+
{"Description" => "Empty bootstrap you can customize", "Filename" => "bootstrap-custom.sh"},
|
148
|
+
|
149
|
+
]},
|
150
|
+
{ "Name" => "Centos 5.4 - 32-bit (Rightscale/EBS)", "ImageId" => "ami-2342a94a",
|
151
|
+
"UserName" => "root" ,"Arch" => "32", "Bootstraps" =>
|
152
|
+
[ {"Description" => "Ruby 1.8.7 from source + (chef,puppet) as gems", "Filename" => "bootstrap-centos-rubysource-1.8.7.sh"},
|
153
|
+
{"Description" => "Ruby 1.8.7 via rvm + (chef,puppet) as gems", "Filename" => "bootstrap-centos-rvm-1.8.7.sh"},
|
154
|
+
{"Description" => "Ruby REE 1.8.7 via rvm + (chef,puppet) as gems", "Filename" => "bootstrap-centos-rvm-ree-1.8.7.sh"},
|
155
|
+
|
156
|
+
{"Description" => "Ruby 1.9.2 via rvm + (chef,puppet) as gems", "Filename" => "bootstrap-centos-rvm-1.9.2.sh"},
|
157
|
+
{"Description" => "Empty bootstrap you can customize", "Filename" => "bootstrap-custom.sh"},
|
158
|
+
|
159
|
+
]},
|
160
|
+
|
161
|
+
]
|
162
|
+
|
163
|
+
imageId=""
|
164
|
+
userName="root"
|
165
|
+
imageDescription=""
|
166
|
+
arch="0"
|
167
|
+
bootstrap=""
|
168
|
+
|
169
|
+
choose do |menu|
|
170
|
+
menu.index_suffix =") "
|
171
|
+
menu.header="\nSuggested image Ids"
|
172
|
+
menu.default="1"
|
173
|
+
menu.prompt="\nSelect the Image Id (aka AMI-ID on EC2): |1| "
|
174
|
+
suggestions.each do |suggestion|
|
175
|
+
menu.choice "#{suggestion['Name']} - #{suggestion['ImageId']}" do
|
176
|
+
imageId=suggestion['ImageId']
|
177
|
+
userName=suggestion['UserName']
|
178
|
+
imageDescription=suggestion['Name']
|
179
|
+
arch=suggestion['Arch']
|
180
|
+
|
181
|
+
choose do |bootstrap_menu|
|
182
|
+
bootstrap_menu.index_suffix =") "
|
183
|
+
bootstrap_menu.header="\nSuggested bootstraps"
|
184
|
+
bootstrap_menu.default="1"
|
185
|
+
bootstrap_menu.prompt="\nSelect the Image Id (aka AMI-ID on EC2): |1| "
|
186
|
+
suggestion["Bootstraps"].each do |bootstrap_file|
|
187
|
+
bootstrap_menu.choice "#{bootstrap_file['Description']}" do
|
188
|
+
bootstrap=File.expand_path(File.join(File.dirname(__FILE__),'..','templates',"#{bootstrap_file["Filename"]}"))
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
end
|
195
|
+
menu.choice "Specify your own:" do
|
196
|
+
imageId=ask("Image Id: ")
|
197
|
+
userName=ask("Username to login: ")
|
198
|
+
imageDescription=ask("Description: ")
|
199
|
+
arch=ask("Architecture (32,64): "){|q| q.default="64"}
|
200
|
+
bootstrap=ask("Path to Bootstrap script: ")
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
return { "imageId"=>imageId,"userName" =>userName,"imageDescription" => imageDescription,"arch" => arch,"bootstrap" => bootstrap}
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
def self.select_identity()
|
210
|
+
|
211
|
+
puts "If you share the same cloud provider account, you can specify an identity"
|
212
|
+
puts "to uniquely identify *your* servers (ex. firstname.lastname)"
|
213
|
+
puts "Leave blank if you want to work in a team "
|
214
|
+
puts ""
|
215
|
+
mcIdentity=ask("Identity: ") {|q| q.default="#{ENV['USER']}"}
|
216
|
+
puts
|
217
|
+
return mcIdentity
|
218
|
+
|
219
|
+
end
|
220
|
+
|
221
|
+
def self.select_servername()
|
222
|
+
|
223
|
+
puts "Provide an short name to identify your server (ex. web,db) "
|
224
|
+
mcIdentity=ask("Servername: ") { |q| q.default="web"}
|
225
|
+
puts
|
226
|
+
return mcIdentity
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
def self.select_environment()
|
231
|
+
|
232
|
+
puts "Provide a name for the environment your are using (ex. development, test, demo)"
|
233
|
+
mcEnvironment=ask("Environment: "){|q| q.default="development"}
|
234
|
+
puts
|
235
|
+
return mcEnvironment
|
236
|
+
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
def self.select_flavor(filter=nil)
|
241
|
+
flavorId="t1.micro"
|
242
|
+
choose do |menu|
|
243
|
+
menu.index_suffix =") "
|
244
|
+
menu.header="\nAvailable machine flavors"
|
245
|
+
menu.default="1"
|
246
|
+
menu.prompt="\nSelect the flavor for your machine: |1| "
|
247
|
+
@provider.flavors.each do |flavor|
|
248
|
+
if "#{flavor.bits}"==filter || "#{flavor.bits}"=="0"
|
249
|
+
menu.choice "#{flavor.name} - #{flavor.id} - #{flavor.cores} cores" do
|
250
|
+
flavorId=flavor.id
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
return flavorId
|
256
|
+
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.select_security_group(identity=nil)
|
260
|
+
|
261
|
+
securityGroup="default"
|
262
|
+
choose do |menu|
|
263
|
+
menu.index_suffix =") "
|
264
|
+
menu.header="\nAvailable security groups"
|
265
|
+
menu.default="1"
|
266
|
+
menu.prompt="\nSelect the security group for your machine: |1| "
|
267
|
+
|
268
|
+
mcgroup=@provider.security_groups.get("#{identity}-securitygroup")
|
269
|
+
if mcgroup.nil?
|
270
|
+
menu.choice "[Create new] #{identity}-securitygroup" do
|
271
|
+
sg=@provider.security_groups.new
|
272
|
+
sg.name="#{identity}-securitygroup"
|
273
|
+
sg.description="#{identity}-securitygroup"
|
274
|
+
sg.save
|
275
|
+
|
276
|
+
puts "Authorizing access to port 22"
|
277
|
+
sg.authorize_port_range(22..22)
|
278
|
+
|
279
|
+
securityGroup="#{identity}-securitygroup"
|
280
|
+
end
|
281
|
+
else
|
282
|
+
menu.choice "#{identity}-securitygroup" do
|
283
|
+
securityGroup="#{identity}-securitygroup"
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
@provider.security_groups.each do |group|
|
288
|
+
unless "#{group.name}"=="#{identity}-securitygroup"
|
289
|
+
menu.choice "#{group.name} - #{group.description}" do
|
290
|
+
puts "Make sure this security group has ssh/port 22 enabled\n"
|
291
|
+
securityGroup=group.name
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
# We should check to see if 22 is enabled for that zone
|
298
|
+
#(AWS.security_groups.get("JMETER").ip_permissions[0]["fromPort"]..AWS.security_groups.get("JMETER").ip_permissions[0]["toPort"]) === 22
|
299
|
+
# make sure port 22 is open in the first security group
|
300
|
+
# security_group = connection.security_groups.get(server.groups.first)
|
301
|
+
# authorized = security_group.ip_permissions.detect do |ip_permission|
|
302
|
+
# ip_permission['ipRanges'].first && ip_permission['ipRanges'].first['cidrIp'] == '0.0.0.0/0' &&
|
303
|
+
# ip_permission['fromPort'] == 22 &&
|
304
|
+
# ip_permission['ipProtocol'] == 'tcp' &&
|
305
|
+
# ip_permission['toPort'] == 22
|
306
|
+
# end
|
307
|
+
# unless authorized
|
308
|
+
# security_group.authorize_port_range(22..22)
|
309
|
+
# end
|
310
|
+
return securityGroup
|
311
|
+
|
312
|
+
end
|
313
|
+
|
314
|
+
def self.select_zone()
|
315
|
+
|
316
|
+
|
317
|
+
zone="default"
|
318
|
+
|
319
|
+
choose do |menu|
|
320
|
+
menu.index_suffix =") "
|
321
|
+
menu.header="\nAvailable zones"
|
322
|
+
menu.default="us-east-1b"
|
323
|
+
menu.prompt="\nSelect the zone for your machine: |#{menu.default}| "
|
324
|
+
|
325
|
+
@provider.describe_availability_zones.body["availabilityZoneInfo"].each do |region|
|
326
|
+
menu.choice "#{region['zoneName']} - #{region['regionName']}" do
|
327
|
+
zone=region['zoneName']
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
[ {"zoneName" => "eu-west-1a", "regionName" => "eu-west-1"}, {"zoneName" => "eu-west-1b", "regionName" => "eu-west-1"}].each do |region|
|
332
|
+
menu.choice "#{region['zoneName']} - #{region['regionName']}" do
|
333
|
+
zone=region['zoneName']
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
return zone
|
339
|
+
|
340
|
+
end
|
341
|
+
|
342
|
+
def self.create_fog(provider='AWS')
|
343
|
+
begin
|
344
|
+
@provider=Fog::Compute.new(:provider => provider)
|
345
|
+
rescue ArgumentError => e
|
346
|
+
# Missing required arguments:
|
347
|
+
required_string=e.message
|
348
|
+
required_string["Missing required arguments: "]=""
|
349
|
+
required_options=required_string.split(", ")
|
350
|
+
puts "Please provide credentials for provider [#{provider}]:"
|
351
|
+
answer=Hash.new
|
352
|
+
for fog_option in required_options do
|
353
|
+
answer["#{fog_option}".to_sym]=ask("- #{fog_option}: ")
|
354
|
+
#{ |q| q.validate = /\A\d{5}(?:-?\d{4})?\Z/ }
|
355
|
+
end
|
356
|
+
puts "\nThe following snippet will be written to #{File.join(ENV['HOME'],".fog")}"
|
357
|
+
|
358
|
+
snippet=":default:\n"
|
359
|
+
for fog_option in required_options do
|
360
|
+
snippet=snippet+" :#{fog_option}: #{answer[fog_option.to_sym]}\n"
|
361
|
+
end
|
362
|
+
|
363
|
+
puts "======== snippit start ====="
|
364
|
+
puts "#{snippet}"
|
365
|
+
puts "======== snippit end ======="
|
366
|
+
confirmed=agree("Do you want to save this?: ") {|q| q.default="yes"}
|
367
|
+
puts
|
368
|
+
|
369
|
+
if (confirmed)
|
370
|
+
fogfile=File.new("#{File.join(ENV['HOME'],".fog")}","w")
|
371
|
+
FileUtils.chmod(0600,fogfile)
|
372
|
+
fogfile.puts "#{snippet}"
|
373
|
+
fogfile.close
|
374
|
+
else
|
375
|
+
#puts "Ok, we won't write it, but we continue with your credentials in memory"
|
376
|
+
exit -1
|
377
|
+
end
|
378
|
+
begin
|
379
|
+
answer[:provider]= provider
|
380
|
+
@provider=Fog::Compute.new(answer)
|
381
|
+
rescue
|
382
|
+
puts "We tried to create the provider but failed again, sorry we give up"
|
383
|
+
exit -1
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
def self.select_keypair()
|
389
|
+
|
390
|
+
|
391
|
+
valid_private_key=false
|
392
|
+
valid_public_key=false
|
393
|
+
private_key_path=""
|
394
|
+
public_key_path=""
|
395
|
+
|
396
|
+
keyName=nil
|
397
|
+
choose do |menu|
|
398
|
+
menu.index_suffix =") "
|
399
|
+
menu.header="\nAvailable keypairs"
|
400
|
+
menu.default="1"
|
401
|
+
menu.prompt="\nSelect a keypair: |1| "
|
402
|
+
|
403
|
+
menu.choice "Use/Generate a new (mccloud) keypair (RSA)" do
|
404
|
+
|
405
|
+
private_key_path=File.join("#{ENV['HOME']}",".ssh","mccloud_rsa")
|
406
|
+
public_key_path=File.join("#{ENV['HOME']}",".ssh","mccloud_rsa.pub")
|
407
|
+
|
408
|
+
if File.exists?(private_key_path)
|
409
|
+
reuse=agree("\nReuse existing (mccloud) keypair?: ") { |q| q.default="yes"}
|
410
|
+
else
|
411
|
+
reuse=false
|
412
|
+
end
|
413
|
+
|
414
|
+
rsa_key=nil
|
415
|
+
unless reuse
|
416
|
+
keyName=ask("\nPlease enter a name for your new key: "){|q| q.default="mccloud-key-#{ENV['USER']}"}
|
417
|
+
rsa_key=generate_key(keyName)
|
418
|
+
|
419
|
+
unless File.exists?(File.dirname(public_key_path))
|
420
|
+
puts "Creating directory #{File.dirname(public_key_path)}"
|
421
|
+
FileUtils.mkdir_p(File.dirname(public_key_path))
|
422
|
+
FileUtils.chmod(0700,File.dirname(public_key_path))
|
423
|
+
end
|
424
|
+
|
425
|
+
unless File.exists?(File.dirname(private_key_path))
|
426
|
+
puts "Creating directory #{File.dirname(private_key_path)}"
|
427
|
+
|
428
|
+
FileUtils.mkdir_p(File.dirname(private_key_path))
|
429
|
+
FileUtils.chmod(0700,File.dirname(private_key_path))
|
430
|
+
end
|
431
|
+
|
432
|
+
|
433
|
+
File.open(public_key_path, 'w') {|f| f.write(rsa_key.ssh_public_key) }
|
434
|
+
File.open(private_key_path, 'w') {|f| f.write(rsa_key.rsa_private_key) }
|
435
|
+
FileUtils.chmod(0600,private_key_path)
|
436
|
+
FileUtils.chmod(0600,public_key_path)
|
437
|
+
|
438
|
+
puts
|
439
|
+
puts "Created a new public key in #{public_key_path}"
|
440
|
+
puts "Created a new private key in #{private_key_path}"
|
441
|
+
puts "I suggest you backup these later."
|
442
|
+
puts
|
443
|
+
|
444
|
+
provider_keypair=@provider.key_pairs.get(keyName)
|
445
|
+
unless (provider_keypair.nil?)
|
446
|
+
puts "Updating your existing key #{keyName} with cloud provider"
|
447
|
+
provider_keypair.destroy()
|
448
|
+
end
|
449
|
+
provider_keypair=@provider.key_pairs.create(
|
450
|
+
:name => keyName,
|
451
|
+
:public_key => rsa_key.ssh_public_key )
|
452
|
+
puts "Registered #{keyName} with your cloud provider"
|
453
|
+
|
454
|
+
else
|
455
|
+
keyName=ask("\nPlease enter a name for your key: "){|q| q.default="mccloud-key-#{ENV['USER']}"}
|
456
|
+
end
|
457
|
+
|
458
|
+
valid_public_key=true
|
459
|
+
valid_private_key=true
|
460
|
+
end
|
461
|
+
|
462
|
+
menu.choice "Provide your own keypair (RSA)" do
|
463
|
+
keyName=nil
|
464
|
+
end
|
465
|
+
@provider.key_pairs.each do |keypair|
|
466
|
+
menu.choice "#{keypair.name} - #{keypair.fingerprint}" do
|
467
|
+
keyName=keypair.name
|
468
|
+
end
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
|
473
|
+
if keyName.nil?
|
474
|
+
puts "You selected to provide a custom keypair. Note that only RSA keys are supported"
|
475
|
+
puts
|
476
|
+
keyName=ask("Please enter a name for your custom key: (ex. ec2key-firstname.lastname) "){|q| q.default="mccloud-key-#{ENV['USER']}"}
|
477
|
+
else
|
478
|
+
valid_public_key=true
|
479
|
+
end
|
480
|
+
|
481
|
+
while (valid_private_key==false) do
|
482
|
+
private_key_path=ask("Enter full path to private key: "){|q| q.default="#{File.join(ENV['HOME'],'.ssh','mccloud-id_rsa')}"}
|
483
|
+
if File.exists?(private_key_path)
|
484
|
+
valid_private_key=true
|
485
|
+
else
|
486
|
+
puts "#{private_key_path} does not exist"
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
while (valid_public_key==false) do
|
491
|
+
public_key_path=ask("Enter full path to public key: "){|q| q.default="#{File.join(ENV['HOME'],'.ssh','mccloud-id_rsa.pub')}"}
|
492
|
+
if File.exists?(public_key_path)
|
493
|
+
valid_public_key=true
|
494
|
+
else
|
495
|
+
puts "#{public_key_path} does not exist"
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
|
500
|
+
if private_key_path==""
|
501
|
+
return {"keyName" => keyName,"privateKeyPath" => private_key_path}
|
502
|
+
|
503
|
+
else
|
504
|
+
return {"keyName" => keyName,"publicKeyPath" => public_key_path,"privateKeyPath" => private_key_path}
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
7
508
|
end
|
8
509
|
end
|
9
|
-
end
|