rudy 0.4.0 → 0.6.0
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/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
|