etna 0.1.40 → 0.1.41

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e83d3c30c23693011d59b103f8b5a9372950eba1b3123376a288826204d47c62
4
- data.tar.gz: c3b50952e71d91f4361a87e872ba5532849644abe42fbc9e480549726a6bbf93
3
+ metadata.gz: 44b6c9fde1d01fab95038052180531fafd4a120e77ffbd12a8ac14e28122cd05
4
+ data.tar.gz: e1cb315eaeb4d35efc9e7f181e0cad767833b98f7ce3f26386e040c758c8483c
5
5
  SHA512:
6
- metadata.gz: c3c561cdd7db4631c267f2edba8421b94baba5de790ca1ff9edd06cd21d039d7224d868eaa43ba7090b4114b595830ac777c1c4688ec15c9320cde90530be4e5
7
- data.tar.gz: 7148582a82f7e90357ed6658c7337bce7b34dd532b4a899ac27a2d74f40f34224cb6c225b2aa4db4164c467aa8a5c189d7acf28a1c462097e619e9875fbdc4d1
6
+ metadata.gz: 3129a01c4181a772ab6752ed319396485e06f774b8091bff1ed9cbf6543a34820e0cc0706fd313ce5b3fb848a25f347de17bc376dc66b36458975d6298f48608
7
+ data.tar.gz: 82c57cff18c826a0a2664a63e0a531df57c75af30ceb3408d1d8ec1b9cb942fd25bd11253e6d880db6973df4cd60ade0764fac798a543af1e7601bfcc21abc45
data/lib/etna.rb CHANGED
@@ -22,6 +22,7 @@ require_relative './etna/filesystem'
22
22
  require_relative './etna/formatting'
23
23
  require_relative './etna/cwl'
24
24
  require_relative './etna/metrics'
25
+ require_relative './etna/remote'
25
26
 
26
27
  class EtnaApp
27
28
  include Etna::Application
@@ -60,17 +60,6 @@ module Etna::Application
60
60
  end
61
61
  end
62
62
 
63
- # This will cause metrics to persist to a file.
64
- # NOTE -- /tmp/metrics.bin should be a persistent mount when using this.
65
- # You will still need to export metrics in the text format for the node_exporter on the host machine to
66
- # export them to prometheus. Ensure that the /tmp/metrics.bin is on a named volume or a bind mount, either is fine.
67
- def enable_job_metrics!
68
- require 'prometheus'
69
- Prometheus::Client.config.data_store = Prometheus::Client::DataStores::DirectFileStore.new({
70
- dir: "/tmp/metrics.bin"
71
- })
72
- end
73
-
74
63
  def setup_yabeda
75
64
  application = self.id
76
65
  Yabeda.configure do
@@ -198,7 +187,8 @@ module Etna::Application
198
187
 
199
188
  Yabeda.etna.last_command_completion.set(tags, Time.now.to_i)
200
189
  Yabeda.etna.command_runtime.measure(tags, dur)
201
- write_job_metrics("run_command")
190
+
191
+ write_job_metrics("run_command.#{cmd.class.name}")
202
192
  end
203
193
  end
204
194
  end
@@ -9,20 +9,24 @@ module Etna
9
9
  # Since we are doing manual triage of files,
10
10
  # do not automatically copy directory trees.
11
11
  # srcs must be a list of full paths to files.
12
- def copy_files(srcs)
12
+ def copy_files(srcs, &block)
13
13
  srcs.each do |src|
14
- next unless ingest_filesystem.exist?(src)
14
+ if !ingest_filesystem.exist?(src)
15
+ logger&.warn("#{src} does not exist on source filesystem. Skipping.")
16
+ next
17
+ end
15
18
 
16
19
  logger&.info("Copying file #{src} (#{Etna::Formatting.as_size(ingest_filesystem.stat(src).size)})")
17
20
 
18
21
  # For ingestion triage, just copy over the exact path + filename.
