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.
Files changed (99) hide show
  1. data/CHANGES.txt +8 -9
  2. data/README.rdoc +48 -7
  3. data/Rakefile +102 -7
  4. data/Rudyfile +28 -0
  5. data/bin/ird +162 -0
  6. data/bin/rudy +287 -93
  7. data/lib/annoy.rb +227 -0
  8. data/lib/aws_sdb/service.rb +1 -1
  9. data/lib/console.rb +20 -4
  10. data/lib/escape.rb +305 -0
  11. data/lib/rudy.rb +265 -125
  12. data/lib/rudy/aws.rb +61 -26
  13. data/lib/rudy/aws/ec2.rb +20 -296
  14. data/lib/rudy/aws/ec2/address.rb +121 -0
  15. data/lib/rudy/aws/ec2/group.rb +241 -0
  16. data/lib/rudy/aws/ec2/image.rb +46 -0
  17. data/lib/rudy/aws/ec2/instance.rb +407 -0
  18. data/lib/rudy/aws/ec2/keypair.rb +92 -0
  19. data/lib/rudy/aws/ec2/snapshot.rb +87 -0
  20. data/lib/rudy/aws/ec2/volume.rb +234 -0
  21. data/lib/rudy/aws/simpledb.rb +33 -15
  22. data/lib/rudy/cli.rb +142 -0
  23. data/lib/rudy/cli/addresses.rb +85 -0
  24. data/lib/rudy/cli/backups.rb +175 -0
  25. data/lib/rudy/{command → cli}/config.rb +18 -13
  26. data/lib/rudy/cli/deploy.rb +12 -0
  27. data/lib/rudy/cli/disks.rb +125 -0
  28. data/lib/rudy/cli/domains.rb +17 -0
  29. data/lib/rudy/cli/groups.rb +77 -0
  30. data/lib/rudy/{command → cli}/images.rb +18 -6
  31. data/lib/rudy/cli/instances.rb +142 -0
  32. data/lib/rudy/cli/keypairs.rb +47 -0
  33. data/lib/rudy/cli/manager.rb +51 -0
  34. data/lib/rudy/{command → cli}/release.rb +10 -10
  35. data/lib/rudy/cli/routines.rb +80 -0
  36. data/lib/rudy/cli/volumes.rb +121 -0
  37. data/lib/rudy/command/addresses.rb +62 -39
  38. data/lib/rudy/command/backups.rb +60 -170
  39. data/lib/rudy/command/disks-old.rb +322 -0
  40. data/lib/rudy/command/disks.rb +5 -209
  41. data/lib/rudy/command/domains.rb +34 -0
  42. data/lib/rudy/command/groups.rb +105 -48
  43. data/lib/rudy/command/instances.rb +263 -70
  44. data/lib/rudy/command/keypairs.rb +149 -0
  45. data/lib/rudy/command/manager.rb +65 -0
  46. data/lib/rudy/command/volumes.rb +110 -49
  47. data/lib/rudy/config.rb +90 -70
  48. data/lib/rudy/config/objects.rb +67 -0
  49. data/lib/rudy/huxtable.rb +253 -0
  50. data/lib/rudy/metadata/backup.rb +23 -48
  51. data/lib/rudy/metadata/disk.rb +79 -68
  52. data/lib/rudy/metadata/machine.rb +34 -0
  53. data/lib/rudy/routines.rb +54 -0
  54. data/lib/rudy/routines/disk_handler.rb +190 -0
  55. data/lib/rudy/routines/release.rb +15 -0
  56. data/lib/rudy/routines/script_runner.rb +65 -0
  57. data/lib/rudy/routines/shutdown.rb +42 -0
  58. data/lib/rudy/routines/startup.rb +48 -0
  59. data/lib/rudy/utils.rb +57 -2
  60. data/lib/storable.rb +11 -5
  61. data/lib/sysinfo.rb +274 -0
  62. data/rudy.gemspec +84 -20
  63. data/support/randomize-root-password +45 -0
  64. data/support/rudy-ec2-startup +5 -5
  65. data/support/update-ec2-ami-tools +20 -0
  66. data/test/05_config/00_setup_test.rb +24 -0
  67. data/test/05_config/30_machines_test.rb +69 -0
  68. data/test/20_sdb/00_setup_test.rb +31 -0
  69. data/test/20_sdb/10_domains_test.rb +113 -0
  70. data/test/25_ec2/00_setup_test.rb +34 -0
  71. data/test/25_ec2/10_keypairs_test.rb +33 -0
  72. data/test/25_ec2/20_groups_test.rb +139 -0
  73. data/test/25_ec2/30_addresses_test.rb +35 -0
  74. data/test/25_ec2/40_volumes_test.rb +46 -0
  75. data/test/25_ec2/50_snapshots_test.rb +69 -0
  76. data/test/26_ec2_instances/00_setup_test.rb +33 -0
  77. data/test/26_ec2_instances/10_instances_test.rb +81 -0
  78. data/test/26_ec2_instances/50_images_test.rb +13 -0
  79. data/test/30_sdb_metadata/00_setup_test.rb +28 -0
  80. data/test/30_sdb_metadata/10_disks_test.rb +99 -0
  81. data/test/30_sdb_metadata/20_backups_test.rb +102 -0
  82. data/test/50_commands/00_setup_test.rb +11 -0
  83. data/test/50_commands/10_keypairs_test.rb +79 -0
  84. data/test/50_commands/20_groups_test.rb +77 -0
  85. data/test/50_commands/40_volumes_test.rb +55 -0
  86. data/test/50_commands/50_instances_test.rb +110 -0
  87. data/test/coverage.txt +51 -0
  88. data/test/helper.rb +35 -0
  89. data/tryouts/disks.rb +55 -0
  90. data/tryouts/nested_methods.rb +36 -0
  91. data/tryouts/session_tryout.rb +48 -0
  92. metadata +94 -25
  93. data/bin/rudy-ec2 +0 -108
  94. data/lib/rudy/command/base.rb +0 -839
  95. data/lib/rudy/command/deploy.rb +0 -12
  96. data/lib/rudy/command/environment.rb +0 -74
  97. data/lib/rudy/command/machines.rb +0 -170
  98. data/lib/rudy/command/metadata.rb +0 -41
  99. data/lib/rudy/metadata.rb +0 -26
