rudy 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,77 @@
1
+
2
+
3
+ module Rudy
4
+ module Command
5
+ class Config < Rudy::Command::Base
6
+
7
+ # We force the Command::Base#print_header to be quiet
8
+ def print_header
9
+ @global.quiet = true
10
+ super
11
+ end
12
+
13
+
14
+ # Display configuration from the local user data file (~/.rudy/config).
15
+ # This config contains user data which is sent to each EC2 when
16
+ # it's created.
17
+ #
18
+ # The primary purpose of this command is to give other apps a way
19
+ # to check various configuration values. (This is mostly useful for
20
+ # debugging and checking configuration on an instance itself).
21
+ #
22
+ # It will return the most specific configuration available. If the
23
+ # attribute isn'e found it will check each parent for the same attribute.
24
+ # i.e. if [prod][app][ami] is not available, it will check [prod][ami]
25
+ # and then [ami].
26
+ #
27
+ # # Display the value for a specific machine.
28
+ # $ rudy -e prod -r db config param-name
29
+ #
30
+ # # Display all configuration
31
+ # $ rudy config --all
32
+ #
33
+ def config
34
+ return if @config.nil?
35
+ puts "Config: #{@config.paths}" if @global.verbose > 0
36
+
37
+ which = @option.defaults ? @global.user : machine_name
38
+ puts "Machine: #{which}" if @global.verbose > 0
39
+ puts "User: #{@global.user}" if @global.verbose > 0
40
+
41
+ return if @config.empty?
42
+
43
+ # We need to check whether we're running on a human's computer
44
+ # or within EC2 (we call that running "in-situ"). The userdata
45
+ # available when running in-situ is in a different format.
46
+ if Rudy.in_situ?
47
+
48
+
49
+ else
50
+
51
+ if @option.all
52
+ y @config.machines.to_hash
53
+ y @config.routines.to_hash
54
+ elsif @option.defaults
55
+ y @config.defaults.to_hash
56
+ else
57
+ env, rol, usr, att = @global.environment, @global.role, @global.user, @argv.name
58
+ val = @config.machines.find_deferred(env, rol, usr, att) || ''
59
+ puts (val.is_a?(String)) ? val : val.to_hash.to_yaml
60
+ end
61
+
62
+ #name = @argv.first
63
+ #if name && @config.userdata.has_key?(which)
64
+ # value = @config.userdata[which][name.to_s]
65
+ # puts value if value
66
+ #elsif @option.all
67
+ # puts @config.to_yaml
68
+ #else
69
+ # value = @config.userdata[which]
70
+ # puts value.to_yaml if value
71
+ #end
72
+ end
73
+
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,12 @@
1
+
2
+
3
+
4
+
5
+ module Rudy
6
+ module Command
7
+ class Deploy < Rudy::Command::Base
8
+
9
+ end
10
+ end
11
+ end
12
+
@@ -4,240 +4,210 @@ module Rudy
4
4
  module Command
5
5
  class Disks < Rudy::Command::Base
6
6
 
7
- def print_backups
8
- criteria = [@zone]
9
- criteria += [@environment, @role] unless @all
10
-
11
- Rudy::MetaData::Backup.list(@sdb, *criteria).each do |backup|
12
- puts "%s (%s)" % [backup.name, backup.awsid]
7
+ def disk
8
+ criteria = [@global.zone]
9
+ criteria += [@global.environment, @global.role] unless @option.all
10
+ Rudy::MetaData::Disk.list(@sdb, *criteria).each do |disk|
11
+ backups = Rudy::MetaData::Backup.for_disk(@sdb, disk, 2)
12
+ print_disk(disk, backups)
13
13
  end
14
14
  end
15
+
16
+ def create_disk_valid?
17
+ raise "No filesystem path specified" unless @option.path
18
+ raise "No size specified" unless @option.size
19
+ @instances = @ec2.instances.list(machine_group)
20
+ raise "There are no instances running in #{machine_group}" if !@instances || @instances.empty?
21
+ true
22
+ end
15
23
 
16
- # Check for backups pointing to snapshots that don't exist.
17
- def sync_backups
18
- criteria = [@zone]
19
- criteria += [@environment, @role] unless @all
24
+ def create_disk
25
+ puts "Creating #{@option.path} for #{machine_group}"
26
+ switch_user("root")
27
+ exit unless are_you_sure?(2)
28
+ machine = @instances.values.first # NOTE: DANGER! Should handle position.
20
29
 
21
- puts "Looking for backup metadata with delinquent snapshots..."
22
- to_be_deleted = {} # snap-id => backup
23
- Rudy::MetaData::Backup.list(@sdb, *criteria).each do |backup|
24
- to_be_deleted[backup.awsid] = backup unless @ec2.snapshots.exists?(backup.awsid)
30
+ disk = Rudy::MetaData::Disk.new
31
+ [:region, :zone, :environment, :role, :position].each do |n|
32
+ disk.send("#{n}=", @global.send(n)) if @global.send(n)
25
33
  end
