rudy 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/CHANGES.txt +32 -17
  2. data/README.rdoc +74 -40
  3. data/bin/rudy +66 -10
  4. data/bin/rudy-ec2 +3 -1
  5. data/examples/authorize.rb +15 -0
  6. data/examples/gem-test.rb +11 -5
  7. data/examples/solaris.rb +35 -0
  8. data/examples/windows.rb +101 -0
  9. data/lib/rudy.rb +7 -1
  10. data/lib/rudy/aws.rb +2 -2
  11. data/lib/rudy/aws/ec2.rb +29 -22
  12. data/lib/rudy/aws/ec2/group.rb +1 -1
  13. data/lib/rudy/aws/ec2/image.rb +1 -29
  14. data/lib/rudy/aws/ec2/instance.rb +4 -32
  15. data/lib/rudy/aws/ec2/keypair.rb +1 -6
  16. data/lib/rudy/aws/ec2/snapshot.rb +2 -20
  17. data/lib/rudy/aws/ec2/volume.rb +11 -19
  18. data/lib/rudy/aws/ec2/zone.rb +1 -6
  19. data/lib/rudy/aws/sdb.rb +1 -1
  20. data/lib/rudy/cli/aws/ec2/addresses.rb +4 -10
  21. data/lib/rudy/cli/aws/ec2/groups.rb +0 -1
  22. data/lib/rudy/cli/aws/ec2/images.rb +1 -4
  23. data/lib/rudy/cli/aws/ec2/info.rb +63 -0
  24. data/lib/rudy/cli/aws/ec2/instances.rb +3 -5
  25. data/lib/rudy/cli/aws/ec2/keypairs.rb +3 -5
  26. data/lib/rudy/cli/aws/ec2/snapshots.rb +2 -6
  27. data/lib/rudy/cli/aws/ec2/zones.rb +2 -4
  28. data/lib/rudy/cli/backups.rb +20 -9
  29. data/lib/rudy/cli/base.rb +60 -3
  30. data/lib/rudy/cli/candy.rb +1 -1
  31. data/lib/rudy/cli/disks.rb +65 -7
  32. data/lib/rudy/cli/execbase.rb +0 -2
  33. data/lib/rudy/cli/images.rb +97 -0
  34. data/lib/rudy/cli/info.rb +48 -0
  35. data/lib/rudy/cli/keypairs.rb +43 -0
  36. data/lib/rudy/cli/machines.rb +41 -36
  37. data/lib/rudy/cli/networks.rb +68 -0
  38. data/lib/rudy/cli/routines.rb +3 -10
  39. data/lib/rudy/config/objects.rb +0 -1
  40. data/lib/rudy/disks.rb +4 -0
  41. data/lib/rudy/global.rb +1 -1
  42. data/lib/rudy/huxtable.rb +9 -3
  43. data/lib/rudy/machines.rb +1 -1
  44. data/lib/rudy/metadata.rb +4 -1
  45. data/lib/rudy/metadata/backup.rb +2 -2
  46. data/lib/rudy/metadata/disk.rb +7 -4
  47. data/lib/rudy/metadata/machine.rb +66 -2
  48. data/lib/rudy/routines.rb +2 -1
  49. data/lib/rudy/routines/base.rb +4 -157
  50. data/lib/rudy/routines/handlers/base.rb +6 -3
  51. data/lib/rudy/routines/handlers/disks.rb +127 -42
  52. data/lib/rudy/routines/handlers/group.rb +45 -10
  53. data/lib/rudy/routines/handlers/host.rb +16 -10
  54. data/lib/rudy/routines/handlers/keypair.rb +26 -10
  55. data/lib/rudy/routines/handlers/rye.rb +171 -0
  56. data/lib/rudy/routines/handlers/script.rb +2 -1
  57. data/lib/rudy/routines/passthrough.rb +2 -2
  58. data/lib/rudy/routines/reboot.rb +2 -2
  59. data/lib/rudy/routines/shutdown.rb +2 -2
  60. data/lib/rudy/routines/startup.rb +4 -2
  61. data/rudy.gemspec +17 -10
  62. data/tryouts/10_require_time/10_rudy_tryouts.rb +1 -1
  63. data/tryouts/12_config/20_defaults_tryouts.rb +1 -1
  64. data/tryouts/12_config/40_machines_tryouts.rb +1 -1
  65. data/tryouts/15_huxtable/20_user_tryouts.rb +1 -1
  66. data/tryouts/25_ec2/10_keypairs_tryouts.rb +1 -0
  67. data/tryouts/30_metadata/10_include_tryouts.rb +1 -1
  68. data/tryouts/30_metadata/13_object_tryouts.rb +4 -0
  69. data/tryouts/30_metadata/50_disk_tryouts.rb +4 -2
  70. data/tryouts/30_metadata/51_disk_digest_tryouts.rb +1 -1
  71. data/tryouts/30_metadata/53_disk_list_tryouts.rb +2 -1
  72. data/tryouts/30_metadata/56_disk_volume_tryouts.rb +1 -1
  73. data/tryouts/30_metadata/60_backup_tryouts.rb +4 -2
  74. data/tryouts/30_metadata/63_backup_list_tryouts.rb +1 -1
  75. data/tryouts/30_metadata/64_backup_disk_tryouts.rb +3 -1
  76. data/tryouts/30_metadata/66_backup_snapshot_tryouts.rb +1 -1
  77. data/tryouts/30_metadata/70_machine_tryouts.rb +5 -2
  78. data/tryouts/30_metadata/73_machine_list_tryouts.rb +1 -1
  79. data/tryouts/30_metadata/76_machine_instance_tryouts.rb +15 -3
  80. data/tryouts/30_metadata/77_machines_tryouts.rb +1 -1
  81. data/tryouts/40_routines/10_keypair_handler_tryouts.rb +6 -5
  82. data/tryouts/40_routines/11_group_handler_tryouts.rb +1 -1
  83. metadata +14 -7
  84. data/lib/rudy/cli/status.rb +0 -60