@@ -0,0 +1,67 @@
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
+ def create(*args, &b)
24
+ hash_handler(:create, *args, &b)
25
+ end
26
+ def destroy(*args, &b)
27
+ hash_handler(:destroy, *args, &b)
28
+ end
29
+ def restore(*args, &b)
30
+ hash_handler(:restore, *args, &b)
31
+ end
32
+ def mount(*args, &b)
33
+ hash_handler(:mount, *args, &b)
34
+ end
35
+
36
+ #
37
+ # Force the specified keyword to always be treated as a hash.
38
+ # Example:
39
+ #
40
+ # startup do
41
+ # disks do
42
+ # create "/path/2" # Available as hash: [action][disks][create][/path/2] == {}
43
+ # create "/path/4" do # Available as hash: [action][disks][create][/path/4] == {size => 14}
44
+ # size 14
45
+ # end
46
+ # end
47
+ # end
48
+ #
49
+ def hash_handler(caesars_meth, *args, &b)
50
+ # TODO: Move to caesars
51
+ return @caesars_properties[caesars_meth] if @caesars_properties.has_key?(caesars_meth) && args.empty? && b.nil?
52
+ return nil if args.empty? && b.nil?
53
+ return method_missing(caesars_meth, *args, &b) if args.empty?
54
+
55
+ caesars_name = args.shift
56
+
57
+ prev = @caesars_pointer
58
+ @caesars_pointer[caesars_meth] ||= Caesars::Hash.new
59
+ hash = Caesars::Hash.new
60
+ @caesars_pointer = hash
61
+ b.call if b
62
+ @caesars_pointer = prev
63
+ @caesars_pointer[caesars_meth][caesars_name] = hash
64
+ @caesars_pointer = prev
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,253 @@
1
+
2
+
3
+
4
+ module Rudy
5
+ module Huxtable
6
+ include Rudy::AWS
7
+
8
+ @@debug = false
9
+
10
+ attr_accessor :config
11
+ attr_accessor :global
12
+ attr_accessor :logger
13
+
14
+ # An instance of Rye::Box for the local machine (running Rudy)
15
+ attr_reader :rbox
16
+
17
+ def initialize(opts={})
18
+ opts = { :config => nil, :logger => STDERR, :global => OpenStruct.new }.merge(opts)
19
+
20
+ # Set instance variables
21
+ opts.each_pair { |n,v| self.send("#{n}=", v) if self.respond_to?("#{n}=") }
22
+
23
+ unless @config
24
+ @config = Rudy::Config.new
25
+ @config.look_and_load(@global.config)
26
+ end
27
+
28
+ init_globals
29
+
30
+ @rbox = Rye::Box.new('localhost')
31
+
32
+ raise Rudy::NoConfig unless has_keys?
33
+ Rudy::AWS.set_access_identifiers(@global.accesskey, @global.secretkey, @logger)
34
+
35
+ end
36
+
37
+
38
+
39
+ def init_globals
40
+ @global.verbose ||= 0
41
+
42
+ @global.cert = File.expand_path(@global.cert || '')
43
+ @global.privatekey = File.expand_path(@global.privatekey || '')
44
+
45
+ # ATROCIOUS!
46
+
47
+ if @config.defaults
48
+ @global.region ||= @config.defaults.region
49
+ @global.zone ||= @config.defaults.zone
50
+ @global.environment ||= @config.defaults.environment
51
+ @global.role ||= @config.defaults.role
52
+ @global.position ||= @config.defaults.position
53
+ @global.user ||= @config.defaults.user
54
+ @global.nocolor = @config.defaults.nocolor
55
+ @global.quiet = @config.defaults.quiet
56
+ end
57
+
58
+ @global.region ||= DEFAULT_REGION
59
+ @global.zone ||= DEFAULT_ZONE
60
+ @global.environment ||= DEFAULT_ENVIRONMENT
61
+ @global.role ||= DEFAULT_ROLE
62
+ @global.position ||= DEFAULT_POSITION
63
+ @global.user ||= DEFAULT_USER
64
+ @global.nocolor = false
65
+ @global.quiet = false
66
+
67
+ @global.position &&= @global.position.to_s.rjust(2, '0')
68
+
69
+ if @config.accounts && @config.accounts.aws
70
+ @global.accesskey ||= @config.accounts.aws.accesskey
71
+ @global.secretkey ||= @config.accounts.aws.secretkey
72
+ @global.account ||= @config.accounts.aws.accountnum
73
+
74
+ @global.cert ||= @config.accounts.aws.cert
75
+ @global.privatekey ||= @config.accounts.aws.privatekey
76
+ end
77
+
78
+ @global.accesskey ||= ENV['AWS_ACCESS_KEY']
79
+ @global.secretkey ||= ENV['AWS_SECRET_KEY'] || ENV['AWS_SECRET_ACCESS_KEY']
80
+ @global.account ||= ENV['AWS_ACCOUNT_NUMBER']
81
+
82
+ @global.cert ||= ENV['EC2_CERT']
83
+ @global.privatekey ||= ENV['EC2_PRIVATE_KEY']
84
+
85
+ @global.local_user = ENV['USER'] || :rudy
86
+ @global.local_hostname = Socket.gethostname || :localhost
87
+
88
+
89
+ String.disable_color if @global.nocolor
90
+ Rudy.enable_quiet if @global.quiet
91
+ end
92
+
93
+ def debug?; @@debug && @@debug == true; end
94
+
95
+ def check_keys
96
+ raise "No EC2 .pem keys provided" unless has_pem_keys?
97
+ raise "No SSH key provided for #{current_user}!" unless has_keypair?
98
+ raise "No SSH key provided for root!" unless has_keypair?(:root)
99
+ end
100
+
101
+ def has_pem_keys?
102
+ (@global.cert && File.exists?(@global.cert) &&
103
+ @global.privatekey && File.exists?(@global.privatekey))
104
+ end
105
+
106
+ def has_keys?
107
+ (@global.accesskey && !@global.accesskey.empty? && @global.secretkey && !@global.secretkey.empty?)
108
+ end
109
+
110
+ def config_dirname
111
+ raise "No config paths defined" unless @config.is_a?(Rudy::Config) && @config.paths.is_a?(Array)
112
+ base_dir = File.dirname @config.paths.first
113
+ raise "Config directory doesn't exist #{base_dir}" unless File.exists?(base_dir)
114
+ base_dir
115
+ end
116
+
117
+ def has_keypair?(name=nil)
118
+ kp = user_keypairpath(name)
119
+ (!kp.nil? && File.exists?(kp))
120
+ end
121
+
122
+ def user_keypairname(user)
123
+ kp = user_keypairpath(user)
124
+ return unless kp
125
+ KeyPairs.path_to_name(kp)
126
+ end
127
+
128
+
129
+
130
+ def user_keypairpath(name)
131
+ raise "No user provided" unless name
132
+ zon, env, rol = @global.zone, @global.environment, @global.role
133
+ #Caesars.enable_debug
134
+ kp = @config.machines.find_deferred(zon, env, rol, [:users, name, :keypair])
135
+ kp ||= @config.machines.find_deferred(env, rol, [:users, name, :keypair])
136
+ kp ||= @config.machines.find_deferred(rol, [:users, name, :keypair])
137
+
138
+ # EC2 Keypairs that were created are intended for starting the machine instances.
139
+ # These are used as the root SSH keys. If we can find a user defined key, we'll
140
+ # check the config path for a generated one.
141
+ if !kp && name.to_s == 'root'
142
+ path = File.join(self.config_dirname, "key-#{current_machine_group}")
143
+ kp = path if File.exists?(path)
144
+ end
145
+
146
+ kp &&= File.expand_path(kp)
147
+ kp
148
+ end
149
+
150
+ def has_root_keypair?
151
+ path = user_keypairpath(:root)
152
+ (!path.nil? && !path.empty?)
153
+ end
154
+
155
+ def current_user
156
+ @global.user
157
+ end
158
+ def current_user_keypairpath
159
+ user_keypairpath(current_user)
160
+ end
161
+ def current_machine_hostname(group=nil)
162
+ group ||= machine_group
163
+ find_machine(group)[:dns_name]
164
+ end
165
+
166
+ def current_machine_group
167
+ [@global.environment, @global.role].join(RUDY_DELIM)
168
+ end
169
+
170
+ def current_machine_image
171
+ zon, env, rol = @global.zone, @global.environment, @global.role
172
+ ami = @config.machines.find_deferred(zon, env, rol, :ami)
173
+ ami ||= @config.machines.find_deferred(env, rol, :ami)
174
+ ami ||= @config.machines.find_deferred(rol, :ami)
175
+ raise Rudy::NoMachineImage, current_machine_group unless ami
176
+ ami
177
+ end
178
+
179
+ def current_machine_address
180
+ @config.machines.find_deferred(@global.environment, @global.role, :address)
181
+ end
182
+
183
+ # TODO: fix machine_group to include zone
184
+ def current_machine_name
185
+ [@global.zone, current_machine_group, @global.position].join(RUDY_DELIM)
186
+ end
187
+
188
+
189
+
190
+ # +name+ the name of the remote user to use for the remainder of the command
191
+ # (or until switched again). If no name is provided, the user will be revert
192
+ # to whatever it was before the previous switch.
193
+ # TODO: deprecate
194
+ def switch_user(name=nil)
195
+ if name == nil && @switch_user_previous
196
+ @global.user = @switch_user_previous
197
+ elsif @global.user != name
198
+ raise "No root keypair defined for #{name}!" unless has_keypair?(name)
199
+ @logger.puts "Remote commands will be run as #{name} user"
200
+ @switch_user_previous = @global.user
201
+ @global.user = name
202
+ end
203
+ end
204
+
205
+ # Returns a hash of info for the requested machine. If the requested machine
206
+ # is not running, it will raise an exception.
207
+ def current_machine
208
+ find_machine(current_machine_group)
209
+ end
210
+
211
+ def find_machine(group)
212
+ machine_list = @ec2.instances.list(group)
213
+ machine = machine_list.values.first # NOTE: Only one machine per group, for now...
214
+ raise "There's no machine running in #{group}" unless machine
215
+ raise "The primary machine in #{group} is not in a running state" unless machine[:aws_state] == 'running'
216
+ machine
217
+ end
218
+
219
+
220
+
221
+ def group_metadata(env=@global.environment, role=@global.role)
222
+ query = "['environment' = '#{env}'] intersection ['role' = '#{role}']"
223
+ @sdb.query_with_attributes(RUDY_DOMAIN, query)
224
+ end
225
+
226
+ # * +opts+
227
+ # :recursive => false, :preserve => false, :chunk_size => 16384
228
+ def scp(task, host, user, keypairpath, paths, dest, opts)
229
+ opts = {
230
+ :recursive => false, :preserve => false, :chunk_size => 16384
231
+ }.merge(opts)
232
+
233
+ Net::SCP.start(host, user, :keys => [keypairpath]) do |scp|
234
+ paths.each do |path|
235
+ prev_path = nil
236
+ scp.send("#{task}!", path, dest, opts) do |ch, name, sent, total|
237
+ msg = ((prev_path == name) ? "\r" : "\n") # new line for new file
238
+ msg << "#{name}: #{sent}/#{total}" # otherwise, update the same line
239
+ @logger.print msg
240
+ @logger.flush # update the screen every cycle
241
+ prev_path = name
242
+ end
243
+ @logger.puts unless prev_path == path
244
+ end
245
+ end
246
+ end
247
+
248
+
249
+
250
+ private
251
+
252
+ end
253
+ end
@@ -4,10 +4,7 @@ require 'date'
4
4
  module Rudy