26
-
27
- if to_be_deleted.empty?
28
- puts "All backups are in-sync with snapshots. Nothing to do."
29
- return
34
+ [:path, :device, :size].each do |n|
35
+ disk.send("#{n}=", @option.send(n)) if @option.send(n)
30
36
  end
31
37
 
32
- puts
33
- puts "These backup metadata will be deleted:"
34
- to_be_deleted.each do |snap_id, backup|
35
- puts "%s: %s" % [snap_id, backup.name]
36
- end
38
+ raise "Not enough info was provided to define a disk (#{disk.name})" unless disk.valid?
39
+ raise "The device #{disk.device} is already in use on that machine" if Rudy::MetaData::Disk.is_defined?(@sdb, disk)
40
+ # TODO: Check disk path
41
+ puts "Creating disk metadata for #{disk.name}"
37
42
 
38
- puts
39
- are_you_sure?
40
43
 
41
- puts
42
- puts "Deleting..."
43
- to_be_deleted.each do |snap_id, backup|
44
- print " -> #{backup.name}... "
45
- @sdb.destroy(RUDY_DOMAIN, backup.name)
46
- puts "done"
47
- end
48
44
 
49
- puts "Done!"
45
+ puts "Creating volume... (#{disk.size}GB in #{@global.zone})"
46
+ volume = @ec2.volumes.create(@global.zone, disk.size)
47
+ sleep 3
48
+
49
+ disk.awsid = volume[:aws_id]
50
+ disk.raw_volume = true # This value is not saved.
51
+ Rudy::MetaData::Disk.save(@sdb, disk)
52
+
53
+ execute_attach_disk(disk, machine)
54
+
55
+ print_disk(disk)
50
56
  end
51
57
 
52
58
 
53
- def destroy_backup(name)
54
- puts "Destroying #{name}"
55
- begin
56
- backup = Rudy::MetaData::Backup.get(@sdb, name)
57
- rescue => ex
58
- puts "Error deleteing backup: #{ex.message}"
59
- end
60
-
61
- return unless backup
59
+ def destroy_disk_valid?
60
+ raise "No disk specified" if argv.empty?
62
61
 
63
- begin
64
- puts " -> deleting snapshot..."
65
- @ec2.snapshots.destroy(backup.awsid)
66
- rescue => ex
67
- puts "Error deleting snapshot: #{ex.message}."
68
- puts "Continuing..."
69
- ensure
70
- puts " -> deleting metadata..."
71
- @sdb.destroy(RUDY_DOMAIN, name)
62
+ if @argv.diskname =~ /^disk-/
63
+ @disk = Rudy::MetaData::Disk.get(@sdb, @argv.diskname)
64
+ else
65
+ disk = Rudy::MetaData::Disk.new
66
+ [:zone, :environment, :role, :position].each do |n|
67
+ disk.send("#{n}=", @global.send(n)) if @global.send(n)
68
+ end
69
+ disk.path = @argv.diskname
70
+ @disk = Rudy::MetaData::Disk.get(@sdb, disk.name)
72
71
  end
73
- puts "Done."
72
+
73
+ raise "No such disk: #{@argv.diskname}" unless @disk
74
+ raise "The disk is in another machine environment" unless @global.environment.to_s == @disk.environment.to_s
75
+ raise "The disk is in another machine role" unless @global.role.to_s == @disk.role.to_s
76
+ @instances = @ec2.instances.list(machine_group)
77
+ true
74
78
  end
75
79
 
76
- def create_backup(diskname=nil)
77
- machine = find_current_machine
80
+ def destroy_disk
81
+ puts "Destroying #{@disk.name} and #{@disk.awsid}"
82
+ switch_user("root")
83
+ exit unless are_you_sure?(5)
78
84
 
79
- disks = Rudy::MetaData::Disk.list(@sdb, machine[:aws_availability_zone], @environment, @role, @position)
80
- raise "The machine #{machine_name} does not have any disk metadata" if disks.empty?
85
+ machine = @instances.values.first # NOTE: DANGER! Should handle position.
81
86
 
82
- puts "Machine: #{machine_name}"
87
+ execute_unattach_disk(@disk, machine)
88
+ execute_destroy_disk(@disk, machine)
83
89
 