@@ -0,0 +1,35 @@
1
+ # Rudy Solaris Machines
2
+ #
3
+ # This configuration is used to
4
+ # test solaris instance support.
5
+
6
+
7
+ defaults do
8
+ color true
9
+ environment :test
10
+ role :solaris
11
+ end
12
+
13
+ machines do
14
+ region :'us-east-1' do
15
+ ami 'ami-8f30d1e6' # OpenSolaris 2009.06 32-bit (US)
16
+ end
17
+ region :'eu-west-1' do
18
+ ami 'ami-2381a957' # OpenSolaris 2009.06 32-bit (EU)
19
+ end
20
+ env :test do
21
+ role :solaris do
22
+ user :root
23
+ end
24
+ end
25
+ end
26
+
27
+ routines do
28
+
29
+ uname do
30
+ remote :root do
31
+ uname :a
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,101 @@
1
+ # Rudy Windows Machines
2
+ #
3
+ # This configuration is used to
4
+ # test windows instance support.
5
+
6
+
7
+ defaults do
8
+ color true
9
+ environment :test
10
+ role :windows
11
+ zone :'eu-west-1b'
12
+ bucket 'rudy-ami-eu'
13
+ end
14
+
15
+ machines do
16
+ region :'us-east-1' do
17
+ ami 'ami-de4daab7' # Amazon Windows Server 2003 (US)
18
+ size 'm1.small'
19
+ end
20
+ region :'eu-west-1' do
21
+ ami 'ami-8696bef2' # Rudy Windows 2009-08-24 (EU)
22
+ end
23
+ env :test do
24
+ role :windows do
25
+ os :windows
26
+ user :Administrator
27
+ disks do
28
+ path "F:" do
29
+ size 1
30
+ device 'xvdf'
31
+ fstype 'ntfs'
32
+ end
33
+ path "E:" do
34
+ size 2
35
+ device 'xvde'
36
+ end
37
+ path 'L:' do
38
+ size 3
39
+ device 'xvdl'
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+
47
+ commands do
48
+ allow :rm
49
+ end
50
+
51
+ routines do
52
+
53
+ create_disks do
54
+ disks do
55
+ create "L:"
56
+ #create "F:"
57
+ #create "E:"
58
+ end
59
+
60
+ end
61
+
62
+ shutdown do
63
+ disks do
64
+ destroy "L:"
65
+ #destroy "F:"
66
+ #destroy "E:"
67
+ end
68
+
69
+ end
70
+
71
+
72
+ upload_config do
73
+ remote :root do
74
+ puts "Uploading rudy config"
75
+ home = guess_user_home
76
+ mkdir :p, "#{home}/.rudy", "#{home}/.ssh", ".ssh"
77
+ disable_safe_mode
78
+ file_upload '~/.rudy/config', "#{home}/.rudy/config"
79
+ puts "Uploading keypair"
80
+ file_upload '~/.ssh/id_rsa', '~/.ssh/key-eu-west-1b-test-windows', "#{home}/.ssh/"
81
+ file_upload '~/.ssh/id_rsa', '~/.ssh/key-eu-west-1b-test-windows', ".ssh/"
82
+ end
83
+ end
84
+
85
+ end
86
+
87
+
88
+ __END__
89
+
90
+ * diskpart script example
91
+ * http://social.technet.microsoft.com/Forums/en-US/winserversetup/thread/2cfbaae1-6e33-4197-bb71-63434a34eb3c
92
+ * http://technet.microsoft.com/en-us/library/cc766465(WS.10).aspx
93
+
94
+ * format docs
95
+ * http://www.computerhope.com/formathl.htm
96
+
97
+ * Securing Remote Desktop with copSSH
98
+ * http://www.teamhackaday.com/2008/04/23/securing-windows-remote-desktop-with-copssh/
99
+
100
+ * Windows SSH
101
+ * http://www.windowsnetworking.com/articles_tutorials/install-SSH-Server-Windows-Server-2008.html
@@ -42,7 +42,7 @@ module Rudy
42
42
  unless defined?(MAJOR)