5
5
  module MetaData
6
6
  class Backup < Storable
7
- include Rudy::MetaData::ObjectBase
8
- extend Rudy::MetaData::ObjectBase
9
-
10
- @@rtype = "back"
7
+ include Rudy::AWS
11
8
 
12
9
  field :rtype
13
10
  field :awsid
@@ -32,15 +29,12 @@ module Rudy
32
29
  @zone = DEFAULT_ZONE
33
30
  @region = DEFAULT_REGION
34
31
  @position = "01"
35
- @rtype = @@rtype
36
- end
37
-
38
- def rtype
39
- @@rtype
32
+ @rtype = Backup.rtype
33
+ time_stamp # initialize time to right now
40
34
  end
41
35
 
42
36
  def self.rtype
43
- @@rtype
37
+ 'back'
44
38
  end
45
39
 
46
40
 
@@ -50,7 +44,8 @@ module Rudy
50
44
  end
51
45
 
52
46
  def valid?
53
- @zone && @environment && @role && @position && @path && @date && @time && @second
47
+ #puts(@zone, @environment, @role, @position, @path, @date, @time, @second)
48
+ (@zone && @environment && @role && @position && @path && @date && @time && @second)
54
49
  end
55
50
 
56
51
  def time_stamp
@@ -104,54 +99,34 @@ module Rudy
104
99
  dirs = pat.split sep if pat