84
- if @snapshot
85
- raise "You must supply a diskname when using an existing snapshot" unless diskname
86
- raise "The snapshot #{@snapshot} does not exist" unless @ec2.snapshots.exists?(@snapshot)
87
- disk = Rudy::MetaData::Disk.get(@sdb, diskname)
88
-
89
- raise "The disk #{diskname} does not exist" unless disk
90
- backup = Rudy::MetaData::Backup.new
91
- backup.awsid = @snapshot
92
- backup.time_stamp
93
-
94
- # Populate machine infos
95
- [:zone, :environment, :role, :position].each do |n|
96
- val = instance_variable_get("@#{n}")
97
- backup.send("#{n}=", val) if val
98
- end
99
-
100
- # Populate disk infos
101
- [:path, :size].each do |n|
102
- backup.send("#{n}=", disk.send(n)) if disk.send(n)
103
- end
104
-
105
-
106
- Rudy::MetaData::Backup.save(@sdb, backup)
107
-
108
- puts backup.name
109
-
110
- else
111
- volumes = @ec2.instances.volumes(machine[:aws_instance_id])
112
- raise "The machine #{machine_name} does not have any volumes attached." if volumes.empty?
113
-
114
- puts "#{disks.size} Disk(s) defined with #{volumes.size} Volume(s) running"
115
-
116
- volumes.each do |volume|
117
- print "Volume #{volume[:aws_id]}... "
118
- disk = Rudy::MetaData::Disk.from_volume(@sdb, volume[:aws_id])
119
- backup = Rudy::MetaData::Backup.new
120
-
121
- # TODO: Look for the disk based on the machine
122
- raise "No disk associated to volume #{volume[:aws_id]}" unless disk
123
-
124
- backup.volume = volume[:aws_id]
125
-
126
- snap = @ec2.snapshots.create(volume[:aws_id])
127
-
128
- backup.awsid = snap[:aws_id]
129
-
130
- if !snap || !snap.is_a?(Hash)
131
- puts "There was an unknown problem creating #{backup.name}. Continuing with the next volume..."
132
- next
133
- end
134
-
135
- backup.time_stamp
90
+ puts "Done."
91
+ end
136
92
 
137
- # Populate machine infos
138
- [:zone, :environment, :role, :position].each do |n|
139
- val = instance_variable_get("@#{n}")
140
- backup.send("#{n}=", val) if val
141
- end
93
+ def attach_disk_valid?
94
+ destroy_disk_valid?
95
+ raise "There are no instances running in #{machine_group}" if !@instances || @instances.empty?
96
+ true
97
+ end
98
+
99
+ def attach_disk
100
+ puts "Attaching #{name}"
101
+ switch_user("root")
102
+ are_you_sure?(4)
103
+
104
+ machine = @instances.values.first # AK! Assumes single machine
105
+
106
+ execute_attach_disk(@disk, machine)
142
107
 
143
- # Populate disk infos
144
- [:path, :size].each do |n|
145
- backup.send("#{n}=", disk.send(n)) if disk.send(n)
146
- end
108
+ puts
109
+ ssh_command machine[:dns_name], keypairpath, @global.user, "df -h" # Display current mounts
110
+ puts
147
111
 
112
+ puts "Done!"
113
+ end
148
114
 
149
- Rudy::MetaData::Backup.save(@sdb, backup)
150
115
 
151
- puts backup.name
152
-
153
- end
154
116
 
155
- end
156
117
 
157
-
118
+ def unattach_disk_valid?
119
+ destroy_disk_valid?
120
+ true
121
+ end
158
122
 
123
+ def unattach_disk
124
+ puts "Unattaching #{@disk.name} from #{machine_group}"
125
+ switch_user("root")
126
+ are_you_sure?(4)
127
+
128
+ machine = @instances.values.first
129
+
130
+ execute_unattach_disk(@disk, machine)
131
+
132
+ puts "Done!"
133
+ end
134
+
135
+
136
+
137
+ def execute_unattach_disk(disk, machine)
138
+ begin
159
139
 
160
- end
161
-
162
-
163
- def create_disk
164
- disk = Rudy::MetaData::Disk.new
165
- [:environment, :role, :position, :path, :device, :size].each do |n|
166
- val = instance_variable_get("@#{n}")
167
- disk.send("#{n}=", val) if val
140
+ if machine
141
+ puts "Unmounting #{disk.path}...".att(:bright)
142
+ ssh_command machine[:dns_name], keypairpath, global.user, "umount #{disk.path}"
143
+ sleep 1
144
+ end
145
+
146
+ if @ec2.volumes.attached?(disk.awsid)
147
+ puts "Unattaching #{disk.awsid}".att(:bright)
148
+ @ec2.volumes.detach(disk.awsid)
149
+ sleep 5
150
+ end
151
+
152
+ rescue => ex
153
+ puts "Error while unattaching volume #{disk.awsid}: #{ex.message}"
154
+ puts ex.backtrace if Drydock.debug?
168
155
  end
