rest-ftp-daemon 0.435.2 → 0.501.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +35 -29
  3. data/config.ru +1 -1
  4. data/defaults.yml +16 -12
  5. data/lib/rest-ftp-daemon.rb +1 -0
  6. data/lib/rest-ftp-daemon/api/config.rb +1 -2
  7. data/lib/rest-ftp-daemon/api/dashboard.rb +6 -4
  8. data/lib/rest-ftp-daemon/api/debug.rb +6 -5
  9. data/lib/rest-ftp-daemon/api/jobs.rb +1 -1
  10. data/lib/rest-ftp-daemon/api/root.rb +11 -10
  11. data/lib/rest-ftp-daemon/api/status.rb +1 -1
  12. data/lib/rest-ftp-daemon/constants.rb +12 -3
  13. data/lib/rest-ftp-daemon/counters.rb +1 -1
  14. data/lib/rest-ftp-daemon/entities/job.rb +1 -5
  15. data/lib/rest-ftp-daemon/entities/location.rb +4 -3
  16. data/lib/rest-ftp-daemon/entities/options.rb +1 -1
  17. data/lib/rest-ftp-daemon/exceptions.rb +1 -1
  18. data/lib/rest-ftp-daemon/helpers/api.rb +1 -1
  19. data/lib/rest-ftp-daemon/helpers/common.rb +1 -1
  20. data/lib/rest-ftp-daemon/helpers/views.rb +29 -10
  21. data/lib/rest-ftp-daemon/initialize.rb +1 -1
  22. data/lib/rest-ftp-daemon/job.rb +11 -13
  23. data/lib/rest-ftp-daemon/job_queue.rb +9 -10
  24. data/lib/rest-ftp-daemon/jobs/dummy.rb +1 -1
  25. data/lib/rest-ftp-daemon/jobs/errors.rb +13 -15
  26. data/lib/rest-ftp-daemon/jobs/transfer.rb +15 -15
  27. data/lib/rest-ftp-daemon/jobs/video.rb +7 -7
  28. data/lib/rest-ftp-daemon/launcher.rb +1 -1
  29. data/lib/rest-ftp-daemon/location.rb +91 -67
  30. data/lib/rest-ftp-daemon/metrics.rb +2 -2
  31. data/lib/rest-ftp-daemon/notification.rb +1 -1
  32. data/lib/rest-ftp-daemon/paginate.rb +1 -1
  33. data/lib/rest-ftp-daemon/remote/base.rb +8 -3
  34. data/lib/rest-ftp-daemon/remote/ftp.rb +18 -18
  35. data/lib/rest-ftp-daemon/remote/s3.rb +100 -41
  36. data/lib/rest-ftp-daemon/remote/sftp.rb +15 -15
  37. data/lib/rest-ftp-daemon/static/css/main.css +34 -4
  38. data/lib/rest-ftp-daemon/uri.rb +1 -1
  39. data/lib/rest-ftp-daemon/views/dashboard.haml +1 -1
  40. data/lib/rest-ftp-daemon/views/dashboard_counters.haml +1 -1
  41. data/lib/rest-ftp-daemon/views/dashboard_footer.haml +1 -1
  42. data/lib/rest-ftp-daemon/views/dashboard_header.haml +1 -1
  43. data/lib/rest-ftp-daemon/views/dashboard_jobs.haml +1 -2
  44. data/lib/rest-ftp-daemon/views/dashboard_rates.haml +1 -1
  45. data/lib/rest-ftp-daemon/views/dashboard_table.haml +8 -5
  46. data/lib/rest-ftp-daemon/views/dashboard_tokens.haml +1 -1
  47. data/lib/rest-ftp-daemon/views/dashboard_workers.haml +1 -1
  48. data/lib/rest-ftp-daemon/worker_pool.rb +2 -2
  49. data/lib/rest-ftp-daemon/workers/conchita.rb +1 -1
  50. data/lib/rest-ftp-daemon/workers/reporter.rb +1 -1
  51. data/lib/rest-ftp-daemon/workers/transfer.rb +3 -3
  52. data/lib/rest-ftp-daemon/workers/worker.rb +1 -1
  53. data/lib/shared/patch_file.rb +5 -0
  54. data/rest-ftp-daemon.gemspec +2 -2
  55. data/spec/spec_helper.rb +2 -1
  56. data/spec/support/request_helpers.rb +1 -1
  57. metadata +6 -5