105
100
  dirs.shift while dirs && (dirs[0].nil? || dirs[0].empty?)
106
101
  timestamp = Backup.format_timestamp(dat.utc)
107
- [@@rtype, zon, env, rol, pos, dirs, timestamp].flatten.join(RUDY_DELIM)
102
+ [rtype, zon, env, rol, pos, dirs, timestamp].flatten.join(RUDY_DELIM)
108
103
  end
109
104
 
110
-
111
- def Backup.for_disk(sdb, disk, max=50)
112
- list = Backup.list(sdb, disk.zone, disk.environment, disk.role, disk.position, disk.path) || []
113
- list[0..(max-1)]
114
- end
115
105
 
116
- def Backup.get(sdb, name)
117
- object = sdb.get_attributes(RUDY_DOMAIN, name)
118
- raise "Object #{name} does not exist!" unless object.has_key?(:attributes) && !object[:attributes].empty?
119
- self.from_hash(object[:attributes])
120
- end
121
106
 
122
- def Backup.save(sdb, obj, replace = :replace)
123
- sdb.store(RUDY_DOMAIN, obj.name, obj.to_hash, replace)
107
+
108
+ def to_select
109
+
124
110
  end
125
111
 
126
- def Backup.list(sdb, zon, env=nil, rol=nil, pos=nil, path=nil, date=nil)
127
- query = "select * from #{RUDY_DOMAIN} where "
128
- query << "rtype = '#{rtype}' "
129
- query << " and zone = '#{zon}'" if zon
130
- query << " and environment = '#{env}'" if env
131
- query << " and role = '#{rol}'" if rol
132
- query << " and position = '#{pos}'" if pos
133
- query << " and path = '#{path}'" if path
134
- query << " and date = '#{date}'" if date
135
- query << " and unixtime != '0' order by unixtime desc"
136
- list = []
137
- sdb.select(query).each do |obj|
138
- list << self.from_hash(obj)
139
- end
140
- list
112
+ def save
113
+ @@sdb.store(RUDY_DOMAIN, name, self.to_hash, :replace) # Always returns nil
114
+ true
141
115
  end
