rest-ftp-daemon 0.435.2 → 0.501.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.
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