@@ -43,4 +43,4 @@ module RestFtpDaemon
43
43
  end
44
44
 
45
45
  end
46
- end
46
+ end
@@ -50,10 +50,6 @@ module RestFtpDaemon
50
50
  # Source and target #, :unless => Proc.new {|g| g.source_loc.nil?}
51
51
  expose :source_loc, using: Entities::Location#, as: :source
52
52
  expose :target_loc, using: Entities::Location#, as: :target
53
-
54
- # expose :slots do |station,options|
55
- # station.slots.map{ |slot| SlotEntity.new(slot).serializable_hash }
56
- # end
57
53
  end
58
54
  end
59
- end
55
+ end
@@ -4,8 +4,9 @@ module RestFtpDaemon
4
4
  module Entities
5
5
  class Location < Grape::Entity
6
6
 
7
- expose :original, as: '_'
8
- expose :uri
7
+ expose :url
8
+ #, as: 'raw'
9
+ # expose :uri
9
10
  expose :scheme
10
11
 
11
12
  expose :host, unless: Proc.new {|obj| obj.host.nil?}
@@ -22,4 +23,4 @@ module RestFtpDaemon
22
23
 
23
24
  end
24
25
  end
25
- end
26
+ end
@@ -10,4 +10,4 @@ module RestFtpDaemon
10
10
 
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -28,4 +28,4 @@ module RestFtpDaemon
28
28
  class VideoMovieError < BaseException; end
29
29
 
30
30
 
31
- end
31
+ end
@@ -22,4 +22,4 @@ module RestFtpDaemon
22
22
  end
23
23
 
24
24
  end
25
- end
25
+ end
@@ -34,4 +34,4 @@ module RestFtpDaemon
34
34
  end
35
35
 
36
36
  end
37
- end
37
+ end
@@ -40,6 +40,8 @@ module RestFtpDaemon
40
40
  "success"
41
41
  when URI::S3
42
42
  "primary"
43
+ when URI::Generic
44
+ "info"
43
45
  else
44
46
  "default"
45
47
  end
@@ -58,15 +60,6 @@ module RestFtpDaemon
58
60
  end
59
61
  end
60
62
 
61
- def location_label uri
62
- sprintf(
63
- '<div class="transfer-type label label-%s" title="%s">%s</div>',
64
- location_style(uri),
65
- uri.to_s,
66
- uri.class.name.split('::').last
67
- )
68
- end
69
-
70
63
  def job_type job
71
64
  # sprintf(
72
65
  # '<span class="glyphicon glyphicon-%s" alt="%s"></span>&nbsp;%s',