142
116
 
143
- def Backup.destroy(sdb, name)
144
- back = Backup.get(sdb, name) # get raises an exception if the disk doesn't exist
145
- sdb.destroy(RUDY_DOMAIN, name)
146
- true # wtf: RightAws::SimpleDB doesn't tell us whether it succeeds. We'll assume!
117
+ def destroy
118
+ @@sdb.destroy(RUDY_DOMAIN, name)
119
+ true
147
120
  end
148
121
 
149
-
122
+ def refresh
123
+ h = @@sdb.get(RUDY_DOMAIN, name) || {}
124
+ from_hash(h)
125
+ end
150
126
 
151
- def Backup.is_defined?(sdb, backup)
152
- query = backup.to_query()
153
- puts query
154
- !sdb.select(query).empty?
127
+ def Backup.get(dname)
128
+ h = @@sdb.get(RUDY_DOMAIN, dname) || {}
129
+ from_hash(h)
155
130
  end
156
131
 
157
132
  end
@@ -1,14 +1,12 @@
1
1
 
2
2
 
3
3
  module Rudy
4
-
5
4
  module MetaData
6
5
  class Disk < Storable
7
-
8
- @@rtype = 'disk'
6
+ include Rudy::Huxtable
9
7
 
10
8
  # This is a flag used internally to specify that a volume has been
