rudy 0.3.2 → 0.4.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.
@@ -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
+