@@ -118,6 +111,32 @@ module RestFtpDaemon
118
111
  path.gsub(/\[([^\[]+)\]/, token_to_label('\1'))
119
112
  end
120
113
 
114
+ def location_label loc
115
+ # sprintf(
116
+ # '<div class="transfer-type label label-%s" title="%s">%s</div>',
117
+ # location_style(loc.uri),
118
+ # loc.to_s,
119
+ # loc.uri.class.name.split('::').last
120
+ # )
121
+ sprintf(
122
+ '
123
+ <span class="label-group">
124
+ <span class="transfer-type label label-xs label-%s" title="%s">%s</span><span class="label label-simple" title="%s">%s</span>
125
+ </span>
126
+ ',
127
+ location_style(loc.uri),
128
+ loc.to_s,
129
+ loc.uri.class.name.split('::').last,
130
+ loc.tokens.first,
131
+ loc.tokens.first,
132
+ )
133
+ end
134
+
135
+ # def token_highlight path
136
+ # return unless path.is_a? String
137
+ # path.gsub(/\[([^\[]+)\]/, token_to_label('\1'))
138
+ # end
139
+
121
140
  def text_or_empty text
122
141
  return "-" if text.nil? || text.empty?
123
142
  text
@@ -125,4 +144,4 @@ module RestFtpDaemon
125
144
 
126
145
 
127
146
  end
128
- end
147
+ end
@@ -11,4 +11,4 @@ end
11
11
 
12
12
  # Initialize workers
13
13
  Conf.log :initialize, "prepare workers"
14
- RestFtpDaemon::WorkerPool.instance.start_em_all
14
+ RestFtpDaemon::WorkerPool.instance.start_em_all
@@ -85,7 +85,7 @@ module RestFtpDaemon
85
85
  @target_loc = Location.new(params[:target])
86
86
 
87
87
  # We're done!
88
- log_info "Job.initialized", {
88
+ log_info "initialized", {
89
89
  source: @source_loc.uri,
90
90
  target: @target_loc.uri,
91
91
  pool: @pool,
@@ -110,7 +110,7 @@ module RestFtpDaemon
110
110
  set_status JOB_STATUS_QUEUED
111
111
  set_error nil
112
112
  client_notify :queued
113
- log_info "Job.reset notify[queued] tentative[#{@tentatives}]"
113
+ log_info "reset notify[queued] tentative[#{@tentatives}]"
114
114
  end
115
115
 
116
116
  # Process job
@@ -123,23 +123,23 @@ module RestFtpDaemon
123
123
  @started_at = Time.now
124
124
 
125
125
  # Notify we start working
126
- log_info "Job.start notify [started]"
126
+ log_info "client_notify [started]"
127
127
  current_signal = :started
128
128
  set_status JOB_STATUS_WORKING
129
129
  client_notify :started
130
130
 
131
131
  # Before work
132
- log_debug "Job.start do_before"
132
+ log_debug "do_before"
133
133
  current_signal = :started
134
134
  do_before
135
135
 
136
136
  # Do the hard work
137
- log_debug "Job.start do_work"
137
+ log_debug "do_work"
138
138
  current_signal = :ended
139
139
  do_work
140
140
 
141
141
  # Finalize all this
142
- log_debug "Job.start do_after"
142
+ log_debug "do_after"
143
143
  current_signal = :ended
144
144
  do_after
145
145
 
@@ -150,7 +150,7 @@ module RestFtpDaemon
150
150
  else
151
151
  # All done !
152
152
  set_status JOB_STATUS_FINISHED
153
- log_info "Job.start notify [ended]"
153
+ log_info "client_notify [ended]"
154
154
  client_notify :ended
155
155
  end
156
156
 
@@ -217,7 +217,7 @@ module RestFtpDaemon
217
217
  protected
218
218
 
219
219
  def alert_common_method_called
220
- log_error "Job PLACEHOLDER METHOD CALLED"
220
+ log_error "PLACEHOLDER METHOD CALLED"
221
221
  end
222
222
 
223
223
  private
@@ -289,25 +289,23 @@ module RestFtpDaemon
289
289
  RestFtpDaemon::Notification.new @notify, payload
290
290
 
291
291
  rescue StandardError => ex
292
- log_error "Job.client_notify EXCEPTION: #{ex.inspect}"
292
+ log_error "client_notify EXCEPTION: #{ex.inspect}"
293
293
  end
294
294
 
295
295
  def oops signal, exception, error = nil#, include_backtrace = false
296
296
  # Find error code in ERRORS table
297
297
  if error.nil?
298
298
  error = ERRORS.key(exception.class)
299
- # log_debug "Job.oops ERRORS: #{exception.class} > #{error}"
300
299
  end
301
300
 
302
301
  # Default error code derived from exception name
303
302
  if error.nil?
304
303
  error = exception_to_error(exception)
305
- # log_debug "Job.oops derivated: #{exception.class} > #{error}"
306
304
  include_backtrace = true
307
305
  end
308
306
 
309
307
  # Log backtrace ?
310
- message = "Job.oops signal[#{signal}] exception[#{exception.class}] error[#{error}] #{exception.message}"
308
+ message = "oops signal[#{signal}] exception[#{exception.class}] error[#{error}] #{exception.message}"
311
309
  if include_backtrace
312
310
  log_error message, exception.backtrace
313
311
  else
@@ -349,4 +347,4 @@ module RestFtpDaemon
349
347
  add_transaction_tracer :initialize, category: :task
350
348
 
351
349
  end
352
- end
350
+ end
@@ -30,7 +30,7 @@ module RestFtpDaemon
30
30
 
31
31
  # Identifiers generator
32
32
  @prefix = identifier(JOB_IDENT_LEN)
33
- log_info "JobQueue initialized (prefix: #{@prefix})"
33
+ log_info "initialized (prefix: #{@prefix})"
34
34
  end
35
35
 
36
36
  def create_job params
@@ -42,7 +42,7 @@ module RestFtpDaemon
42
42
  # If object not found, don't create a job !
43
43
  unless klass && klass < Job
44
44
  message = "can't create [#{klass_name}] for type [#{params[:type]}]"
45
- log_error "JobQueue.create_job: #{message}"
45
+ log_error "create_job: #{message}"
46
46
  raise QueueCantCreateJob, message
47
47
  end
48
48
 
@@ -53,7 +53,7 @@ module RestFtpDaemon
53
53
  job_id = prefixed_id(@last_id)
54
54
 
55
55
  # Instantiate it and return the now object
56
- log_info "JobQueue.create_job: creating [#{klass.name}] with ID [#{job_id}]"
56
+ log_info "create_job: creating [#{klass.name}] with ID [#{job_id}]"
57
57
  job = klass.new(job_id, params)
58
58
 
59
59
  # Push it on the queue
@@ -147,10 +147,10 @@ module RestFtpDaemon
147
147
 
148
148
  def push job
149
149
  # Check that item responds to "priorty" method
150
- raise "JobQueue.push: job should respond to: priority" unless job.respond_to? :priority
151
- raise "JobQueue.push: job should respond to: id" unless job.respond_to? :id
152
- raise "JobQueue.push: job should respond to: pool" unless job.respond_to? :pool
153
- raise "JobQueue.push: job should respond to: reset" unless job.respond_to? :reset
150
+ raise "push: job should respond to: priority" unless job.respond_to? :priority
151
+ raise "push: job should respond to: id" unless job.respond_to? :id
152
+ raise "push: job should respond to: pool" unless job.respond_to? :pool
153
+ raise "push: job should respond to: reset" unless job.respond_to? :reset
154
154
 
155
155
  @mutex.synchronize do
156
156
  # Get this job's pool & prepare queue of this pool
@@ -190,7 +190,6 @@ module RestFtpDaemon
190
190
  @waitings[pool] ||= []
191
191
  loop do
192
192
  if myqueue.empty?
193
- #puts "JobQueue.pop(#{pool}): empty"
194
193
  raise ThreadError, "queue empty" if non_block
195
194
  @waitings[pool].push Thread.current
196
195
  @mutex.sleep
@@ -228,7 +227,7 @@ module RestFtpDaemon
228
227
 
229
228
  # Compute oldest limit
230
229
  time_limit = Time.now - maxage.to_i
231
- log_info "JobQueue.expire limit [#{time_limit}] status [#{status}]" if verbose
230
+ log_info "expire limit [#{time_limit}] status [#{status}]" if verbose
232
231
 
233
232
  @mutex.synchronize do
234
233
  # Delete jobs from the queue when they match status and age limits
@@ -269,4 +268,4 @@ module RestFtpDaemon
269
268
  add_transaction_tracer :jobs_by_status, category: :task
270
269
 
271
270
  end
272
- end
271
+ end
@@ -17,4 +17,4 @@ module RestFtpDaemon
17
17
  end
18
18
 
19
19
  end
20
- end
20
+ end
@@ -5,12 +5,16 @@ require "net/ftp"
5
5
  require 'streamio-ffmpeg'
6
6
 
7
7
  module RestFtpDaemon
8
+ class InvalidWorkerNumber < BaseException; end
9
+ class QueueCantCreateJob < BaseException; end
10
+ class JobException < BaseException; end
11
+ class JobNotFound < BaseException; end
8
12
  class Job
9
13
 
10
14
  # Common errors
11
15
  ERRORS = {
12
- invalid_argument: Errno::EINVAL,
13
- runtime_error: RuntimeError,
16
+ # oops_invalid_argument: Errno::EINVAL,
17
+ oops_runtime_error: RuntimeError,
14
18
 
15
19
  job_timeout: RestFtpDaemon::JobTimeout,
16
20
  source_not_supported: RestFtpDaemon::SourceUnsupported,
@@ -41,7 +45,10 @@ module RestFtpDaemon
41
45
  ftp_proto_error: Net::FTPProtoError,
42
46
  ftp_error: Net::FTPError,
43
47
 
44
- ffmpeg_error: FFMPEG::Error,
48
+ sftp_exception: Net::SFTP::StatusException,
49
+ sftp_key_mismatch: Net::SSH::HostKeyMismatch,
50
+ sftp_auth_failed: Net::SSH::AuthenticationFailed,
51
+ sftp_openssl_error: OpenSSL::SSL::SSLError,
45
52
 
46
53
  s3_no_such_waiter: Aws::Waiters::Errors::NoSuchWaiterError,
47
54
  s3_failure_state_error: Aws::Waiters::Errors::FailureStateError,
@@ -49,30 +56,21 @@ module RestFtpDaemon
49
56
  s3_waiter_unexpected: Aws::Waiters::Errors::UnexpectedError,
50
57
  s3_waiter_failed: Aws::Waiters::Errors::WaiterFailed,
51
58
 
59
+ #s3_not_found: Aws::S3::Errors::NotFound,
52
60
  s3_permanent_redirect: Aws::S3::Errors::PermanentRedirect,
53
61
  s3_no_such_key: Aws::S3::Errors::NoSuchKey,
54
62
  s3_no_such_bucket: Aws::S3::Errors::NoSuchBucket,
55
63
  s3_no_such_upload: Aws::S3::Errors::NoSuchUpload,
56
64
  s3_error: Aws::S3::Errors::ServiceError,
57
65
 
58
- sftp_exception: Net::SFTP::StatusException,
59
- sftp_key_mismatch: Net::SSH::HostKeyMismatch,
60
- sftp_auth_failed: Net::SSH::AuthenticationFailed,
61
- sftp_openssl_error: OpenSSL::SSL::SSLError,
62
-
63
66
  video_missing_binary: RestFtpDaemon::VideoMissingBinary,
64
67
  video_movie_error: RestFtpDaemon::VideoMovieError,
68
+ video_ffmpeg_error: FFMPEG::Error,
65
69
 
66
70
  # rescue Encoding::UndefinedConversionError => exception
67
71
  # return oops :ended, exception, "encoding_error", true
68
72
  }
69
73
 
70
- class InvalidWorkerNumber < BaseException; end
71
- class QueueCantCreateJob < BaseException; end
72
- class JobException < BaseException; end
73
- class JobNotFound < BaseException; end
74
-
75
-
76
74
 
77
75
  end
78
- end
76
+ end
@@ -21,20 +21,20 @@ module RestFtpDaemon
21
21
  # Prepare remote object
22
22
  case target_uri
23
23
  when URI::FTP
24
- log_info "JobTransfer.do_before target_method FTP"
24
+ log_info "do_before target_method FTP"
25
25
  @remote = Remote::RemoteFTP.new @target_loc, log_context, @config[:debug_ftp]
26
26
  when URI::FTPES, URI::FTPS
27
- log_info "JobTransfer.do_before target_method FTPES/FTPS"
27
+ log_info "do_before target_method FTPES/FTPS"
28
28
  @remote = Remote::RemoteFTP.new @target_loc, log_context, @config[:debug_ftps], :ftpes
29
29
  when URI::SFTP
30
- log_info "JobTransfer.do_before target_method SFTP"
30
+ log_info "do_before target_method SFTP"
31
31
  @remote = Remote::RemoteSFTP.new @target_loc, log_context, @config[:debug_sftp]
32
32
  when URI::S3
33
- log_info "JobTransfer.do_before target_method S3"
33
+ log_info "do_before target_method S3"
34
34
  @remote = Remote::RemoteS3.new @target_loc, log_context, @config[:debug_s3]
35
35
  else
36
36
  message = "unknown scheme [#{@target_loc.scheme}] [#{target_uri.class.name}]"
37
- log_info "JobTransfer.do_before #{message}"
37
+ log_info "do_before #{message}"
38
38
  raise RestFtpDaemon::TargetUnsupported, message
39
39
  end
40
40
 
@@ -48,10 +48,10 @@ module RestFtpDaemon
48
48
  def do_work
49
49
  # Scan local source files from disk
50
50
  set_status JOB_STATUS_CHECKING_SRC
51
- sources = @source_loc.scan_files
51
+ sources = @source_loc.local_files
52
52
  set_info INFO_SOURCE_COUNT, sources.size
53
53
  set_info INFO_SOURCE_FILES, sources.collect(&:name)
54
- log_info "JobTransfer.do_work sources #{sources.collect(&:name)}"
54
+ log_info "do_work sources #{sources.collect(&:name)}"
55
55
  raise RestFtpDaemon::SourceNotFound if sources.empty?
56
56
 
57
57
  # Guess target file name, and fail if present while we matched multiple sources
@@ -63,7 +63,8 @@ module RestFtpDaemon
63
63
 
64
64
  # Prepare target path or build it if asked
65
65
  set_status JOB_STATUS_CHDIR
66
- @remote.chdir_or_create @target_loc.dir, @mkdir
66
+ #log_info "do_work chdir_or_create #{@target_loc.filedir}"
67
+ @remote.chdir_or_create @target_loc.filedir, @mkdir
67
68
 
68
69
  # Compute total files size
69
70
  @transfer_total = sources.collect(&:size).sum
@@ -95,7 +96,7 @@ module RestFtpDaemon
95
96
 
96
97
  def do_after
97
98
  # Close FTP connexion and free up memory
98
- log_info "JobTransfer.do_after close connexion, update status and counters"
99
+ log_info "do_after close connexion, update status and counters"
99
100
  @remote.close
100
101
 
101
102
  # Free @remote object
@@ -117,14 +118,14 @@ module RestFtpDaemon
117
118
  raise RestFtpDaemon::AssertionFailed, "remote_upload/target" if target.nil?
118
119
 
119
120
  # Use source filename if target path provided none (typically with multiple sources)
120
- log_info "JobTransfer.remote_upload [#{source.name}]: [#{source.path}] > [#{target.path}]"
121
+ log_info "remote_upload temp[#{@tempfile}] source[#{source.path}] target[#{target.path}]"
121
122
  set_info INFO_SOURCE_CURRENT, source.name
122
123
 
123
124
  # Remove any existing version if present, or check if it's there
124
125
  if @overwrite
125
126
  @remote.remove! target
126
- elsif size = @remote.present?(target)
127
- log_debug "JobTransfer.remote_upload existing (#{format_bytes size, 'B'})"
127
+ elsif (size = @remote.size_if_exists(target)) # won't be triggered when NIL or 0 is returned
128
+ log_debug "remote_upload file exists ! (#{format_bytes size, 'B'})"
128
129
  raise RestFtpDaemon::TargetFileExists
129
130
  end
130
131
 
@@ -134,7 +135,6 @@ module RestFtpDaemon
134
135
 
135
136
  # Start the transfer, update job status after each block transfer
136
137
  set_status JOB_STATUS_UPLOADING
137
- log_debug "JobTransfer.remote_upload source[#{source.path}] temp[#{@tempfile}]"
138
138
  @remote.upload source, target, @tempfile do |transferred, name|
139
139
  # Update transfer statistics
140
140
  update_progress transferred, name
@@ -192,7 +192,7 @@ module RestFtpDaemon
192
192
  format_bytes(@current_bitrate.round(0), "bps")
193
193
  ]
194
194
  stack2 = stack.map { |txt| ("%#{LOG_PIPE_LEN.to_i}s" % txt) }.join("\t")
195
- log_debug "progress #{stack2} \t#{name}"
195
+ log_info "progress #{stack2} \t#{name}"
196
196
 
197
197
  # Prepare and send notification
198
198
  client_notify :progress, status: {
@@ -233,4 +233,4 @@ module RestFtpDaemon
233
233
  # add_transaction_tracer :prepare, category: :task
234
234
  # add_transaction_tracer :run, category: :task
235
235
 
236
- end
236
+ end