11
- # created for this disk, but not formated.
9
+ # created for this disk, but not yet formated.
12
10
  attr_accessor :raw_volume
13
11
 
14
12
  field :rtype
@@ -27,21 +25,25 @@ module Rudy
27
25
 
28
26
  def initialize
29
27
  @backups = []
30
- @rtype = @@rtype.to_s
31
28
  @raw_volume = false
29
+ @rtype = Disk.rtype
32
30
  end
33
31
 
34
- def rtype
35
- @@rtype.to_s
36
- end
37
-
38
- def rtype=(val)
32
+ def self.rtype
33
+ 'disk'
39
34
  end
40
35
 
41
36
  def name
42
37
  Disk.generate_name(@zone, @environment, @role, @position, @path)
43
38
  end
44
39
 
40
+ def Disk.generate_name(zon, env, rol, pos, pat, sep=File::SEPARATOR)
41
+ pos = pos.to_s.rjust 2, '0'
42
+ dirs = pat.split sep if pat
43
+ dirs.shift while dirs && (dirs[0].nil? || dirs[0].empty?)
44
+ ["disk", zon, env, rol, pos, *dirs].join(RUDY_DELIM)
45
+ end
46
+
45
47
  def valid?
46
48
  @zone && @environment && @role && @position && @path && @size && @device
