ey_cloud_server 1.1.1.pre7 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/ey-snapshots CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
-
3
2
  require File.dirname(__FILE__) + '/../lib/ey-flex'
4
3
 
5
- puts EY::SnapshotMinder.run(ARGV)
4
+ EY::SnapshotMinder.run(ARGV)
data/lib/ey-flex.rb CHANGED
@@ -7,6 +7,7 @@ require 'fileutils'
7
7
  require 'json/ext'
8
8
  require 'right_aws'
9
9
  require 'open-uri'
10
+ require 'rest_client'
10
11
  require 'dbi'
11
12
  require 'zlib'
12
13
  require 'stringio'
@@ -26,6 +27,7 @@ end
26
27
  require lib_dir + '/big-brother'
27
28
  require lib_dir + '/backups'
28
29
  require lib_dir + '/bucket_minder'
30
+ require lib_dir + '/ey-api'
29
31
  require lib_dir + '/mysql_database'
30
32
  require lib_dir + '/postgresql_database'
31
33
  require lib_dir + '/snapshot_minder'
@@ -70,6 +70,10 @@ module EY::Flex
70
70
  options[:index] = index
71
71
  end
72
72
 
73
+ opts.on("-q", "--quiet", "Supress output to STDOUT") do
74
+ options[:quiet] = true
75
+ end
76
+
73
77
  end
74
78
 
75
79
  opts.parse!(args)
@@ -81,7 +85,7 @@ module EY::Flex
81
85
 
82
86
  case options[:command]
83
87
  when :list
84
- eyb.list options[:db], true
88
+ eyb.list options[:db]
85
89
  when :new_backup
86
90
  eyb.new_backup
87
91
  when :download
@@ -91,13 +95,13 @@ module EY::Flex
91
95
  end
92
96
  eyb.cleanup
93
97
  rescue EY::Flex::Error => e
94
- $stderr.puts e.message
95
- exit 1
98
+ abort e.message
96
99
  end
97
100
 
98
101
  ENGINES = {}
99
102
 
100
103
  def initialize(options = {})
104
+ @quiet = options[:quiet]
101
105
  engine_klass = ENGINES[options[:engine]] || raise("Invalid database engine: #{options[:engine].inspect}")
102
106
  @engine = engine_klass.new(self)
103
107
 
@@ -128,8 +132,7 @@ module EY::Flex
128
132
  if File.exist?(filename)
129
133
  @config = YAML::load(File.read(filename))
130
134
  else
131
- $stderr.puts "You need to have a backup file at #{filename}"
132
- exit 1
135
+ abort "You need to have a backup file at #{filename}"
133
136
  end
134
137
  end
135
138
 
@@ -139,16 +142,21 @@ module EY::Flex
139
142
  end
140
143
  end
141
144
 
145
+ def say(msg, newline = true)
146
+ return if @quiet
147
+ print("#{msg}#{"\n" if newline}")
148
+ end
149
+
142
150
  def backup_database(database)
143
151
  File.open("#{self.backup_dir}/#{database}.#{@tmpname}", "w") do |f|
144
- puts "doing database: #{database}"
152
+ say "doing database: #{database}"
145
153
  @engine.dump_database(database, f)
146
154
  end
147
155
 
148
156
  File.open("#{self.backup_dir}/#{database}.#{@tmpname}") do |f|
149
157
  path = "#{@env}.#{database}/#{database}.#{@tmpname}"
150
158
  AWS::S3::S3Object.store(path, f, @bucket, :access => :private)
151
- puts "successful backup: #{database}.#{@tmpname}"
159
+ say "successful backup: #{database}.#{@tmpname}"
152
160
  end
153
161
  end
154
162
 
@@ -158,13 +166,12 @@ module EY::Flex
158
166
 
159
167
  if obj = list(db)[idx.to_i]
160
168
  filename = normalize_name(obj)
161
- puts "downloading: #{filename}"
169
+ say "downloading: #{filename}"
162
170
  File.open(filename, 'wb') do |f|
163
- print "."
171
+ say ".", false
164
172
  obj.value {|chunk| f.write chunk }
165
173
  end
166
- puts
167
- puts "finished"
174
+ say "finished"
168
175
  [db, filename]
169
176
  else
170
177
  raise BackupNotFound, "No backup found for database #{db.inspect}: requested index: #{idx}"
@@ -180,8 +187,8 @@ module EY::Flex
180
187
 
181
188
  def cleanup
182
189
  begin
183
- list('all',false)[0...-(@keep*@databases.size)].each do |o|
184
- puts "deleting: #{o.key}"
190
+ list('all')[0...-(@keep*@databases.size)].each do |o|
191
+ say "deleting: #{o.key}"
185
192
  o.delete
186
193
  end
187
194
  rescue AWS::S3::S3Exception, AWS::S3::Error