43
43
  MAJOR = 0.freeze
44
44
  MINOR = 9.freeze
45
- TINY = 1.freeze
45
+ TINY = 2.freeze
46
46
  end
47
47
  def self.to_s; [MAJOR, MINOR, TINY].join('.'); end
48
48
  def self.to_f; self.to_s.to_f; end
@@ -72,6 +72,12 @@ module Rudy
72
72
  DEFAULT_EC2_HOST = "ec2.amazonaws.com"
73
73
  DEFAULT_EC2_PORT = 443
74
74
 
75
+ DEFAULT_WINDOWS_FS = 'ntfs'
76
+ DEFAULT_LINUX_FS = 'ext3'
77
+
78
+ DEFAULT_WINDOWS_DEVICE = 'xvdf'
79
+ DEFAULT_LINUX_DEVICE = '/dev/sdh'
80
+
75
81
  MAX_INSTANCES = 5.freeze
76
82
 
77
83
  ID_MAP = {
@@ -1,6 +1,6 @@
1
1
 
2
2
 
3
- require 'EC2' # amazon-ec2 gem
3
+ require 'AWS' # amazon-ec2 gem
4
4
 
5
5
 
6
6
  module Rudy
@@ -27,7 +27,7 @@ module Rudy
27
27
 
28
28
  Rudy::Utils.require_glob(RUDY_LIB, 'rudy', 'aws', '{ec2,s3,sdb}', "*.rb")
29
29
 
30
- class Error < ::EC2::Error; end
30
+ class Error < ::AWS::Error; end
31
31
  end
32
32
 
33
33
  end
@@ -3,6 +3,8 @@ module Rudy; module AWS
3
3
  module EC2
4
4
  # include Rudy::Huxtable
5
5
 
6
+ @@mutex = Mutex.new
7
+
6
8
  def self.connect(access_key=nil, secret_key=nil, region=nil, logger=nil)
7
9
 
8
10
  if region
@@ -15,7 +17,7 @@ module Rudy; module AWS
15
17
  host ||= DEFAULT_EC2_HOST
16
18
  port ||= DEFAULT_EC2_PORT
17
19
 
18
- @@ec2 = ::EC2::Base.new(:port => port, :server=> host, :access_key_id => access_key, :secret_access_key => secret_key)
20
+ @@ec2 = ::AWS::EC2::Base.new(:port => port, :server=> host, :access_key_id => access_key, :secret_access_key => secret_key)
19
21
  @@logger = logger
20
22
  end
21
23
 
@@ -28,31 +30,36 @@ module Rudy; module AWS
28
30
  # Returns the return value from the request is returned untouched
29
31
  # or the default value on error or if the request returned nil.
30
32
  def self.execute_request(default=nil, timeout=nil, &request)
31
- timeout ||= 15
33
+ timeout ||= 30
32
34
  raise "No block provided" unless request
33
35
  response = nil
34
- begin
35
- Timeout::timeout(timeout) do
36
- response = request.call
37
- end
38
- # Raise the EC2 exceptions
39
- rescue ::EC2::Error, ::EC2::InvalidInstanceIDMalformed => ex
40
- raise Rudy::AWS::Error, ex.message
36
+ @@mutex.synchronize {
37
+ begin
38
+
39
+ Timeout::timeout(timeout) do
40
+ response = request.call
41
+ end
41
42
 
42
- # NOTE: The InternalError is returned for non-existent volume IDs.
43
- # It's probably a bug so we're ignoring it -- Dave.
44
- rescue ::EC2::InternalError => ex
45
- raise Rudy::AWS::Error, ex.message
43
+ # Raise the EC2 exceptions
44
+ rescue ::AWS::Error, ::AWS::InvalidInstanceIDMalformed => ex
45
+ raise Rudy::AWS::Error, ex.message
46
+
47
+ # NOTE: The InternalError is returned for non-existent volume IDs.
48
+ # It's probably a bug so we're ignoring it -- Dave.
49
+ rescue ::AWS::InternalError => ex
50
+ raise Rudy::AWS::Error, ex.message
46
51
 
47
- rescue Timeout::Error => ex
48
- STDERR.puts "Timeout (#{timeout}): #{ex.message}!"
49
- rescue SocketError => ex
50
- #STDERR.puts ex.message
51
- #STDERR.puts ex.backtrace
52
- raise SocketError, "Check your Internets!" unless @@global.offline
53
- ensure
54
- response ||= default
55
- end
52
+ rescue Timeout::Error => ex
53
+ STDERR.puts "Timeout (#{timeout}): #{ex.message}!"
54
+ rescue SocketError => ex
55
+ #STDERR.puts ex.message
56
+ #STDERR.puts ex.backtrace
57
+ raise SocketError, "Check your Internets!" unless @@global.offline
58
+ ensure
59
+ response ||= default
60
+ end
61
+ sleep 0.1 # defeat race conditions
62
+ }
56
63
  response
57
64
  end
58
65
 
@@ -171,7 +171,7 @@ module Rudy::AWS
171
171
  def exists?(name)
172
172
  begin
173
173
  g = list([name.to_s])
174
- rescue ::EC2::InvalidGroupNotFound
174
+ rescue ::AWS::InvalidGroupNotFound
175
175
  return false
176
176
  end
177
177
 
@@ -13,37 +13,9 @@ module Rudy::AWS
13
13
  field :visibility
14
14
  field :location
15
15
  field :kind
16
-
17
- def liner_note
18
- info = @location
19
- # Highlight "debian-5" in /dir/debian-5.manifest.xml
20
- #info = info.split(/\//)
21
- #info[-1].gsub!(/(.+?)((\.img)?\.manifest\.xml)/) { |m,n| ($1 || "").bright << $2 }
22
- #info = info.join('/')
23
- "%s %-6s (%s)" % [self.awsid.bright, self.arch, info]
24
- end
25
16
 
26
17
  def to_s(with_title=false)
27
- lines = []
28
- lines << liner_note
29
- #if self.available?
30
- # p = public? ? "public" : "private"
31
- # k, r = @aki || 'aki-unknown', @ari || 'ari-unknown'
32
- # lines << @@sformat % %w{arch owner aki ari visibility} if with_title
33
- # lines << @@sformat % [@arch, @owner, k, r, p]
34
- #end
35
- lines.join($/)
36
- end
37
-
38
- def inspect
39
- lines = []
40
- lines << liner_note
41
- field_names.each do |key|
42
- next unless self.respond_to?(key)
43
- val = self.send(key)
44
- lines << sprintf(" %22s: %s", key, (val.is_a?(Array) ? val.join(', ') : val))
45
- end
46
- lines.join($/)
18
+ [@awsid.bright, @arch, @visibility, @location].join '; '
47
19
  end
48
20
 
49
21
  def available?; @state && @state == "available"; end
@@ -23,38 +23,9 @@ module Rudy::AWS
23
23
  @groups ||= []
24
24
  end
25
25
 
26
- def liner_note
27
- info = self.running? ? self.dns_public : self.state
28
- "%s %-30s" % [self.awsid.bright, info]
29
- end
30
-
31
- def to_s(with_title=false)
32
- lines = []
33
- if @groups
34
- gpstr = [@groups].flatten.compact.join(', ')
35
- gpstr &&= "(#{gpstr})"
36
- else
37
- gpstr = ''
38
- end
39
-
40
- lines << "%s %s" % [liner_note, gpstr]
41
- #if self.running?
42
- # k, g = @keyname || 'no-keypair', self.groups.join(', ')
43
- # lines << @@sformat % %w{zone size ami keyname groups} if with_title
44
- # lines << @@sformat % [@zone, @size, @ami, k, g]
45
- #end
46
- lines.join($/)
47
- end
48
-
49
- def pretty
50
- lines = []
51
- lines << liner_note
52
- field_names.each do |key|
53
- next unless self.respond_to?(key)
54
- val = self.send(key)
55
- lines << sprintf(" %22s: %s", key, (val.is_a?(Array) ? val.join(', ') : val))
56
- end
57
- lines.join($/)
26
+ def to_s(*args)
27
+ groups = [@groups].flatten.compact.join(', ')
28
+ [self.awsid.bright, self.state, self.dns_public, groups].join '; '
58
29
  end
59
30
 
60
31
  def running?; self.state && self.state == 'running'; end
@@ -307,6 +278,7 @@ module Rudy::AWS
307
278
  # +inst_id+ is an instance ID
308
279
  # Returns an Instance object
309
280
  def get(inst_id)
281
+ return nil if inst_id.nil?
310
282
  inst_id = inst_id.awsid if inst_id.is_a?(Rudy::AWS::EC2::Instance)
311
283
  inst = list(:any, inst_id)
312
284
  inst &&= inst.first
@@ -8,13 +8,8 @@ module Rudy::AWS
8
8
  field :fingerprint
9
9
  field :private_key
10
10
 
11
- def liner_note
12
- "%-20s %s" % [self.name.bright, self.fingerprint]
13
- end
14
-
15
11
  def to_s(titles=false)
16
- str = titles ? "%-20s %s#{$/}" % ['name', 'fingerprint'] : ""
17
- str << liner_note
12
+ [@name.bright, @fingerprint].join '; '
18
13
  end
19
14
 
20
15
  def public_key
@@ -3,7 +3,6 @@
3
3
  module Rudy::AWS
4
4
  module EC2
5
5
  class Snapshot < Storable
6
- @@sformat = "%s <- %10s; %s"
7
6
 
8
7
  field :awsid
9
8
  field :progress
@@ -11,25 +10,8 @@ module Rudy::AWS
11
10
  field :volid
12
11
  field :status
13
12
 
14
- def liner_note
15
- t = Time.parse(@created)
16
- info = t.strftime("%Y-%m-%d %H:%M:%S")
17
- "%s (%s)" % [(self.awsid || '').bright, info]
18
- end
19
-
20
13
  def to_s(with_title=false)
21
- @@sformat % [liner_note, @volid, @status]
22
- end
23
-
24
- def pretty
25
- lines = []
26
- lines << liner_note
27
- field_names.each do |key|
28
- next unless self.respond_to?(key)
29
- val = self.send(key)
30
- lines << sprintf(" %22s: %s", key, (val.is_a?(Array) ? val.join(', ') : val))
31
- end
32
- lines.join($/)
14
+ [@awsid.bright, @volid, @created, @status, @progress].join '; '
33
15
  end
34
16
 
35
17
  def completed?
@@ -98,7 +80,7 @@ module Rudy::AWS
98
80
  end
99
81
 
100
82
  def get(snap_id)
101
- list(snap_id).first || nil
83
+ list(snap_id).first rescue nil
102
84
  end
103
85
 
104
86
  def exists?(snap_id)
@@ -20,23 +20,8 @@ module Rudy::AWS
20
20
  @size &&= @size.to_i
21
21
  end
22
22
 
23
- def liner_note
24
- info = attached? ? "attached to #{@instid}" : @status
25
- "%s (%s)" % [(self.awsid || '').bright, info]
26
- end
27
-
28
- def to_s(with_title=false)
29
- line = @@sformat % [liner_note, @zone, @size, @device]
30
- line << " <- %s" % [@snapid] if @snapid
31
- line
32
- end
33
-
34
- def pretty
35
- lines = [liner_note]
36
- field_names.each do |n|
37
- lines << sprintf(" %12s: %s", n, self.send(n)) if self.send(n)
38
- end
39
- lines.join($/)
23
+ def to_s(*args)
24
+ [@awsid.bright, @zone, @size, @created, @instid, @snapid].join '; '
40
25
  end
41
26
 
42
27
  # Alias for status
@@ -155,7 +140,14 @@ module Rudy::AWS
155
140
  volumes = nil if volumes.empty?
156
141
  volumes
157
142
  end
158
-
143
+
144
+ def list_by_instance(instid, &each_vol)
145
+ instid = instid.awsid if instid.is_a? Rudy::AWS::EC2::Instance
146
+ volumes = list(:attached, &each_vol)
147
+ volumes &&= volumes.select { |v| v.instid == instid }
148
+ volumes
149
+ end
150
+
159
151
  def any?(state=nil,vol_id=[])
160
152
  vols = list(state, vol_id)
161
153
  !vols.nil?
@@ -180,7 +172,7 @@ module Rudy::AWS
180
172
  vol_id = Volumes.get_vol_id(vol_id)
181
173
  return false unless vol_id
182
174
  vol = get(vol_id)
183
- (vol && vol.status == state)
175
+ (vol && vol.status == state) ? true : false
184
176
  end
185
177
  end
186
178