47
49
  end
@@ -51,86 +53,95 @@ module Rudy
51
53
  criteria -= [*remove].flatten
52
54
  query = []
53
55
  criteria.each do |n|
54
- query << "['#{n}' = '#{self.send(n.to_sym)}'] "
56
+ val = self.send(n.to_sym)
57
+ query << "['#{n}' = '#{self.send(n.to_sym)}'] " if val # Only add attributes with values
55
58
  end
56
59
  query.join(" intersection ")
57
60
  end
58
61
 
59
- def to_s
60
- str = ""
61
- field_names.each do |key|
62
- str << sprintf(" %22s: %s#{$/}", key, self.send(key.to_sym))
63
- end
64
- str
65
- end
66
-
67
- def Disk.generate_name(zon, env, rol, pos, pat, sep=File::SEPARATOR)
68
- pos = pos.to_s.rjust 2, '0'
69
- dirs = pat.split sep if pat
70
- dirs.shift while dirs && (dirs[0].nil? || dirs[0].empty?)
71
- ["disk", zon, env, rol, pos, *dirs].join(RUDY_DELIM)
62
+ def to_select
63
+
72
64
  end
73
65
 
74
- def Disk.get(sdb, name)
75
- disk = sdb.get_attributes(RUDY_DOMAIN, name)
76
- return nil unless disk && disk.has_key?(:attributes) && !disk[:attributes].empty?
77
- # raise "Disk #{name} does not exist!" unless
78
- Rudy::MetaData::Disk.from_hash(disk[:attributes])
66
+ def save
67
+ @@sdb.store(RUDY_DOMAIN, name, self.to_hash, :replace) # Always returns nil
68
+ true
79
69
  end
80
70
 
81
- def Disk.destroy(sdb, disk)
82
- disk = Disk.get(sdb, disk) if disk.is_a?(String) # get raises an exception if the disk doesn't exist
83
- sdb.destroy(RUDY_DOMAIN, disk.name)
84
- true # wtf: RightAws::SimpleDB doesn't tell us whether it succeeds. We'll assume!
71
+ def destroy
72
+ @@sdb.destroy(RUDY_DOMAIN, name)
73
+ true
85
74
  end
86
75
 
87
- def Disk.save(sdb, disk)
88
- sdb.store(RUDY_DOMAIN, disk.name, disk.to_hash, :replace)
76
+ def refresh
77
+ h = @@sdb.get(RUDY_DOMAIN, name) || {}
78
+ from_hash(h)
89
79
  end
90
80
 
91
- def Disk.is_defined?(sdb, disk)
92
- # We don't care about the path, but we do care about the device
93
- # which is not part of the disk's name.
94
- query = disk.to_query(:device, :path)
95
- !sdb.query_with_attributes(RUDY_DOMAIN, query).empty?
81
+ def Disk.get(dname)
82
+ h = @@sdb.get(RUDY_DOMAIN, dname) || {}
83
+ from_hash(h)
96
84
  end
