rudy 0.4.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +54 -30
- data/README.rdoc +100 -12
- data/Rakefile +103 -8
- data/Rudyfile +119 -0
- data/bin/ird +175 -0
- data/bin/rudy +259 -156
- data/bin/rudy-ec2 +228 -95
- data/bin/rudy-s3 +76 -0
- data/bin/rudy-sdb +67 -0
- data/lib/annoy.rb +270 -0
- data/lib/console.rb +30 -9
- data/lib/escape.rb +305 -0
- data/lib/rudy.rb +151 -182
- data/lib/rudy/aws.rb +56 -49
- data/lib/rudy/aws/ec2.rb +47 -292
- data/lib/rudy/aws/ec2/address.rb +157 -0
- data/lib/rudy/aws/ec2/group.rb +301 -0
- data/lib/rudy/aws/ec2/image.rb +168 -0
- data/lib/rudy/aws/ec2/instance.rb +434 -0
- data/lib/rudy/aws/ec2/keypair.rb +104 -0
- data/lib/rudy/aws/ec2/snapshot.rb +98 -0
- data/lib/rudy/aws/ec2/volume.rb +230 -0
- data/lib/rudy/aws/ec2/zone.rb +77 -0
- data/lib/rudy/aws/s3.rb +54 -0
- data/lib/rudy/aws/sdb.rb +298 -0
- data/lib/rudy/aws/sdb/error.rb +46 -0
- data/lib/rudy/{metadata/backup.rb → backup.rb} +26 -51
- data/lib/rudy/cli.rb +157 -0
- data/lib/rudy/cli/aws/ec2/addresses.rb +105 -0
- data/lib/rudy/cli/aws/ec2/candy.rb +208 -0
- data/lib/rudy/cli/aws/ec2/groups.rb +121 -0
- data/lib/rudy/cli/aws/ec2/images.rb +196 -0
- data/lib/rudy/cli/aws/ec2/instances.rb +194 -0
- data/lib/rudy/cli/aws/ec2/keypairs.rb +53 -0
- data/lib/rudy/cli/aws/ec2/snapshots.rb +49 -0
- data/lib/rudy/cli/aws/ec2/volumes.rb +104 -0
- data/lib/rudy/cli/aws/ec2/zones.rb +22 -0
- data/lib/rudy/cli/aws/s3/buckets.rb +50 -0
- data/lib/rudy/cli/aws/s3/store.rb +22 -0
- data/lib/rudy/cli/aws/sdb/domains.rb +41 -0
- data/lib/rudy/cli/candy.rb +8 -0
- data/lib/rudy/{command → cli}/config.rb +34 -24
- data/lib/rudy/cli/disks.rb +35 -0
- data/lib/rudy/cli/machines.rb +94 -0
- data/lib/rudy/cli/routines.rb +57 -0
- data/lib/rudy/config.rb +77 -72
- data/lib/rudy/config/objects.rb +29 -0
- data/lib/rudy/disks.rb +248 -0
- data/lib/rudy/global.rb +121 -0
- data/lib/rudy/huxtable.rb +340 -0
- data/lib/rudy/machines.rb +245 -0
- data/lib/rudy/metadata.rb +123 -13
- data/lib/rudy/routines.rb +47 -0
- data/lib/rudy/routines/helpers/diskhelper.rb +101 -0
- data/lib/rudy/routines/helpers/scripthelper.rb +91 -0
- data/lib/rudy/routines/release.rb +34 -0
- data/lib/rudy/routines/shutdown.rb +57 -0
- data/lib/rudy/routines/startup.rb +58 -0
- data/lib/rudy/scm/svn.rb +1 -1
- data/lib/rudy/utils.rb +322 -4
- data/lib/storable.rb +26 -17
- data/lib/sysinfo.rb +274 -0
- data/lib/tryouts.rb +6 -13
- data/rudy.gemspec +128 -42
- data/support/randomize-root-password +45 -0
- data/support/rudy-ec2-startup +9 -9
- data/support/update-ec2-ami-tools +20 -0
- data/test/05_config/00_setup_test.rb +20 -0
- data/test/05_config/30_machines_test.rb +69 -0
- data/test/20_sdb/00_setup_test.rb +16 -0
- data/test/20_sdb/10_domains_test.rb +115 -0
- data/test/25_ec2/00_setup_test.rb +29 -0
- data/test/25_ec2/10_keypairs_test.rb +41 -0
- data/test/25_ec2/20_groups_test.rb +131 -0
- data/test/25_ec2/30_addresses_test.rb +38 -0
- data/test/25_ec2/40_volumes_test.rb +49 -0
- data/test/25_ec2/50_snapshots_test.rb +74 -0
- data/test/26_ec2_instances/00_setup_test.rb +28 -0
- data/test/26_ec2_instances/10_instances_test.rb +83 -0
- data/test/26_ec2_instances/50_images_test.rb +13 -0
- data/test/30_sdb_metadata/00_setup_test.rb +21 -0
- data/test/30_sdb_metadata/10_disks_test.rb +109 -0
- data/test/30_sdb_metadata/20_backups_test.rb +102 -0
- data/test/coverage.txt +51 -0
- data/test/helper.rb +36 -0
- data/vendor/highline-1.5.1/CHANGELOG +222 -0
- data/vendor/highline-1.5.1/INSTALL +35 -0
- data/vendor/highline-1.5.1/LICENSE +7 -0
- data/vendor/highline-1.5.1/README +63 -0
- data/vendor/highline-1.5.1/Rakefile +82 -0
- data/vendor/highline-1.5.1/TODO +6 -0
- data/vendor/highline-1.5.1/examples/ansi_colors.rb +38 -0
- data/vendor/highline-1.5.1/examples/asking_for_arrays.rb +18 -0
- data/vendor/highline-1.5.1/examples/basic_usage.rb +75 -0
- data/vendor/highline-1.5.1/examples/color_scheme.rb +32 -0
- data/vendor/highline-1.5.1/examples/limit.rb +12 -0
- data/vendor/highline-1.5.1/examples/menus.rb +65 -0
- data/vendor/highline-1.5.1/examples/overwrite.rb +19 -0
- data/vendor/highline-1.5.1/examples/page_and_wrap.rb +322 -0
- data/vendor/highline-1.5.1/examples/password.rb +7 -0
- data/vendor/highline-1.5.1/examples/trapping_eof.rb +22 -0
- data/vendor/highline-1.5.1/examples/using_readline.rb +17 -0
- data/vendor/highline-1.5.1/lib/highline.rb +758 -0
- data/vendor/highline-1.5.1/lib/highline/color_scheme.rb +120 -0
- data/vendor/highline-1.5.1/lib/highline/compatibility.rb +17 -0
- data/vendor/highline-1.5.1/lib/highline/import.rb +43 -0
- data/vendor/highline-1.5.1/lib/highline/menu.rb +395 -0
- data/vendor/highline-1.5.1/lib/highline/question.rb +463 -0
- data/vendor/highline-1.5.1/lib/highline/system_extensions.rb +193 -0
- data/vendor/highline-1.5.1/setup.rb +1360 -0
- data/vendor/highline-1.5.1/test/tc_color_scheme.rb +56 -0
- data/vendor/highline-1.5.1/test/tc_highline.rb +823 -0
- data/vendor/highline-1.5.1/test/tc_import.rb +54 -0
- data/vendor/highline-1.5.1/test/tc_menu.rb +429 -0
- data/vendor/highline-1.5.1/test/ts_all.rb +15 -0
- metadata +141 -38
- data/lib/aws_sdb.rb +0 -3
- data/lib/aws_sdb/error.rb +0 -42
- data/lib/aws_sdb/service.rb +0 -215
- data/lib/rudy/aws/simpledb.rb +0 -53
- data/lib/rudy/command/addresses.rb +0 -46
- data/lib/rudy/command/backups.rb +0 -175
- data/lib/rudy/command/base.rb +0 -841
- data/lib/rudy/command/deploy.rb +0 -12
- data/lib/rudy/command/disks.rb +0 -213
- data/lib/rudy/command/environment.rb +0 -73
- data/lib/rudy/command/groups.rb +0 -61
- data/lib/rudy/command/images.rb +0 -91
- data/lib/rudy/command/instances.rb +0 -85
- data/lib/rudy/command/machines.rb +0 -161
- data/lib/rudy/command/metadata.rb +0 -41
- data/lib/rudy/command/release.rb +0 -174
- data/lib/rudy/command/volumes.rb +0 -66
- data/lib/rudy/metadata/disk.rb +0 -138
- data/tryouts/console_tryout.rb +0 -91
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Rudy
|
4
|
+
module CLI
|
5
|
+
class Disks < Rudy::CLI::CommandBase
|
6
|
+
|
7
|
+
|
8
|
+
def disks
|
9
|
+
rdisk = Rudy::Disks.new
|
10
|
+
rdisk.list do |d|
|
11
|
+
puts @@global.verbose > 0 ? d.inspect : d.dump(@@global.format)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def disks_wash
|
16
|
+
rdisk = Rudy::Disks.new
|
17
|
+
dirt = (rdisk.list || [])#.select { |d| d.available? }
|
18
|
+
if dirt.empty?
|
19
|
+
puts "Nothing to wash in #{rdisk.current_machine_group}"
|
20
|
+
return
|
21
|
+
end
|
22
|
+
|
23
|
+
puts "The following disk metadata will be deleted:"
|
24
|
+
puts dirt.collect {|d| d.name }
|
25
|
+
execute_check(:medium)
|
26
|
+
|
27
|
+
dirt.each do |d|
|
28
|
+
d.destroy(:force)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Rudy
|
4
|
+
module CLI
|
5
|
+
class Machines < Rudy::CLI::CommandBase
|
6
|
+
|
7
|
+
|
8
|
+
def machines
|
9
|
+
rmach = Rudy::Machines.new
|
10
|
+
mlist = rmach.list || []
|
11
|
+
if mlist.empty?
|
12
|
+
puts "No machines running in #{current_machine_group}"
|
13
|
+
puts "Try: #{$0} startup"
|
14
|
+
end
|
15
|
+
mlist.each do |m|
|
16
|
+
puts @@global.verbose > 0 ? m.inspect : m.dump(@@global.format)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def machines_wash
|
21
|
+
rmach = Rudy::Machines.new
|
22
|
+
dirt = (rmach.list || []).select { |m| !m.running? }
|
23
|
+
if dirt.empty?
|
24
|
+
puts "Nothing to wash in #{rmach.current_machine_group}"
|
25
|
+
return
|
26
|
+
end
|
27
|
+
|
28
|
+
puts "The following machine metadata will be deleted:"
|
29
|
+
puts dirt.collect {|m| m.name }
|
30
|
+
execute_check(:medium)
|
31
|
+
|
32
|
+
dirt.each do |m|
|
33
|
+
m.destroy
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def ssh
|
40
|
+
# TODO: Give this methos a good look over
|
41
|
+
pkey = user_keypairpath(@@global.user)
|
42
|
+
unless pkey
|
43
|
+
puts "No private key configured for #{@@global.user} in #{current_machine_group}"
|
44
|
+
end
|
45
|
+
|
46
|
+
# Options to be sent to Net::SSH
|
47
|
+
ssh_opts = { :user => @@global.user || Rudy.sysinfo.user, :debug => nil }
|
48
|
+
if pkey
|
49
|
+
raise "Cannot find file #{pkey}" unless File.exists?(pkey)
|
50
|
+
raise InsecureKeyPermissions, @pkey unless File.stat(pkey).mode == 33152
|
51
|
+
ssh_opts[:keys] = pkey
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# The user specified a command to run. We won't create an interactive
|
56
|
+
# session so we need to prepare the command and its arguments
|
57
|
+
if @argv.first
|
58
|
+
command, command_args = @argv.shift, @argv || []
|
59
|
+
puts "#{command} #{command_args.join(' ')}" if @@global.verbose > 1
|
60
|
+
|
61
|
+
# otherwise, we'll open an ssh session or print command
|
62
|
+
else
|
63
|
+
command, command_args = :interactive_ssh, @option.print.nil?
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
checked = false
|
68
|
+
rudy = Rudy::Machines.new
|
69
|
+
lt = rudy.list do |machine|
|
70
|
+
# Print header
|
71
|
+
if @@global.quiet
|
72
|
+
print "You are #{ssh_opts[:user].to_s.bright}. " if !checked # only the 1st
|
73
|
+
else
|
74
|
+
print "Connecting #{ssh_opts[:user].to_s.bright}@#{machine.dns_public} "
|
75
|
+
puts "#{machine.name} (#{machine.awsid})"
|
76
|
+
end
|
77
|
+
|
78
|
+
# Make sure we want to run this command on all instances
|
79
|
+
if !checked && command != :interactive_ssh
|
80
|
+
execute_check(:medium) if ssh_opts[:user] == "root"
|
81
|
+
checked = true
|
82
|
+
end
|
83
|
+
|
84
|
+
# Open the connection and run the command
|
85
|
+
rbox = Rye::Box.new(machine.dns_public, ssh_opts)
|
86
|
+
ret = rbox.send(command, command_args)
|
87
|
+
puts ret unless command == :interactive_ssh
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Rudy; module CLI;
|
4
|
+
class Routines < Rudy::CLI::CommandBase
|
5
|
+
|
6
|
+
def startup
|
7
|
+
rr = Rudy::Routines::Startup.new
|
8
|
+
rr.execute
|
9
|
+
|
10
|
+
puts $/, "The following machines are now available:"
|
11
|
+
rmach = Rudy::Machines.new
|
12
|
+
rmach.list do |machine|
|
13
|
+
puts machine.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
if @@global.environment == @@config.default.environment &&
|
17
|
+
@@global.role == @@config.default.role
|
18
|
+
puts
|
19
|
+
puts "Try: #{$0} -u root ssh"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def release
|
25
|
+
rr = Rudy::Routines::Release.new
|
26
|
+
rmach = Rudy::Machines.new
|
27
|
+
startup unless rmach.running?
|
28
|
+
rr.execute
|
29
|
+
end
|
30
|
+
|
31
|
+
def shutdown
|
32
|
+
rr = Rudy::Routines::Shutdown.new
|
33
|
+
routine = fetch_routine_config(:shutdown)
|
34
|
+
|
35
|
+
puts "All machines in #{current_machine_group} will be shutdown and"
|
36
|
+
if routine && routine.disks
|
37
|
+
if routine.disks.destroy
|
38
|
+
puts "the following filesystems will be destroyed:".color(:red)
|
39
|
+
puts routine.disks.destroy.keys.join($/).bright
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
execute_check :medium
|
44
|
+
|
45
|
+
rr.execute
|
46
|
+
|
47
|
+
rinst = Rudy::AWS::EC2::Instances.new(@@global.accesskey, @@global.secretkey, @@global.region)
|
48
|
+
lt = rinst.list_group(current_machine_group, :any) do |inst|
|
49
|
+
puts @@global.verbose > 0 ? inst.inspect : inst.dump(@@global.format)
|
50
|
+
end
|
51
|
+
puts "No instances running" if !lt || lt.empty?
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
end
|
56
|
+
end; end
|
57
|
+
|
data/lib/rudy/config.rb
CHANGED
@@ -1,92 +1,97 @@
|
|
1
1
|
|
2
|
-
|
3
2
|
module Rudy
|
4
3
|
require 'caesars'
|
5
|
-
|
6
|
-
class AWSInfo < Caesars
|
7
|
-
def valid?
|
8
|
-
(!account.nil? && !accesskey.nil? && !secretkey.nil?) &&
|
9
|
-
(!account.empty? && !accesskey.empty? && !secretkey.empty?)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class Defaults < Caesars
|
14
|
-
end
|
15
4
|
|
16
|
-
|
17
|
-
|
5
|
+
class Config < Caesars::Config
|
6
|
+
require 'rudy/config/objects'
|
18
7
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
25
|
-
def restore(*args, &b)
|
26
|
-
hash_handler(:restore, *args, &b)
|
27
|
-
end
|
28
|
-
def mount(*args, &b)
|
29
|
-
hash_handler(:mount, *args, &b)
|
30
|
-
end
|
8
|
+
dsl Rudy::Config::Accounts::DSL
|
9
|
+
dsl Rudy::Config::Defaults::DSL
|
10
|
+
dsl Rudy::Config::Routines::DSL
|
11
|
+
dsl Rudy::Config::Machines::DSL
|
12
|
+
dsl Rudy::Config::Networks::DSL
|
31
13
|
|
32
|
-
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
# create "/path/2" # Available as hash: [action][disks][create][/path/2] == {}
|
39
|
-
# create "/path/4" do # Available as hash: [action][disks][create][/path/4] == {size => 14}
|
40
|
-
# size 14
|
41
|
-
# end
|
42
|
-
# end
|
43
|
-
# end
|
44
|
-
#
|
45
|
-
def hash_handler(caesars_meth, *args, &b)
|
46
|
-
# TODO: Move to caesars
|
47
|
-
return @caesars_properties[caesars_meth] if @caesars_properties.has_key?(caesars_meth) && args.empty? && b.nil?
|
48
|
-
return nil if args.empty? && b.nil?
|
49
|
-
return method_missing(caesars_meth, *args, &b) if args.empty?
|
50
|
-
|
51
|
-
caesars_name = args.shift
|
52
|
-
|
53
|
-
prev = @caesars_pointer
|
54
|
-
@caesars_pointer[caesars_meth] ||= Caesars::Hash.new
|
55
|
-
hash = Caesars::Hash.new
|
56
|
-
@caesars_pointer = hash
|
57
|
-
b.call if b
|
58
|
-
@caesars_pointer = prev
|
59
|
-
@caesars_pointer[caesars_meth][caesars_name] = hash
|
60
|
-
@caesars_pointer = prev
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
class Machines < Caesars
|
65
|
-
end
|
66
|
-
|
67
|
-
class Config < Caesars::Config
|
68
|
-
dsl Rudy::AWSInfo::DSL
|
69
|
-
dsl Rudy::Defaults::DSL
|
70
|
-
dsl Rudy::Routines::DSL
|
71
|
-
dsl Rudy::Machines::DSL
|
14
|
+
# TODO: auto-generate in caesars
|
15
|
+
def accounts?; self.respond_to?(:accounts) && !self[:accounts].nil?; end
|
16
|
+
def defaults?; self.respond_to?(:defaults) && !self[:defaults].nil?; end
|
17
|
+
def machines?; self.respond_to?(:machines) && !self[:machines].nil?; end
|
18
|
+
def routines?; self.respond_to?(:routines) && !self[:routines].nil?; end
|
19
|
+
def networks?; self.respond_to?(:networks) && !self[:networks].nil?; end
|
72
20
|
|
73
21
|
def postprocess
|
74
|
-
#
|
75
|
-
self.awsinfo.cert &&= File.expand_path(self.awsinfo.cert)
|
76
|
-
self.awsinfo.privatekey &&= File.expand_path(self.awsinfo.privatekey)
|
22
|
+
#raise "There is no AWS info configured" if self.accounts.nil?
|
77
23
|
|
24
|
+
# These don't work anymore. Caesars bug?
|
25
|
+
#if accounts? && !self.accounts.aws.nil?
|
26
|
+
# self.accounts.aws.cert &&= File.expand_path(self.accounts.aws.cert)
|
27
|
+
# self.accounts.aws.privatekey &&= File.expand_path(self.accounts.aws.privatekey)
|
28
|
+
#end
|
78
29
|
end
|
79
30
|
|
80
|
-
def look_and_load
|
31
|
+
def look_and_load(adhoc_path=nil)
|
81
32
|
cwd = Dir.pwd
|
82
|
-
|
83
|
-
|
33
|
+
cwd_path = File.join(cwd, '.rudy', 'config')
|
34
|
+
|
35
|
+
# Attempt to load the core configuration file first.
|
36
|
+
# The "core" config file can have any or all configuration
|
37
|
+
# but it should generally only contain the access identifiers
|
38
|
+
# and defaults. That's why we only load one of them.
|
39
|
+
core_config_paths = [adhoc_path, cwd_path, Rudy::CONFIG_FILE]
|
40
|
+
core_config_paths.each do |path|
|
41
|
+
next unless path && File.exists?(path)
|
42
|
+
@paths << path
|
43
|
+
break
|
44
|
+
end
|
45
|
+
|
46
|
+
# Rudy then looks for the rest of the config in these locations
|
47
|
+
@paths += Dir.glob(File.join(cwd, 'Rudyfile')) || []
|
84
48
|
@paths += Dir.glob(File.join(cwd, 'config', 'rudy', '*.rb')) || []
|
85
49
|
@paths += Dir.glob(File.join(cwd, '.rudy', '*.rb')) || []
|
50
|
+
@paths += Dir.glob(File.join('/etc', 'rudy', '*.rb')) || []
|
51
|
+
@paths &&= @paths.uniq
|
52
|
+
|
86
53
|
refresh
|
87
54
|
end
|
55
|
+
|
88
56
|
|
89
|
-
|
57
|
+
def self.init_config_dir
|
58
|
+
|
59
|
+
unless File.exists?(Rudy::CONFIG_DIR)
|
60
|
+
puts "Creating #{Rudy::CONFIG_DIR}"
|
61
|
+
Dir.mkdir(Rudy::CONFIG_DIR, 0700)
|
62
|
+
end
|
63
|
+
|
64
|
+
unless File.exists?(Rudy::CONFIG_FILE)
|
65
|
+
puts "Creating #{Rudy::CONFIG_FILE}"
|
66
|
+
rudy_config = Rudy::Utils.without_indent %Q{
|
67
|
+
# Amazon Web Services
|
68
|
+
# Account access indentifiers.
|
69
|
+
accounts do
|
70
|
+
aws do
|
71
|
+
name "Rudy Default"
|
72
|
+
accountnum ""
|
73
|
+
accesskey ""
|
74
|
+
secretkey ""
|
75
|
+
privatekey "~/path/2/pk-xxxx.pem"
|
76
|
+
cert "~/path/2/cert-xxxx.pem"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Global Defaults
|
81
|
+
# Define the values to use unless otherwise specified on the command-line.
|
82
|
+
defaults do
|
83
|
+
region :"us-east-1"
|
84
|
+
zone :"us-east-1b"
|
85
|
+
environment :stage
|
86
|
+
role :app
|
87
|
+
position "01"
|
88
|
+
user ENV['USER'].to_sym
|
89
|
+
end
|
90
|
+
}
|
91
|
+
Rudy::Utils.write_to_file(Rudy::CONFIG_FILE, rudy_config, 'w', 0600)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
90
95
|
end
|
91
96
|
end
|
92
97
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
class Rudy::Config
|
4
|
+
class Machines < Caesars
|
5
|
+
end
|
6
|
+
|
7
|
+
|
8
|
+
class Accounts < Caesars
|
9
|
+
def valid?
|
10
|
+
(!aws.nil? && !aws.accesskey.nil? && !aws.secretkey.nil?) &&
|
11
|
+
(!aws.account.empty? && !aws.accesskey.empty? && !aws.secretkey.empty?)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Defaults < Caesars
|
16
|
+
end
|
17
|
+
|
18
|
+
class Networks < Caesars
|
19
|
+
end
|
20
|
+
|
21
|
+
class Routines < Caesars
|
22
|
+
|
23
|
+
forced_hash :create
|
24
|
+
forced_hash :destroy
|
25
|
+
forced_hash :restore
|
26
|
+
forced_hash :mount
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
data/lib/rudy/disks.rb
ADDED
@@ -0,0 +1,248 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Rudy
|
4
|
+
class Disk < Storable
|
5
|
+
include Rudy::MetaData::ObjectBase
|
6
|
+
|
7
|
+
field :rtype
|
8
|
+
field :awsid
|
9
|
+
field :status
|
10
|
+
field :instid
|
11
|
+
|
12
|
+
field :region
|
13
|
+
field :zone
|
14
|
+
field :environment
|
15
|
+
field :role
|
16
|
+
field :position
|
17
|
+
field :path
|
18
|
+
|
19
|
+
field :device
|
20
|
+
field :size
|
21
|
+
#field :backups => Array
|
22
|
+
|
23
|
+
field :mounted
|
24
|
+
|
25
|
+
def init(path=nil, size=nil, device=nil, position=nil)
|
26
|
+
@path, @size, @device = path, size, device
|
27
|
+
@rtype = 'disk'
|
28
|
+
@region = @@global.region
|
29
|
+
@zone = @@global.zone
|
30
|
+
@environment = @@global.environment
|
31
|
+
@role = @@global.role
|
32
|
+
@position = position || @@global.position
|
33
|
+
@mounted = false
|
34
|
+
postprocess
|
35
|
+
end
|
36
|
+
|
37
|
+
def postprocess
|
38
|
+
@size &&= @size.to_i
|
39
|
+
@mounted = true if @mounted == "true"
|
40
|
+
end
|
41
|
+
|
42
|
+
def liner_note
|
43
|
+
info = @awsid && !@awsid.empty? ? @awsid : 'no volume'
|
44
|
+
"%s %s" % [self.name.bright, info]
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_s(with_titles=true)
|
48
|
+
update
|
49
|
+
mtd = @mounted ? "mounted" : @status
|
50
|
+
"%s; %3sGB; %s; %s" % [liner_note, @size, @device, mtd]
|
51
|
+
end
|
52
|
+
|
53
|
+
def inspect
|
54
|
+
lines = []
|
55
|
+
lines << liner_note
|
56
|
+
field_names.each do |key|
|
57
|
+
next unless self.respond_to?(key)
|
58
|
+
val = self.send(key)
|
59
|
+
lines << sprintf(" %22s: %s", key, (val.is_a?(Array) ? val.join(', ') : val))
|
60
|
+
end
|
61
|
+
lines.join($/)
|
62
|
+
end
|
63
|
+
|
64
|
+
def name
|
65
|
+
sep=File::SEPARATOR
|
66
|
+
dirs = @path.split sep if @path && !@path.empty?
|
67
|
+
dirs.shift while dirs && (dirs[0].nil? || dirs[0].empty?)
|
68
|
+
super("disk", @zone, @environment, @role, @position, *dirs)
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
def create(snapshot=nil)
|
74
|
+
raise "#{name} is already running" if exists?
|
75
|
+
vol = @rvol.create(@size, @zone, snapshot)
|
76
|
+
@awsid = vol.awsid
|
77
|
+
self.save
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
81
|
+
def attach(instid)
|
82
|
+
raise "No volume id" unless exists?
|
83
|
+
vol = @rvol.attach(@awsid, instid, @device)
|
84
|
+
end
|
85
|
+
|
86
|
+
def detach
|
87
|
+
raise "No volume id" unless exists?
|
88
|
+
vol = @rvol.detach(@awsid)
|
89
|
+
end
|
90
|
+
|
91
|
+
def destroy(force=false)
|
92
|
+
if @awsid && !deleting?
|
93
|
+
if !force
|
94
|
+
raise Rudy::AWS::EC2::VolumeNotAvailable, @awsid if attached?
|
95
|
+
else
|
96
|
+
detach if exists? && attached?
|
97
|
+
sleep 0.1
|
98
|
+
end
|
99
|
+
raise Rudy::AWS::EC2::VolumeNotAvailable, @awsid if in_use?
|
100
|
+
@rvol.destroy(@awsid) if exists? && available?
|
101
|
+
end
|
102
|
+
super() # quotes, otherwise Ruby will send this method's args
|
103
|
+
end
|
104
|
+
|
105
|
+
def update
|
106
|
+
return false unless @awsid
|
107
|
+
@volume = @rvol.get(@awsid)
|
108
|
+
if @volume.is_a?(Rudy::AWS::EC2::Volume)
|
109
|
+
@status = @volume.status
|
110
|
+
@instid = @volume.instid
|
111
|
+
save
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def to_query(more=[], less=[])
|
116
|
+
super([:path, *more], less) # Add path to the default fields
|
117
|
+
end
|
118
|
+
|
119
|
+
def to_select(more=[], less=[])
|
120
|
+
super([:path, *more], less)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Does this disk have enough info to be saved or used?
|
124
|
+
# The test is based on the same criteria for building
|
125
|
+
# SimpleDB queries.
|
126
|
+
def valid?
|
127
|
+
criteria = build_criteria([:path]).flatten
|
128
|
+
criteria.size == criteria.compact.size
|
129
|
+
end
|
130
|
+
|
131
|
+
def mounted?
|
132
|
+
@mounted && @mounted == true
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
%w[exists? deleting? available? attached? in_use?].each do |state|
|
137
|
+
define_method(state) do
|
138
|
+
return false if @awsid.nil? || @awsid.empty?
|
139
|
+
@rvol.send(state, @awsid) rescue false # deleting?, available?, etc...
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Disks
|
145
|
+
include Rudy::MetaData
|
146
|
+
|
147
|
+
|
148
|
+
def create(&each_mach)
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
def destroy(&each_mach)
|
154
|
+
#raise MachineGroupNotRunning, current_machine_group unless running?
|
155
|
+
#raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
|
156
|
+
list do |disk|
|
157
|
+
puts "Destroying #{disk.name}"
|
158
|
+
disk.destroy
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def list(more=[], less=[], &each_disk)
|
163
|
+
disks = list_as_hash(&each_disk)
|
164
|
+
disks &&= disks.values
|
165
|
+
disks
|
166
|
+
end
|
167
|
+
|
168
|
+
def list_as_hash(more=[], less=[], &each_disk)
|
169
|
+
query = to_select([:rtype, 'disk'], less)
|
170
|
+
list = @sdb.select(query) || {}
|
171
|
+
disks = {}
|
172
|
+
list.each_pair do |n,d|
|
173
|
+
disks[n] = Rudy::Disk.from_hash(d)
|
174
|
+
end
|
175
|
+
disks.each_pair { |n,disk| each_disk.call(disk) } if each_disk
|
176
|
+
disks = nil if disks.empty?
|
177
|
+
disks
|
178
|
+
end
|
179
|
+
|
180
|
+
def get(rname=nil)
|
181
|
+
dhash = @sdb.get(Rudy::DOMAIN, rname)
|
182
|
+
return nil if dhash.nil? || dhash.empty?
|
183
|
+
d = Rudy::Disk.from_hash(dhash)
|
184
|
+
d.update if d
|
185
|
+
d
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
def running?
|
190
|
+
!list.nil?
|
191
|
+
# TODO: add logic that checks whether the instances are running.
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
|
203
|
+
__END__
|
204
|
+
|
205
|
+
def format(instance)
|
206
|
+
raise "No instance supplied" unless instance
|
207
|
+
raise "Disk not valid" unless self.valid?
|
208
|
+
|
209
|
+
begin
|
210
|
+
puts "Creating the filesystem (mkfs.ext3 -F #{disk.device})".bright
|
211
|
+
ssh_command instance.dns_public, current_user_keypairpath, @@global.user, "mkfs.ext3 -F #{disk.device}"
|
212
|
+
sleep 1
|
213
|
+
rescue => ex
|
214
|
+
@logger.puts ex.backtrace if debug?
|
215
|
+
raise "Error formatting #{disk.path}: #{ex.message}"
|
216
|
+
end
|
217
|
+
true
|
218
|
+
end
|
219
|
+
def mount(instance)
|
220
|
+
raise "No instance supplied" unless instance
|
221
|
+
disk = find_disk(opts[:disk] || opts[:path])
|
222
|
+
raise "Disk #{opts[:disk] || opts[:path]} cannot be found" unless disk
|
223
|
+
switch_user(:root)
|
224
|
+
begin
|
225
|
+
puts "Mounting #{disk.device} to #{disk.path}".bright
|
226
|
+
ssh_command instance.dns_public, current_user_keypairpath, @@global.user, "mkdir -p #{disk.path} && mount -t ext3 #{disk.device} #{disk.path}"
|
227
|
+
rescue => ex
|
228
|
+
@logger.puts ex.backtrace if debug?
|
229
|
+
raise "Error mounting #{disk.path}: #{ex.message}"
|
230
|
+
end
|
231
|
+
true
|
232
|
+
end
|
233
|
+
|
234
|
+
def unmount(instance)
|
235
|
+
raise "No instance supplied" unless instance
|
236
|
+
disk = find_disk(opts[:disk] || opts[:path])
|
237
|
+
raise "Disk #{opts[:disk] || opts[:path]} cannot be found" unless disk
|
238
|
+
switch_user(:root)
|
239
|
+
begin
|
240
|
+
puts "Unmounting #{disk.path}...".bright
|
241
|
+
ssh_command instance.dns_public, current_user_keypairpath, global.user, "umount #{disk.path}"
|
242
|
+
sleep 1
|
243
|
+
rescue => ex
|
244
|
+
@logger.puts ex.backtrace if debug?
|
245
|
+
raise "Error unmounting #{disk.path}: #{ex.message}"
|
246
|
+
end
|
247
|
+
true
|
248
|
+
end
|