19
- copy_file(dest: src, src: src)
22
+ copy_file(dest: src, src: src, &block)
20
23
  end
21
24
  end
22
25
 
23
- def copy_file(dest:, src:)
24
- ingest_filesystem.with_readable(src, "r") do |file|
25
- metis_filesystem.do_streaming_upload(file, dest, file.size)
26
+ def copy_file(dest:, src:, &block)
27
+ ingest_filesystem.with_readable(src, "r") do |io|
28
+ metis_filesystem.do_streaming_upload(io, dest, ingest_filesystem.stat(src).size)
29
+ yield src if block_given?
26
30
  end
27
31
  end
28
32
  end
@@ -3,8 +3,7 @@ require 'fileutils'
3
3
  require 'open3'
4
4
  require 'securerandom'
5
5
  require 'concurrent-ruby'
6
- require 'net/sftp'
7
- require 'net/ssh'
6
+ require 'curb'
8
7
 
9
8
  module Etna
10
9
  # A class that encapsulates opening / reading file system entries that abstracts normal file access in order
@@ -377,55 +376,116 @@ module Etna
377
376
  end
378
377
 
379
378
  class SftpFilesystem < Filesystem
379
+ include WithPipeConsumer
380
+
381
+ class SftpFile
382
+ attr_reader :size, :name
383
+
384
+ def initialize(metadata)
385
+ @metadata_parts = metadata.split(" ")
386
+ @size = @metadata_parts[4].to_i
387
+ @perms = @metadata_parts.first
388
+ @name = @metadata_parts[8]
389
+ end
390
+ end
391
+
380
392
  def initialize(host:, username:, password: nil, port: 22, **args)
381
393
  @username = username
382
394
  @password = password
383
395
  @host = host
384
396
  @port = port
397
+
398
+ @dir_listings = {}
399
+ end
400
+
401
+ def url(src)
402
+ "sftp://#{@host}/#{src}"
385
403
  end
386
404
 
387
- def ssh
388
- @ssh ||= Net::SSH.start(@host, @username, password: @password)
405
+ def authn
406
+ "#{@username}:#{@password}"
389
407
  end
390
408
 
391
- def sftp
392
- @sftp ||= begin
393
- conn = Net::SFTP::Session.new(ssh)
394
- conn.loop { conn.opening? }
409
+ def curl_cmd(path, opts=[])
410
+ connection = Curl::Easy.new(url(path))
411
+ connection.http_auth_types = :basic
412
+ connection.username = @username
413
+ connection.password = @password
395
414
 
396
- conn
415
+ connection
416
+ end
417
+
418
+ def sftp_file_from_path(src)
419
+ file = ls(::File.dirname(src)).split("\n").map do |listing|
420
+ SftpFile.new(listing)
421
+ end.select do |file|
422
+ file.name == ::File.basename(src)
397
423
  end
424
+
425
+ raise "#{src} not found" if file.empty?
426
+
427
+ file.first
398
428
  end
399
429
 
400
- def with_readable(src, opts = 'r', &block)
401
- sftp.file.open(src, opts, &block)
430
+ def mkcommand(rd, wd, file, opts, size_hint: nil)
431
+ env = {}
432
+ cmd = [env, "curl"]
433
+
434
+ cmd << "-u"
435
+ cmd << authn
436
+ cmd << "-o"
437
+ cmd << "-"
438
+ cmd << "-N"
439
+ cmd << url(file)
440
+
441
+ if opts.include?('r')
442
+ cmd << {out: wd}
443
+ end
444
+
445
+ cmd
402
446
  end
403
447
 
404
- def ls(dir)
405
- sftp.dir.entries(dir)
448
+ def with_readable(src, opts = 'r', &block)
449
+ raise "#{src} does not exist" unless exist?(src)
450
+
451
+ sftp_file = sftp_file_from_path(src)
452
+
453
+ mkio(src, opts, size_hint: sftp_file.size, &block)
406
454
  end
407
455
 
408
456
  def exist?(src)