97
85
 
98
- def Disk.find_from_volume(sdb, vol_id)
99
- query = "['awsid' = '#{vol_id}']"
100
- res = sdb.query_with_attributes(RUDY_DOMAIN, query)
101
- if res.empty?
102
- nil
103
- else
104
- disk = Rudy::MetaData::Disk.from_hash(res.values.first)
105
- end
86
+ def is_mounted?
87
+
106
88
  end
107
89
 
108
90
 
109
- def Disk.find_from_path(sdb, path)
110
- query = "['path' = '#{path}']"
111
- res = sdb.query_with_attributes(RUDY_DOMAIN, query)
112
- if res.empty?
113
- nil
114
- else
115
- disk = Rudy::MetaData::Disk.from_hash(res.values.first)
91
+ def format(instance)
92
+ raise "No instance supplied" unless instance
93
+ raise "Disk not valid" unless self.valid?
94
+
95
+ begin
96
+ puts "Creating the filesystem (mkfs.ext3 -F #{disk.device})".bright
97
+ ssh_command instance.dns_name_public, current_user_keypairpath, @global.user, "mkfs.ext3 -F #{disk.device}"
98
+ sleep 1
99
+ rescue => ex
100
+ @logger.puts ex.backtrace if debug?
101
+ raise "Error formatting #{disk.path}: #{ex.message}"
102
+ end
103
+ true
104
+ end
105
+ def mount(instance)
106
+ raise "No instance supplied" unless instance
107
+ disk = find_disk(opts[:disk] || opts[:path])
108
+ raise "Disk #{opts[:disk] || opts[:path]} cannot be found" unless disk
109
+ switch_user(:root)
110
+ begin
111
+ puts "Mounting #{disk.device} to #{disk.path}".bright
112
+ ssh_command instance.dns_name_public, current_user_keypairpath, @global.user, "mkdir -p #{disk.path} && mount -t ext3 #{disk.device} #{disk.path}"
113
+ rescue => ex
114
+ @logger.puts ex.backtrace if debug?
115
+ raise "Error mounting #{disk.path}: #{ex.message}"
116
116
  end
117
+ true
118
+ end
119
+
120
+ def unmount(instance)
121
+ raise "No instance supplied" unless instance
122
+ disk = find_disk(opts[:disk] || opts[:path])
123
+ raise "Disk #{opts[:disk] || opts[:path]} cannot be found" unless disk
124
+ switch_user(:root)
125
+ begin
126
+ puts "Unmounting #{disk.path}...".bright
127
+ ssh_command instance.dns_name_public, current_user_keypairpath, global.user, "umount #{disk.path}"
128
+ sleep 1
129
+ rescue => ex
130
+ @logger.puts ex.backtrace if debug?
131
+ raise "Error unmounting #{disk.path}: #{ex.message}"
132
+ end
133
+ true
117
134
  end
118
135
 
119
- def Disk.list(sdb, zon, env=nil, rol=nil, pos=nil)
120
- query = ''
121
- query << "['rtype' = '#{@@rtype}']" if zon
122
- query << " intersection ['zone' = '#{zon}']" if zon
123
- query << " intersection ['environment' = '#{env}']" if env
124
- query << " intersection ['role' = '#{rol}']" if rol
125
- query << " intersection ['position' = '#{pos}']" if pos
126
-
127
- list = []
128
- sdb.query_with_attributes(RUDY_DOMAIN, query).each_pair do |name, hash|
129
- #puts "DISK: #{hash.to_yaml}"
130
- list << Rudy::MetaData::Disk.from_hash(hash)
136
+ def to_s
137
+ str = ""
138
+ field_names.each do |key|
139
+ str << sprintf(" %22s: %s#{$/}", key, self.send(key.to_sym))
131
140
  end
132
- list
141
+ str
133
142
  end
143
+
144
+
134
145
  end
135
146
 
136
147
  end