@@ -197,8 +204,8 @@ module EY::Flex
197
204
  AWS::S3::S3Object.find name, @bucket
198
205
  end
199
206
 
200
- def list(database='all', printer = false)
201
- puts "Listing database backups for #{database}" if printer
207
+ def list(database='all')
208
+ say "Listing database backups for #{database}"
202
209
  backups = []
203
210
  if database == 'all'
204
211
  @databases.each do |db|
@@ -208,12 +215,12 @@ module EY::Flex
208
215
  else
209
216
  backups = AWS::S3::Bucket.objects(@bucket, :prefix => "#{@env}.#{database}").sort
210
217
  end
211
- if printer
212
- puts "#{backups.size} backup(s) found"
213
- backups.each_with_index do |b,i|
214
- puts "#{i}:#{database} #{normalize_name(b)}"
215
- end
216
- end
218
+
219
+ say "#{backups.size} backup(s) found"
220
+
221
+ backups.each_with_index do |b,i|
222
+ say "#{i}:#{database} #{normalize_name(b)}"
223
+ end
217
224
  backups
218
225
  end
219
226
 
@@ -0,0 +1,22 @@
1
+ module EyApi
2
+ def call_api(path, opts={})
3
+ response = @rest["/api/#{path}"].post(@keys.merge(opts), {"Accept" => "application/json"})
4
+ JSON.parse(response.body)
5
+ rescue RestClient::RequestFailed => e
6
+ case e.http_code
7
+ when 503
8
+ sleep 10 # Nanite, save us...
9
+ retry
10
+ else
11
+ raise "API call to Engine Yard failed with status #{e.http_code}."
12
+ end
13
+ end
14
+
15
+ def get_envs
16
+ @_envs ||= call_api("environments")
17
+ end
18
+
19
+ def get_json(instance_id)
20
+ call_api("json_for_instance", :instance_id => instance_id)
21
+ end
22
+ end
@@ -31,6 +31,9 @@ module EY
31
31
  options[:command] = :snapshot_volumes
32
32
  end
33
33
 
34
+ opts.on("-q", "--quiet", "Supress output to STDOUT") do
35
+ options[:quiet] = true
36
+ end
34
37
 
35
38
  end
36
39
 
@@ -40,8 +43,7 @@ module EY
40
43
  if File.exist?(config = File.expand_path(defaults[:config]))
41
44
  ey = new(options = defaults.merge(YAML::load(File.read(config))).merge(options))
42
45
  else
43
- puts"You need to have an /etc/.mysql.backups.yml file with your credentials in it to use this tool.\nOr point it at a yaml file with -c .mysql.backups.yml"
44
- exit 1
46
+ abort "You need to have an /etc/.mysql.backups.yml file with your credentials in it to use this tool.\nOr point it at a yaml file with -c .mysql.backups.yml"
45
47
  end
46
48
 
47
49
  ey.send(options[:command])
@@ -52,9 +54,9 @@ module EY
52
54
  @opts = opts
53
55
  @instance_id = opts[:instance_id]
54
56
  @db = Mysql.new('root', opts[:dbpass], opts[:lock_wait_timeout]) rescue nil
55
- @ec2 = RightAws::Ec2.new(opts[:aws_secret_id], opts[:aws_secret_key])
57
+ @ec2 = RightAws::Ec2.new(opts[:aws_secret_id], opts[:aws_secret_key], :logger => Logger.new("/dev/null"))
56
58
  get_instance_id
57
- find_volume_ids
59
+ silence_stream($stderr) { find_volume_ids }
58
60
  end
59
61
 
60
62
  def find_volume_ids
@@ -68,7 +70,7 @@ module EY
68
70
  end
69
71
  end
70
72
  end
71
- puts("Volume IDs are #{@volume_ids.inspect}")
73
+ say "Volume IDs are #{@volume_ids.inspect}"
72
74
  @volume_ids
73
75
  end
74
76
 
@@ -81,7 +83,7 @@ module EY
81
83
  end
82
84
  end
83
85
  end
84
- puts("Snapshots #{@snapshot_ids.inspect}")
86
+ say "Snapshots #{@snapshot_ids.inspect}"
85
87
  @snapshot_ids
86
88
  end
87
89
 
@@ -93,7 +95,7 @@ module EY
93
95
  snaps << snapshot
94
96
  end
95
97
  (snaps[keep..-1]||[]).each do |snapshot|
96
- puts "deleting snapshot of /#{mnt}: #{snapshot[:aws_id]}"
98
+ say "deleting snapshot of /#{mnt}: #{snapshot[:aws_id]}"
97
99
  @ec2.delete_snapshot(snapshot[:aws_id])
98
100
  end
99
101
  end
@@ -109,7 +111,7 @@ module EY
109
111
  snaps << create_snapshot(vid)
