solutious-rudy 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +8 -9
- data/README.rdoc +48 -7
- data/Rakefile +102 -7
- data/Rudyfile +28 -0
- data/bin/ird +162 -0
- data/bin/rudy +287 -93
- data/lib/annoy.rb +227 -0
- data/lib/aws_sdb/service.rb +1 -1
- data/lib/console.rb +20 -4
- data/lib/escape.rb +305 -0
- data/lib/rudy.rb +265 -125
- data/lib/rudy/aws.rb +61 -26
- data/lib/rudy/aws/ec2.rb +20 -296
- data/lib/rudy/aws/ec2/address.rb +121 -0
- data/lib/rudy/aws/ec2/group.rb +241 -0
- data/lib/rudy/aws/ec2/image.rb +46 -0
- data/lib/rudy/aws/ec2/instance.rb +407 -0
- data/lib/rudy/aws/ec2/keypair.rb +92 -0
- data/lib/rudy/aws/ec2/snapshot.rb +87 -0
- data/lib/rudy/aws/ec2/volume.rb +234 -0
- data/lib/rudy/aws/simpledb.rb +33 -15
- data/lib/rudy/cli.rb +142 -0
- data/lib/rudy/cli/addresses.rb +85 -0
- data/lib/rudy/cli/backups.rb +175 -0
- data/lib/rudy/{command → cli}/config.rb +18 -13
- data/lib/rudy/cli/deploy.rb +12 -0
- data/lib/rudy/cli/disks.rb +125 -0
- data/lib/rudy/cli/domains.rb +17 -0
- data/lib/rudy/cli/groups.rb +77 -0
- data/lib/rudy/{command → cli}/images.rb +18 -6
- data/lib/rudy/cli/instances.rb +142 -0
- data/lib/rudy/cli/keypairs.rb +47 -0
- data/lib/rudy/cli/manager.rb +51 -0
- data/lib/rudy/{command → cli}/release.rb +10 -10
- data/lib/rudy/cli/routines.rb +80 -0
- data/lib/rudy/cli/volumes.rb +121 -0
- data/lib/rudy/command/addresses.rb +62 -39
- data/lib/rudy/command/backups.rb +60 -170
- data/lib/rudy/command/disks-old.rb +322 -0
- data/lib/rudy/command/disks.rb +5 -209
- data/lib/rudy/command/domains.rb +34 -0
- data/lib/rudy/command/groups.rb +105 -48
- data/lib/rudy/command/instances.rb +263 -70
- data/lib/rudy/command/keypairs.rb +149 -0
- data/lib/rudy/command/manager.rb +65 -0
- data/lib/rudy/command/volumes.rb +110 -49
- data/lib/rudy/config.rb +90 -70
- data/lib/rudy/config/objects.rb +67 -0
- data/lib/rudy/huxtable.rb +253 -0
- data/lib/rudy/metadata/backup.rb +23 -48
- data/lib/rudy/metadata/disk.rb +79 -68
- data/lib/rudy/metadata/machine.rb +34 -0
- data/lib/rudy/routines.rb +54 -0
- data/lib/rudy/routines/disk_handler.rb +190 -0
- data/lib/rudy/routines/release.rb +15 -0
- data/lib/rudy/routines/script_runner.rb +65 -0
- data/lib/rudy/routines/shutdown.rb +42 -0
- data/lib/rudy/routines/startup.rb +48 -0
- data/lib/rudy/utils.rb +57 -2
- data/lib/storable.rb +11 -5
- data/lib/sysinfo.rb +274 -0
- data/rudy.gemspec +84 -20
- data/support/randomize-root-password +45 -0
- data/support/rudy-ec2-startup +5 -5
- data/support/update-ec2-ami-tools +20 -0
- data/test/05_config/00_setup_test.rb +24 -0
- data/test/05_config/30_machines_test.rb +69 -0
- data/test/20_sdb/00_setup_test.rb +31 -0
- data/test/20_sdb/10_domains_test.rb +113 -0
- data/test/25_ec2/00_setup_test.rb +34 -0
- data/test/25_ec2/10_keypairs_test.rb +33 -0
- data/test/25_ec2/20_groups_test.rb +139 -0
- data/test/25_ec2/30_addresses_test.rb +35 -0
- data/test/25_ec2/40_volumes_test.rb +46 -0
- data/test/25_ec2/50_snapshots_test.rb +69 -0
- data/test/26_ec2_instances/00_setup_test.rb +33 -0
- data/test/26_ec2_instances/10_instances_test.rb +81 -0
- data/test/26_ec2_instances/50_images_test.rb +13 -0
- data/test/30_sdb_metadata/00_setup_test.rb +28 -0
- data/test/30_sdb_metadata/10_disks_test.rb +99 -0
- data/test/30_sdb_metadata/20_backups_test.rb +102 -0
- data/test/50_commands/00_setup_test.rb +11 -0
- data/test/50_commands/10_keypairs_test.rb +79 -0
- data/test/50_commands/20_groups_test.rb +77 -0
- data/test/50_commands/40_volumes_test.rb +55 -0
- data/test/50_commands/50_instances_test.rb +110 -0
- data/test/coverage.txt +51 -0
- data/test/helper.rb +35 -0
- data/tryouts/disks.rb +55 -0
- data/tryouts/nested_methods.rb +36 -0
- data/tryouts/session_tryout.rb +48 -0
- metadata +94 -25
- data/bin/rudy-ec2 +0 -108
- data/lib/rudy/command/base.rb +0 -839
- data/lib/rudy/command/deploy.rb +0 -12
- data/lib/rudy/command/environment.rb +0 -74
- data/lib/rudy/command/machines.rb +0 -170
- data/lib/rudy/command/metadata.rb +0 -41
- data/lib/rudy/metadata.rb +0 -26
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Rudy
|
4
|
+
module CLI
|
5
|
+
class Manager < Rudy::CLI::Base
|
6
|
+
|
7
|
+
|
8
|
+
# Print Rudy's metadata to STDOUT
|
9
|
+
def metadata
|
10
|
+
group_metadata.each_pair do |n,h|
|
11
|
+
puts n.bright
|
12
|
+
puts h.inspect, ""
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def destroy_metadata_valid?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def destroy_metadata
|
21
|
+
@sdb.domains.destroy(RUDY_DOMAIN)
|
22
|
+
end
|
23
|
+
|
24
|
+
# TODO: WHERE TO CREATE DOMAIN???????????????????????????
|
25
|
+
|
26
|
+
def create_domain
|
27
|
+
puts "Creating SimpleDB Domain called #{RUDY_DOMAIN}".bright
|
28
|
+
rmanager = Rudy::Manager.new(:config => @config, :global => @global)
|
29
|
+
rmanager.create_domain(RUDY_DOMAIN)
|
30
|
+
doms = rmanager.domains || []
|
31
|
+
puts "Domains: #{doms.join(", ")}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def info
|
35
|
+
puts "Rudy Manager".bright
|
36
|
+
rmanager = Rudy::Manager.new(:config => @config, :global => @global)
|
37
|
+
doms = rmanager.domains
|
38
|
+
puts "Domains: #{doms.join(", ")}"
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def check_environment
|
43
|
+
raise "No Amazon keys provided!" unless has_keys?
|
44
|
+
raise "No SSH keypairs provided!" unless has_keypair?
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
@@ -1,8 +1,8 @@
|
|
1
1
|
|
2
2
|
|
3
3
|
module Rudy
|
4
|
-
module
|
5
|
-
class Release < Rudy::
|
4
|
+
module CLI
|
5
|
+
class Release < Rudy::CLI::Base
|
6
6
|
|
7
7
|
|
8
8
|
|
@@ -61,7 +61,7 @@ module Rudy
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def rerelease
|
64
|
-
puts "Updating release from working copy".
|
64
|
+
puts "Updating release from working copy".bright
|
65
65
|
|
66
66
|
tag, revision = @scm.local_info
|
67
67
|
puts "tag: #{tag}"
|
@@ -71,7 +71,7 @@ module Rudy
|
|
71
71
|
|
72
72
|
if @scm
|
73
73
|
|
74
|
-
puts "Running SCM command".
|
74
|
+
puts "Running SCM command".bright
|
75
75
|
ssh do |session|
|
76
76
|
cmd = "svn #{@scm_params[:command]}"
|
77
77
|
puts "#{cmd}"
|
@@ -91,15 +91,15 @@ module Rudy
|
|
91
91
|
# <li>Executes release routines</li>
|
92
92
|
def release
|
93
93
|
# TODO: store metadata about release with local username and hostname
|
94
|
-
puts "Creating release from working copy".
|
94
|
+
puts "Creating release from working copy".bright
|
95
95
|
|
96
|
-
exit unless are_you_sure?
|
96
|
+
exit unless Annoy.are_you_sure?(:low)
|
97
97
|
|
98
98
|
tag = @scm.create_release(@global.local_user, @option.msg)
|
99
99
|
puts "Done! (#{tag})"
|
100
100
|
|
101
101
|
if @option.switch
|
102
|
-
puts "Switching working copy to new tag".
|
102
|
+
puts "Switching working copy to new tag".bright
|
103
103
|
@scm.switch_working_copy(tag)
|
104
104
|
end
|
105
105
|
|
@@ -107,13 +107,13 @@ module Rudy
|
|
107
107
|
|
108
108
|
switch_user("root")
|
109
109
|
|
110
|
-
puts "Starting #{machine_group}".
|
110
|
+
puts "Starting #{machine_group}".bright
|
111
111
|
|
112
112
|
instances = @ec2.instances.create(@option.image, machine_group.to_s, File.basename(keypairpath), machine_data.to_yaml, @global.zone)
|
113
113
|
inst = instances.first
|
114
114
|
|
115
115
|
if @option.address ||= machine_address
|
116
|
-
puts "Associating #{@option.address} to #{inst[:aws_instance_id]}".
|
116
|
+
puts "Associating #{@option.address} to #{inst[:aws_instance_id]}".bright
|
117
117
|
@ec2.addresses.associate(inst[:aws_instance_id], @option.address)
|
118
118
|
end
|
119
119
|
|
@@ -127,7 +127,7 @@ module Rudy
|
|
127
127
|
|
128
128
|
if @scm
|
129
129
|
|
130
|
-
puts "Running SCM command".
|
130
|
+
puts "Running SCM command".bright
|
131
131
|
ssh do |session|
|
132
132
|
cmd = "svn #{@scm_params[:command]} #{tag} #{@scm_params[:path]}"
|
133
133
|
puts "#{cmd}"
|
@@ -0,0 +1,80 @@
|
|
1
|
+
|
2
|
+
module Rudy
|
3
|
+
module CLI
|
4
|
+
class Routines < Rudy::CLI::Base
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
def startup_valid?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
def startup
|
12
|
+
puts "Starting a machine group".bright
|
13
|
+
opts = {}
|
14
|
+
opts[:ami] = @option.image if @option.image
|
15
|
+
opts[:group] = @option.group if @option.group
|
16
|
+
#exit unless Annoy.are_you_sure?
|
17
|
+
|
18
|
+
rroutine = Rudy::Routines::Startup.new(:config => @config, :global => @global)
|
19
|
+
instances = rroutine.startup(opts)
|
20
|
+
|
21
|
+
puts "Done!"
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
def restart_valid?
|
28
|
+
shutdown_valid?
|
29
|
+
end
|
30
|
+
def restart
|
31
|
+
puts "Restarting #{machine_group}: #{@list.keys.join(', ')}".bright
|
32
|
+
switch_user("root")
|
33
|
+
exit unless Annoy.are_you_sure?(:medium)
|
34
|
+
|
35
|
+
@list.each do |id, inst|
|
36
|
+
execute_routines(@list.values, :restart, :before)
|
37
|
+
end
|
38
|
+
|
39
|
+
puts "Restarting instances: #{@list.keys.join(', ')}".bright
|
40
|
+
@ec2.instances.restart @list.keys
|
41
|
+
sleep 10 # Wait for state to change and SSH to shutdown
|
42
|
+
|
43
|
+
@list.keys.each do |id|
|
44
|
+
wait_for_machine(id)
|
45
|
+
end
|
46
|
+
|
47
|
+
execute_disk_routines(@list.values, :restart)
|
48
|
+
|
49
|
+
@list.each do |id, inst|
|
50
|
+
execute_routines(@list.values, :restart, :after)
|
51
|
+
end
|
52
|
+
|
53
|
+
puts "Done!"
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
def shutdown_valid?
|
61
|
+
raise "Cannot specify both instance ID and group name" if @argv.awsid && @option.group
|
62
|
+
raise "I will not help you ruin production!" if @global.environment == "prod" # TODO: use_caution?, locked?
|
63
|
+
true
|
64
|
+
end
|
65
|
+
def shutdown
|
66
|
+
puts "Shutting down a machine group".bright
|
67
|
+
opts = {}
|
68
|
+
opts[:group] = @option.group if @option.group
|
69
|
+
opts[:id] = @argv.awsid if @argv.awsid
|
70
|
+
opts[:id] &&= [opts[:id]].flatten
|
71
|
+
|
72
|
+
msg = opts[:id] ? "instances: #{opts[:id].join(', ')}" : (opts[:group] ? "group: #{opts[:group]}" : '')
|
73
|
+
puts "This command also affects the disks on these machines! (according to your routines config)"
|
74
|
+
#exit unless Annoy.are_you_sure?(:medium) # TODO: Check if instances are running before this
|
75
|
+
|
76
|
+
puts "TBD"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Rudy
|
4
|
+
module CLI
|
5
|
+
class Volumes < Rudy::CLI::Base
|
6
|
+
|
7
|
+
|
8
|
+
def destroy_volume_valid?
|
9
|
+
raise "You must supply a volume ID. See rudy volume -h" unless @argv.volid
|
10
|
+
|
11
|
+
@rvol = Rudy::Volumes.new(:config => @config, :global => @global)
|
12
|
+
|
13
|
+
@volume = @rvol.get(@argv.volid)
|
14
|
+
|
15
|
+
raise "Volume #{@argv.volid} does not exist" unless @volume
|
16
|
+
|
17
|
+
raise "Volume #{@argv.volid} is still in-use" if @volume.in_use?
|
18
|
+
raise "Volume #{@argv.volid} is still attached" if @volume.attached?
|
19
|
+
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def destroy_volume
|
24
|
+
puts "Destroy Volume".bright, $/
|
25
|
+
|
26
|
+
puts "Destroying #{@volume.awsid}"
|
27
|
+
exit unless Annoy.are_you_sure?(:medium)
|
28
|
+
|
29
|
+
ret = @rvol.destroy(@volume.awsid)
|
30
|
+
raise "Failed" unless ret
|
31
|
+
|
32
|
+
vol = @rvol.get(@volume.awsid)
|
33
|
+
|
34
|
+
puts vol.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def volume_create_valid?
|
39
|
+
raise "You must supply a volume size. See rudy volume -h" unless @option.size
|
40
|
+
raise "You have no zone configured. Check #{RUDY_CONFIG_FILE}." unless @global.zone
|
41
|
+
true
|
42
|
+
end
|
43
|
+
def volume_create
|
44
|
+
puts "Create Volume".bright
|
45
|
+
|
46
|
+
exit unless Annoy.are_you_sure?(:medium)
|
47
|
+
|
48
|
+
rvol = Rudy::Volumes.new(:config => @config, :global => @global)
|
49
|
+
vol = rvol.create(@option.size, @global.zone, @option.snapshot)
|
50
|
+
|
51
|
+
puts vol.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
def volume_attach_valid?
|
55
|
+
raise "You must supply a volume ID. See rudy volume -h" unless @argv.volid
|
56
|
+
raise "You must supply an instance ID. See rudy volume -h" unless @argv.instid
|
57
|
+
|
58
|
+
@rvol = Rudy::Volumes.new(:config => @config, :global => @global)
|
59
|
+
@rmach = Rudy::Instances.new(:config => @config, :global => @global)
|
60
|
+
raise "Volume #{@argv.volid} does not exist" unless @rvol.exists?(@argv.volid)
|
61
|
+
raise "Instance #{@argv.instid} does not exist" unless @rmach.exists?(@argv.instid)
|
62
|
+
|
63
|
+
true
|
64
|
+
end
|
65
|
+
def volume_attach
|
66
|
+
puts "Attach Volume".bright, $/
|
67
|
+
|
68
|
+
@option.device ||= "/dev/sdh"
|
69
|
+
|
70
|
+
puts "Attaching #{@argv.volid} to #{@argv.instid} on #{@option.device}"
|
71
|
+
exit unless Annoy.are_you_sure?(:low)
|
72
|
+
|
73
|
+
ret = @rvol.attach(@argv.volid, @argv.instid, @option.device)
|
74
|
+
raise "Attach failed" unless ret
|
75
|
+
volume = @rvol.get(@argv.volid)
|
76
|
+
puts volume.to_s
|
77
|
+
end
|
78
|
+
|
79
|
+
def volume_detach_valid?
|
80
|
+
raise "You must supply a volume ID. See rudy volume -h" unless @argv.volid
|
81
|
+
|
82
|
+
@rvol = Rudy::Volumes.new(:config => @config, :global => @global)
|
83
|
+
|
84
|
+
@volume = @rvol.get(@argv.volid)
|
85
|
+
|
86
|
+
raise "Volume #{@argv.volid} does not exist" unless @volume
|
87
|
+
|
88
|
+
#raise "Volume #{@argv.volid} is in use" unless @volume.in_use?
|
89
|
+
raise "Volume #{@argv.volid} is not attached" unless @volume.attached?
|
90
|
+
|
91
|
+
true
|
92
|
+
end
|
93
|
+
def volume_detach
|
94
|
+
puts "Detach Volume".bright, $/
|
95
|
+
|
96
|
+
puts "Detaching #{@volume.awsid} from #{@volume.instid}"
|
97
|
+
exit unless Annoy.are_you_sure?(:low)
|
98
|
+
|
99
|
+
ret = @rvol.detach(@volume.awsid)
|
100
|
+
raise "Detach failed" unless ret
|
101
|
+
volume = @rvol.get(@volume.awsid)
|
102
|
+
puts volume.to_s
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
def volume
|
107
|
+
puts "Volumes".bright, $/
|
108
|
+
|
109
|
+
rvol = Rudy::Volumes.new(:config => @config, :global => @global)
|
110
|
+
volumes = rvol.list || []
|
111
|
+
volumes.each do |volume|
|
112
|
+
puts '-'*60
|
113
|
+
puts volume.to_s
|
114
|
+
end
|
115
|
+
puts "No volumes" if volumes.empty?
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
@@ -1,46 +1,69 @@
|
|
1
1
|
|
2
2
|
|
3
|
-
|
4
3
|
module Rudy
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
puts "%s: %s %s" % [inst[:aws_groups], inst[:aws_instance_id], inst[:dns_name]]
|
38
|
-
end
|
39
|
-
end
|
40
|
-
puts
|
41
|
-
end
|
42
|
-
|
4
|
+
class Addresses
|
5
|
+
include Rudy::Huxtable
|
6
|
+
|
7
|
+
def create
|
8
|
+
address = @@ec2.addresses.create
|
9
|
+
raise ErrorCreatingAddress unless address.is_a?(Rudy::AWS::EC2::Address)
|
10
|
+
address
|
11
|
+
end
|
12
|
+
|
13
|
+
def destroy(address)
|
14
|
+
address = address
|
15
|
+
@@ec2.addresses.destroy(address)
|
16
|
+
end
|
17
|
+
|
18
|
+
def assign(address, instance)
|
19
|
+
raise "Not an instance object" unless instance.is_a?(Rudy::AWS::EC2::Instance)
|
20
|
+
raise "Address not available for this account" unless @@ec2.addresses.valid?(address)
|
21
|
+
@@ec2.addresses.associate(instance.awsid, address)
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# Lists the addresses registered with Amazon
|
26
|
+
def list(n=nil, &each_object)
|
27
|
+
n = [n].flatten.compact
|
28
|
+
addresses = @@ec2.addresses.list(n)
|
29
|
+
addresses.each { |n,kp| each_object.call(kp) } if each_object
|
30
|
+
addresses || []
|
31
|
+
end
|
32
|
+
|
33
|
+
def get(n=nil)
|
34
|
+
raise "Address cannot be nil" if n.nil?
|
35
|
+
@@ec2.addresses.get(n)
|
43
36
|
end
|
37
|
+
|
38
|
+
def associated?(n=nil)
|
39
|
+
raise "Address cannot be nil" if n.nil?
|
40
|
+
@@ec2.addresses.associated?(n)
|
41
|
+
end
|
42
|
+
|
43
|
+
def list_as_hash(n=nil, &each_object)
|
44
|
+
n &&= [n].flatten.compact
|
45
|
+
addresses = @@ec2.addresses.list_as_hash(n)
|
46
|
+
addresses.each_pair { |n,kp| each_object.call(kp) } if each_object
|
47
|
+
addresses || {}
|
48
|
+
end
|
49
|
+
|
50
|
+
def exists?(n=nil)
|
51
|
+
n ||= name(n)
|
52
|
+
@@ec2.addresses.exists?(n)
|
53
|
+
end
|
54
|
+
|
55
|
+
def any?(n=nil)
|
56
|
+
n ||= name(n)
|
57
|
+
@@ec2.addresses.any?
|
58
|
+
end
|
59
|
+
|
44
60
|
end
|
61
|
+
|
45
62
|
end
|
46
63
|
|
64
|
+
|
65
|
+
module Rudy
|
66
|
+
class Addresses
|
67
|
+
class ErrorCreatingAddress < RuntimeError; end
|
68
|
+
end
|
69
|
+
end
|
data/lib/rudy/command/backups.rb
CHANGED
@@ -1,175 +1,65 @@
|
|
1
1
|
|
2
2
|
|
3
|
+
module Rudy
|
4
|
+
class Backups
|
5
|
+
|
6
|
+
end
|
7
|
+
end
|
3
8
|
|
4
9
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
puts
|
41
|
-
puts "These backup metadata will be deleted:"
|
42
|
-
to_be_deleted.each do |snap_id, backup|
|
43
|
-
puts "%s: %s" % [snap_id, backup.name]
|
44
|
-
end
|
45
|
-
|
46
|
-
puts
|
47
|
-
are_you_sure?
|
48
|
-
|
49
|
-
puts
|
50
|
-
puts "Deleting..."
|
51
|
-
to_be_deleted.each do |snap_id, backup|
|
52
|
-
print " -> #{backup.name}... "
|
53
|
-
@sdb.destroy(RUDY_DOMAIN, backup.name)
|
54
|
-
puts "done"
|
55
|
-
end
|
56
|
-
|
57
|
-
puts "Done!"
|
58
|
-
end
|
59
|
-
|
60
|
-
def destroy_backup_valid?
|
61
|
-
raise "No backup specified" if argv.empty?
|
62
|
-
exit unless are_you_sure?(5)
|
63
|
-
true
|
64
|
-
end
|
65
|
-
|
66
|
-
def destroy_backup
|
67
|
-
name = @argv.first
|
68
|
-
puts "Destroying #{name}"
|
69
|
-
begin
|
70
|
-
backup = Rudy::MetaData::Backup.get(@sdb, name)
|
71
|
-
rescue => ex
|
72
|
-
puts "Error deleteing backup: #{ex.message}"
|
73
|
-
end
|
74
|
-
|
75
|
-
return unless backup
|
76
|
-
|
77
|
-
begin
|
78
|
-
puts " -> deleting snapshot..."
|
79
|
-
@ec2.snapshots.destroy(backup.awsid)
|
80
|
-
rescue => ex
|
81
|
-
puts "Error deleting snapshot: #{ex.message}."
|
82
|
-
puts "Continuing..."
|
83
|
-
ensure
|
84
|
-
puts " -> deleting metadata..."
|
85
|
-
@sdb.destroy(RUDY_DOMAIN, name)
|
86
|
-
end
|
87
|
-
puts "Done."
|
88
|
-
end
|
89
|
-
|
90
|
-
def create_backup
|
91
|
-
diskname = @argv.first
|
92
|
-
|
93
|
-
machine = find_current_machine
|
94
|
-
|
95
|
-
disks = Rudy::MetaData::Disk.list(@sdb, machine[:aws_availability_zone], @global.environment, @global.role, @global.position)
|
96
|
-
raise "The machine #{machine_name} does not have any disk metadata" if disks.empty?
|
97
|
-
|
98
|
-
puts "Machine: #{machine_name}"
|
99
|
-
|
100
|
-
if @option.snapshot
|
101
|
-
raise "You must supply a diskname when using an existing snapshot" unless diskname
|
102
|
-
raise "The snapshot #{@option.snapshot} does not exist" unless @ec2.snapshots.exists?(@option.snapshot)
|
103
|
-
disk = Rudy::MetaData::Disk.get(@sdb, diskname)
|
104
|
-
|
105
|
-
raise "The disk #{diskname} does not exist" unless disk
|
106
|
-
backup = Rudy::MetaData::Backup.new
|
107
|
-
backup.awsid = @option.snapshot
|
108
|
-
backup.time_stamp
|
109
|
-
|
110
|
-
# Populate machine infos
|
111
|
-
[:zone, :environment, :role, :position].each do |n|
|
112
|
-
backup.send("#{n}=", @global.send(n)) if @global.send(n)
|
113
|
-
end
|
114
|
-
|
115
|
-
# Populate disk infos
|
116
|
-
[:path, :size].each do |n|
|
117
|
-
backup.send("#{n}=", disk.send(n)) if disk.send(n)
|
118
|
-
end
|
119
|
-
|
120
|
-
|
121
|
-
Rudy::MetaData::Backup.save(@sdb, backup)
|
122
|
-
|
123
|
-
puts backup.name
|
124
|
-
|
125
|
-
else
|
126
|
-
volumes = @ec2.instances.volumes(machine[:aws_instance_id])
|
127
|
-
raise "The machine #{machine_name} does not have any volumes attached." if volumes.empty?
|
128
|
-
|
129
|
-
puts "#{disks.size} Disk(s) defined with #{volumes.size} Volume(s) running"
|
130
|
-
|
131
|
-
volumes.each do |volume|
|
132
|
-
print "Volume #{volume[:aws_id]}... "
|
133
|
-
disk = Rudy::MetaData::Disk.find_from_volume(@sdb, volume[:aws_id])
|
134
|
-
backup = Rudy::MetaData::Backup.new
|
135
|
-
|
136
|
-
# TODO: Look for the disk based on the machine
|
137
|
-
raise "No disk associated to volume #{volume[:aws_id]}" unless disk
|
138
|
-
|
139
|
-
backup.volume = volume[:aws_id]
|
140
|
-
|
141
|
-
# Populate machine infos
|
142
|
-
[:zone, :environment, :role, :position].each do |n|
|
143
|
-
backup.send("#{n}=", @global.send(n)) if @global.send(n)
|
144
|
-
end
|
145
|
-
|
146
|
-
# Populate disk infos
|
147
|
-
[:path, :size].each do |n|
|
148
|
-
backup.send("#{n}=", disk.send(n)) if disk.send(n)
|
149
|
-
end
|
150
|
-
|
151
|
-
backup.time_stamp
|
152
|
-
|
153
|
-
raise "There was a problem creating the backup metadata" unless backup.valid?
|
154
|
-
|
155
|
-
snap = @ec2.snapshots.create(volume[:aws_id])
|
156
|
-
|
157
|
-
if !snap || !snap.is_a?(Hash)
|
158
|
-
puts "There was an unknown problem creating #{backup.name}. Continuing with the next volume..."
|
159
|
-
next
|
160
|
-
end
|
161
|
-
|
162
|
-
backup.awsid = snap[:aws_id]
|
163
|
-
|
164
|
-
Rudy::MetaData::Backup.save(@sdb, backup)
|
165
|
-
|
166
|
-
puts backup.name
|
167
|
-
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
|
173
|
-
end
|
10
|
+
__END__
|
11
|
+
|
12
|
+
|
13
|
+
# From Rudy::MetaData::Backup
|
14
|
+
|
15
|
+
def Backup.for_disk(sdb, disk, max=50)
|
16
|
+
list = Backup.list(sdb, disk.zone, disk.environment, disk.role, disk.position, disk.path) || []
|
17
|
+
list[0..(max-1)]
|
18
|
+
end
|
19
|
+
|
20
|
+
def Backup.get(sdb, name)
|
21
|
+
object = sdb.get_attributes(RUDY_DOMAIN, name)
|
22
|
+
raise "Object #{name} does not exist!" unless object.has_key?(:attributes) && !object[:attributes].empty?
|
23
|
+
self.from_hash(object[:attributes])
|
24
|
+
end
|
25
|
+
|
26
|
+
def Backup.save(sdb, obj, replace = :replace)
|
27
|
+
sdb.store(RUDY_DOMAIN, obj.name, obj.to_hash, replace)
|
28
|
+
end
|
29
|
+
|
30
|
+
def Backup.list(sdb, zon, env=nil, rol=nil, pos=nil, path=nil, date=nil)
|
31
|
+
query = "select * from #{RUDY_DOMAIN} where "
|
32
|
+
query << "rtype = '#{rtype}' "
|
33
|
+
query << " and zone = '#{zon}'" if zon
|
34
|
+
query << " and environment = '#{env}'" if env
|
35
|
+
query << " and role = '#{rol}'" if rol
|
36
|
+
query << " and position = '#{pos}'" if pos
|
37
|
+
query << " and path = '#{path}'" if path
|
38
|
+
query << " and date = '#{date}'" if date
|
39
|
+
query << " and unixtime != '0' order by unixtime desc"
|
40
|
+
list = []
|
41
|
+
sdb.select(query).each do |obj|
|
42
|
+
list << self.from_hash(obj)
|
174
43
|
end
|
175
|
-
|
44
|
+
list
|
45
|
+
end
|
46
|
+
|
47
|
+
def Backup.find_most_recent(zon, env, rol, pos, path)
|
48
|
+
criteria = [zon, env, rol, pos, path]
|
49
|
+
(Rudy::MetaData::Backup.list(@sdb, *criteria) || []).first
|
50
|
+
end
|
51
|
+
|
52
|
+
def Backup.destroy(sdb, name)
|
53
|
+
back = Backup.get(sdb, name) # get raises an exception if the disk doesn't exist
|
54
|
+
sdb.destroy(RUDY_DOMAIN, name)
|
55
|
+
true # wtf: RightAws::SimpleDB doesn't tell us whether it succeeds. We'll assume!
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
def Backup.is_defined?(sdb, backup)
|
61
|
+
query = backup.to_query()
|
62
|
+
puts query
|
63
|
+
!sdb.select(query).empty?
|
64
|
+
end
|
65
|
+
|