ey_cloud_server 1.1.1.pre7 → 1.2.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.
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