110
112
  when :db
111
113
  @db.flush_tables_with_read_lock
112
- puts("Read lock acquired. Writing master binlog info to #{@master_status_file} and syncing filesystem buffers.")
114
+ say "Read lock acquired. Writing master binlog info to #{@master_status_file} and syncing filesystem buffers."
113
115
  @db.write_master_status
114
116
  sync_filesystem_buffers
115
117
  snaps << create_snapshot(vid)
@@ -125,8 +127,8 @@ module EY
125
127
  open('http://169.254.169.254/latest/meta-data/instance-id') do |f|
126
128
  @instance_id = f.gets
127
129
  end
128
- raise "Cannot find instance id!" unless @instance_id
129
- puts("Instance ID is #{@instance_id}")
130
+ abort "Cannot find instance id!" unless @instance_id
131
+ say "Instance ID is #{@instance_id}"
130
132
  @instance_id
131
133
  end
132
134
 
@@ -137,10 +139,24 @@ module EY
137
139
 
138
140
  def create_snapshot(volume_id)
139
141
  snap = @ec2.create_snapshot(volume_id)
140
- puts("Created snapshot of #{volume_id} as #{snap[:aws_id]}")
142
+ say "Created snapshot of #{volume_id} as #{snap[:aws_id]}"
141
143
  snap
142
144
  end
143
-
145
+
146
+ private
147
+ def say(msg, newline = true)
148
+ return if @opts[:quiet]
149
+ print("#{msg}#{"\n" if newline}")
150
+ end
151
+
152
+ def silence_stream(stream)
153
+ old_stream = stream.dup
154
+ stream.reopen("/dev/null")
155
+ stream.sync = true
156
+ yield
157
+ ensure
158
+ stream.reopen(old_stream)
159
+ end
144
160
  end
145
161
 
146
162
  class Mysql
@@ -166,8 +182,6 @@ module EY
166
182
  end
167
183
 
168
184
  def flush_tables_with_read_lock
169
- puts("Requesting read lock for snapshot.")
170
-
171
185
  pipe = IO.popen("mysql -u #{@username} -p#{@password}", 'w')
172
186
  @read_lock_pid = pipe.pid
173
187
 
@@ -180,14 +194,13 @@ module EY
180
194
  # after killing the process the mysql thread is still hanging out, need to kill it directly
181
195
  kill_thread_cmd = "mysql -u #{@username} -p#{@password} -e'kill #{thread_id};'"
182
196
  system(kill_thread_cmd)
183
- raise "Read lock not acquired after #{@lock_wait_timeout} second timeout. Killed request and aborting backup."
197
+ abort "Read lock not acquired after #{@lock_wait_timeout} second timeout. Killed request and aborting backup."
184
198
  end
185
199
 
186
200
  true
187
201
  end
188
202
 
189
203
  def unlock_tables
190
- puts("Unlocking tables")
191
204
  # technically we don't actually have to do anything here since the spawned
192
205
  # process that has the read lock will die with this one but it doesn't hurt
193
206
  # to be safe
@@ -196,10 +209,7 @@ module EY
196
209
  end
197
210
 
198
211
  def disconnect
199
- puts("Disconnecting from MySQL")
200
212
  @dbh.disconnect
201
213
  end
202
-
203
214
  end
204
-
205
- end
215
+ end
@@ -1,3 +1,3 @@
1
1
  module EY::CloudServer
2
- VERSION = '1.1.1.pre7'
2
+ VERSION = '1.1.0'
3
3
  end
metadata CHANGED
@@ -1,110 +1,124 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ey_cloud_server
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: true
4
+ prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 1
8
- - 1
9
- - pre7
10
- version: 1.1.1.pre7
7
+ - 2
8
+ - 0
9
+ version: 1.2.0
11
10
  platform: ruby
12
11
  authors:
13
- - Ezra Zygmuntowicz
12
+ - Engine Yard Engineers
14
13
  autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-04-19 00:00:00 -07:00
17
+ date: 2010-04-27 00:00:00 -07:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
- type: :runtime
23
- version_requirements: &id001 !ruby/object:Gem::Requirement
21
+ name: json
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  segments:
28
28
  - 0
29
29
  version: "0"
30
- requirement: *id001
31
- name: json
32
- prerelease: false
33
- - !ruby/object:Gem::Dependency
34
30
  type: :runtime
35
- version_requirements: &id002 !ruby/object:Gem::Requirement
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: right_aws
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
39
  segments:
40
40
  - 0
41
41
  version: "0"
42
- requirement: *id002
43
- name: right_aws
44
- prerelease: false
42
+ type: :runtime
43
+ version_requirements: *id002
45
44
  - !ruby/object:Gem::Dependency
