Class: Aspera::NodeSimulatorServlet

Inherits:
WEBrick::HTTPServlet::AbstractServlet
  • Object
show all
Defined in:
lib/aspera/node_simulator.rb

Overview

this class answers the Faspex /send API and creates a package on Aspera on Cloud a new instance is created for each request

Constant Summary collapse

PATH_TRANSFERS =
'/ops/transfers'
PATH_ONE_TRANSFER =
%r{/ops/transfers/(.+)$}
PATH_BROWSE =
'/files/browse'

Instance Method Summary collapse

Constructor Details

#initialize(server, credentials, simulator) ⇒ NodeSimulatorServlet



166
167
168
169
170
# File 'lib/aspera/node_simulator.rb', line 166

def initialize(server, credentials, simulator)
  super(server)
  @credentials = credentials
  @simulator = simulator
end

Instance Method Details

#do_GET(request, response) ⇒ Object



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/aspera/node_simulator.rb', line 248

def do_GET(request, response)
  case request.path
  when '/info'
    info = Ascp::Installation.instance.ascp_info
    set_json_response(request, response, {
      application:                           'node',
      current_time:                          Time.now.utc.iso8601(0),
      version:                               info['sdk_ascp_version'].gsub(/ .*$/, ''),
      license_expiration_date:               info['expiration_date'],
      license_max_rate:                      info['maximum_bandwidth'],
      os:                                    %x(uname -srv).chomp,
      aej_status:                            'disconnected',
      async_reporting:                       'no',
      transfer_activity_reporting:           'no',
      transfer_user:                         'xfer',
      docroot:                               'file:////data/aoc/eudemo-sedemo',
      node_id:                               '2bbdcc39-f789-4d47-8163-6767fc14f421',
      cluster_id:                            '6dae2844-d1a9-47a5-916d-9b3eac3ea466',
      acls:                                  ['impersonation'],
      access_key_configuration_capabilities: {
        transfer: %w[
          cipher
          policy
          target_rate_cap_kbps
          target_rate_kbps
          preserve_timestamps
          content_protection_secret
          aggressiveness
          token_encryption_key
          byok_enabled
          bandwidth_flow_network_rc_module
          file_checksum_type],
        server:   %w[
          activity_event_logging
          activity_file_event_logging
          recursive_counts
          aej_logging
          wss_enabled
          activity_transfer_ignore_skipped_files
          activity_files_max
          access_key_credentials_encryption_type
          discovery
          auto_delete
          allow
          deny]
      },
      capabilities:                          [
        {name:  'sync', value: true},
        {name:  'watchfolder', value: true},
        {name:  'symbolic_links', value: true},
        {name:  'move_file', value: true},
        {name:  'move_directory', value: true},
        {name:  'filelock', value: false},
        {name:  'ssh_fingerprint', value: false},
        {name:  'aej_version', value: '1.0'},
        {name:  'page', value: true},
        {name:  'file_id_version', value: '2.0'},
        {name:  'auto_delete', value: false}],
      settings:                              [
        {name:  'content_protection_required', value: false},
        {name:  'content_protection_strong_pass_required', value: false},
        {name:  'filelock_restriction', value: 'none'},
        {name:  'ssh_fingerprint', value: nil},
        {name:  'wss_enabled', value: false},
        {name:  'wss_port', value: 443}
      ]})
  when PATH_TRANSFERS
    set_json_response(request, response, @simulator.all_sessions)
  when PATH_ONE_TRANSFER
    job_id = request.path.match(PATH_ONE_TRANSFER)[1]
    set_json_response(request, response, @simulator.job_to_transfer(job_id))
  else
    set_json_response(request, response, [{error: 'Unknown request'}], code: 400)
  end
end

#do_POST(request, response) ⇒ Object



233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/aspera/node_simulator.rb', line 233

def do_POST(request, response)
  case request.path
  when PATH_TRANSFERS
    job_id = @simulator.start(JSON.parse(request.body))
    sleep(0.5)
    set_json_response(request, response, @simulator.job_to_transfer(job_id))
  when PATH_BROWSE
    req = JSON.parse(request.body)
    # req['count']
    set_json_response(request, response, folder_to_structure(req['path']))
  else
    set_json_response(request, response, [{error: 'Bad request'}], code: 400)
  end
end

#folder_to_structure(folder_path) ⇒ Object



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/aspera/node_simulator.rb', line 175

def folder_to_structure(folder_path)
  raise "Path does not exist or is not a directory: #{folder_path}" unless Dir.exist?(folder_path)

  # Build self structure
  folder_stat = File.stat(folder_path)
  structure = {
    'self'  => {
      'path'        => folder_path,
      'basename'    => File.basename(folder_path),
      'type'        => 'directory',
      'size'        => folder_stat.size,
      'mtime'       => folder_stat.mtime.utc.iso8601,
      'permissions' => [
        { 'name' => 'view' },
        { 'name' => 'edit' },
        { 'name' => 'delete' }
      ]
    },
    'items' => []
  }

  # Iterate over folder contents
  Dir.foreach(folder_path) do |entry|
    next if entry == '.' || entry == '..' # Skip current and parent directory

    item_path = File.join(folder_path, entry)
    item_type = File.ftype(item_path) rescue 'unknown' # Get the type of file
    item_stat = File.lstat(item_path) # Use lstat to handle symbolic links correctly

    item = {
      'path'        => item_path,
      'basename'    => entry,
      'type'        => item_type,
      'size'        => item_stat.size,
      'mtime'       => item_stat.mtime.utc.iso8601,
      'permissions' => [
        { 'name' => 'view' },
        { 'name' => 'edit' },
        { 'name' => 'delete' }
      ]
    }

    # Add additional details for specific types
    case item_type
    when 'file'
      item['partial_file'] = false
    when 'link'
      item['target'] = File.readlink(item_path) rescue nil # Add the target of the symlink
    when 'unknown'
      item['note'] = 'File type could not be determined'
    end

    structure['items'] << item
  end

  structure
end

#set_json_response(request, response, json, code: 200) ⇒ Object



324
325
326
327
328
329
# File 'lib/aspera/node_simulator.rb', line 324

def set_json_response(request, response, json, code: 200)
  response.status = code
  response['Content-Type'] = 'application/json'
  response.body = json.to_json
  Log.log.trace1{Log.dump("response for #{request.request_method} #{request.path}", json)}
end