409
- begin
410
- sftp.file.open(src)
411
- rescue Net::SFTP::StatusException
412
- return false
413
- end
414
- return true
457
+ files = ls(::File.dirname(src))
458
+ files.include?(::File.basename(src))
459
+ end
460
+
461
+ def ls(dir)
462
+ dir = dir + "/" unless "/" == dir[-1] # Trailing / makes curl list directory
463
+
464
+ return @dir_listings[dir] if @dir_listings.has_key?(dir)
465
+
466
+ listing = ''
467
+ connection = curl_cmd(dir)
468
+ connection.on_body { |data| listing << data; data.size }
469
+ connection.perform
470
+
471
+ @dir_listings[dir] = listing
472
+
473
+ listing
415
474
  end
416
475
 
417
476
  def stat(src)
418
- sftp.file.open(src).stat
477
+ sftp_file_from_path(src)
419
478
  end
420
479
  end
421
480
 
422
481
  class Mock < Filesystem
423
482
  class MockStat
424
- def initialize
483
+ def initialize(io)
484
+ @io = io
425
485
  end
426
486
 
427
487
  def size
428
- 0
488
+ @io.respond_to?(:length) ? @io.length : 0
429
489
  end
430
490
  end
431
491
 
@@ -499,7 +559,7 @@ module Etna
499
559
  end
500
560
 
501
561
  def stat(src)
502
- @files[src].respond_to?(:stat) ? @files[src].stat : MockStat.new
562
+ @files[src].respond_to?(:stat) ? @files[src].stat : MockStat.new(@files[src])
503
563
  end
504
564
  end
505
565
  end
@@ -0,0 +1,38 @@
1
+ require "net/ssh"
2
+
3
+ module Etna
4
+ class RemoteSSH
5
+ class RemoteSSHError < Exception
6
+ end
7
+
8
+ def initialize(host:, username:, password: nil, port: 22, root:, **args)
9
+ @username = username
10
+ @password = password
11
+ @host = host
12
+ @port = port
13
+ @root = root
14
+ end
15
+
16
+ def ssh
17
+ @ssh ||= Net::SSH.start(@host, @username, password: @password)
18
+ end
19
+
20
+ def mkdir_p(dir)
21
+ output = ssh.exec!("mkdir -p #{dir}")
22
+
23
+ raise RemoteSSHError.new("Unable to mkdir -p, #{output}") unless 0 == output.exitstatus
24
+ end
25
+
26
+ def lftp_get(username:, password:, host:, remote_filename:, &block)
27
+ full_local_path = ::File.join(@root, host, remote_filename)
28
+ full_local_dir = ::File.dirname(full_local_path)
29
+ mkdir_p(full_local_dir)
30
+
31
+ cmd = "lftp sftp://#{username}:#{password}@#{host} -e \"get #{remote_filename} -o #{full_local_path}; bye\""
32
+
33
+ output = ssh.exec!(cmd)
34
+ raise RemoteSSHError.new("LFTP get failure: #{output}") unless 0 == output.exitstatus
35
+ yield remote_filename if block_given?
36
+ end
37
+ end
38
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: etna
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.40
4
+ version: 0.1.41
5
5
  platform: ruby
6
6
  authors:
7
7
  - Saurabh Asthana
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-29 00:00:00.000000000 Z
11
+ date: 2021-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -95,19 +95,33 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: net-sftp
98
+ name: curb
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: 3.0.0
103
+ version: '0'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: 3.0.0
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: net-ssh
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  description: See summary
112
126
  email: Saurabh.Asthana@ucsf.edu
113
127
  executables:
@@ -186,6 +200,7 @@ files:
186
200
  - lib/etna/metrics.rb
187
201
  - lib/etna/multipart_serializable_nested_hash.rb
188
202
  - lib/etna/parse_body.rb
203
+ - lib/etna/remote.rb
189
204
  - lib/etna/route.rb
190
205
  - lib/etna/server.rb
191
206
  - lib/etna/sign_service.rb