45
+ name: open4
46
+ prerelease: false
47
+ requirement: &id003 !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - "="
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 0
53
+ - 9
54
+ - 6
55
+ version: 0.9.6
46
56
  type: :runtime
47
- version_requirements: &id003 !ruby/object:Gem::Requirement
57
+ version_requirements: *id003
58
+ - !ruby/object:Gem::Dependency
59
+ name: aws-s3
60
+ prerelease: false
61
+ requirement: &id004 !ruby/object:Gem::Requirement
48
62
  requirements:
49
63
  - - ">="
50
64
  - !ruby/object:Gem::Version
51
65
  segments:
52
66
  - 0
53
67
  version: "0"
54
- requirement: *id003
55
- name: open4
56
- prerelease: false
57
- - !ruby/object:Gem::Dependency
58
68
  type: :runtime
59
- version_requirements: &id004 !ruby/object:Gem::Requirement
69
+ version_requirements: *id004
70
+ - !ruby/object:Gem::Dependency
71
+ name: rest-client
72
+ prerelease: false
73
+ requirement: &id005 !ruby/object:Gem::Requirement
60
74
  requirements:
61
75
  - - ">="
62
76
  - !ruby/object:Gem::Version
63
77
  segments:
64
78
  - 0
65
79
  version: "0"
66
- requirement: *id004
67
- name: aws-s3
68
- prerelease: false
69
- - !ruby/object:Gem::Dependency
70
80
  type: :runtime
71
- version_requirements: &id005 !ruby/object:Gem::Requirement
81
+ version_requirements: *id005
82
+ - !ruby/object:Gem::Dependency
83
+ name: ey_stonith
84
+ prerelease: false
85
+ requirement: &id006 !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - "="
87
+ - - ~>
74
88
  - !ruby/object:Gem::Version
75
89
  segments:
76
90
  - 0
77
- - 1
78
- - 5
79
- - pre3
80
- version: 0.1.5.pre3
81
- requirement: *id005
82
- name: ey_stonith
83
- prerelease: false
84
- description: Server side components for Engine Yard's cloud
85
- email: awsmdev@engineyard.com
91
+ - 2
92
+ - 0
93
+ version: 0.2.0
94
+ type: :runtime
95
+ version_requirements: *id006
96
+ description: "Server side components for Engine Yard's cloud "
97
+ email:
98
+ - ninja@engineyard.com
86
99
  executables:
87
100
  - eybackup
88
101
  - ey-snapshots
89
102
  - ey-agent
90
103
  extensions: []
91
104
 
92
- extra_rdoc_files:
93
- - README.rdoc
94
- - LICENSE
105
+ extra_rdoc_files: []
106
+
95
107
  files:
96
- - LICENSE
97
- - README.rdoc
98
108
  - lib/ey-flex/backups.rb
99
109
  - lib/ey-flex/big-brother.rb
100
110
  - lib/ey-flex/bucket_minder.rb
111
+ - lib/ey-flex/ey-api.rb
101
112
  - lib/ey-flex/mysql_database.rb
102
113
  - lib/ey-flex/postgresql_database.rb
103
114
  - lib/ey-flex/snapshot_minder.rb
104
115
  - lib/ey-flex/version.rb
105
116
  - lib/ey-flex.rb
117
+ - bin/eybackup
118
+ - bin/ey-snapshots
119
+ - bin/ey-agent
106
120
  has_rdoc: true
107
- homepage: http://engineyard.com/cloud
121
+ homepage: http://github.com/engineyard
108
122
  licenses: []
109
123
 
110
124
  post_install_message:
@@ -121,16 +135,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
121
135
  version: "0"
122
136
  required_rubygems_version: !ruby/object:Gem::Requirement
123
137
  requirements:
124
- - - ">"
138
+ - - ">="
125
139
  - !ruby/object:Gem::Version
126
140
  segments:
127
- - 1
128
- - 3
129
- - 1
130
- version: 1.3.1
141
+ - 0
142
+ version: "0"
131
143
  requirements: []
132
144
 
133
- rubyforge_project:
145
+ rubyforge_project: http://gemcutter.org
134
146
  rubygems_version: 1.3.6
135
147
  signing_key:
136
148
  specification_version: 3
data/LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright (c) 2009 Engine Yard Inc.
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc DELETED
@@ -1,25 +0,0 @@
1
- == ey
2
-
3
- = Development
4
-
5
- You need to have gem bundler install
6
-
7
- gem install bundler
8
-
9
- Then bundle everything up:
10
-
11
- gem bundle -- --with-mysql_config
12
-
13
- To run the specs, just jump into a "bundled" shell:
14
-
15
- gem exec bash
16
-
17
- Copy the example file to spec/config.yml:
18
-
19
- Then you can run specs:
20
-
21
- spec -c spec
22
-
23
- Running the bin files are easy too:
24
-
25
- bin/ey-recipes