169
-
170
- raise "Not enough info was provided to define a disk (#{disk.name})" unless disk.valid?
171
- raise "The device #{disk.device} is already in use on that machine" if Rudy::MetaData::Disk.is_defined?(@sdb, disk)
172
- puts "Creating disk metadata for #{disk.name}"
173
-
174
- Rudy::MetaData::Disk.save(@sdb, disk)
175
-
176
- print_disks
177
156
  end
178
157
 
179
-
180
- def print_disks
181
- criteria = [@zone]
182
- criteria += [@environment, @role] unless @all
183
-
184
- Rudy::MetaData::Disk.list(@sdb, *criteria).each do |disk|
185
- backups = Rudy::MetaData::Backup.for_disk(@sdb, disk, 2)
186
- print_disk(disk, backups)
158
+ def execute_destroy_disk(disk, machine)
159
+ begin
160
+
161
+ if disk
162
+
163
+ if disk.awsid && @ec2.volumes.available?(disk.awsid)
164
+ puts "Destroying #{disk.path} (#{disk.awsid})".att(:bright)
165
+ @ec2.volumes.destroy(disk.awsid)
166
+ end
167
+
168
+ end
187
169
 
170
+ rescue => ex
171
+ puts "Error while destroying volume #{disk.awsid}: #{ex.message}"
172
+ puts ex.backtrace if Drydock.debug?
173
+ ensure
174
+ puts "Deleteing metadata for #{disk.name}".att(:bright)
175
+ Rudy::MetaData::Disk.destroy(@sdb, disk)
188
176
  end
189
-
190
177
  end
191
178
 
192
- def unattach_disk(name)
193
- puts "Looking for #{name}"
194
- disk = Rudy::MetaData::Disk.get(@sdb, name)
195
- instances = @ec2.instances.list(machine_group)
196
- @user = "root"
197
- check_keys
198
- raise "That is not a valid disk" unless disk
199
- raise "There are no instances running in #{machine_group}" if !instances || instances.empty?
200
- raise "The disk has no attached volume " unless disk.awsid
201
-
202
- machine = instances.values.first
203
-
204
- puts "Unmounting #{disk.path}..."
205
- ssh machine[:dns_name], keypairpath, user, "umount #{disk.path}"
206
- sleep 1
207
-
208
- puts "Detaching #{disk.awsid}"
209
- @ec2.volumes.detach(disk.awsid)
210
-
211
- Rudy::MetaData::Backup.for_disk(@sdb, disk, 2)
212
-
213
- puts "Done!"
214
- end
215
-
216
- def attach_disk(name)
217
- puts "Looking for #{name}"
218
- disk = Rudy::MetaData::Disk.get(@sdb, name)
219
- instances = @ec2.instances.list(machine_group)
220
- raise "There are no instances running in #{machine_group}" if !instances || instances.empty?
221
- instance_id = instances.keys.first # <--- TODO: This is bad!
222
- machine = instances.values.first
223
-
224
- do_dirty_disk_volume_deeds(disk, machine)
225
-
226
-
227
- puts
228
- ssh machine[:dns_name], keypairpath, user, "df -h" # Display current mounts
229
- puts
230
-
231
- puts "Done!"
179
+ def execute_attach_disk(disk, machine)
180
+ begin
181
+ unless @ec2.instances.attached_volume?(machine[:aws_instance_id], disk.device)
182
+ puts "Attaching #{disk.awsid} to #{machine[:aws_instance_id]}".att(:bright)
183
+ @ec2.volumes.attach(machine[:aws_instance_id], disk.awsid, disk.device)
184
+ sleep 3
185
+ end
186
+
187
+ if disk.raw_volume
188
+ puts "Creating the filesystem (mkfs.ext3 -F #{disk.device})".att(:bright)
189
+ ssh_command machine[:dns_name], keypairpath, @global.user, "mkfs.ext3 -F #{disk.device}"
190
+ sleep 1
191
+ end
192
+
193
+ puts "Mounting #{disk.path} to #{disk.device}".att(:bright)
194
+ ssh_command machine[:dns_name], keypairpath, @global.user, "mkdir -p #{disk.path} && mount -t ext3 #{disk.device} #{disk.path}"
195
+
196
+ sleep 1
197
+ rescue => ex
198
+ puts "There was an error attaching #{disk.name}: #{ex.message}"
199
+ puts ex.backtrace if Drydock.debug?
200
+ end
232
201
  end
233
202
 
234
- def destroy_disk(name)
235
- puts "Destroying #{name}"
236
- @sdb.destroy(RUDY_DOMAIN, name)
237
- puts "Done."
238
- end
239
-
240
203
  end
241
204
  end
242
205
  end
243
206
 
207
+
208
+ __END__
209
+
210
+
211
+
212
+
213
+