Class: Aspera::Cli::Plugins::Server

Inherits:
BasicAuthPlugin show all
Defined in:
lib/aspera/cli/plugins/server.rb

Overview

implement basic remote access with FASP/SSH

Defined Under Namespace

Classes: LocalExecutor

Constant Summary collapse

ACTIONS =
[:nagios,:nodeadmin,:userdata,:configurator,:ctl,:download,:upload,:browse,:delete,:rename].concat(Aspera::AsCmd::OPERATIONS)

Constants inherited from Aspera::Cli::Plugin

Aspera::Cli::Plugin::ALL_OPS, Aspera::Cli::Plugin::GLOBAL_OPS, Aspera::Cli::Plugin::INSTANCE_OPS

Instance Method Summary collapse

Methods inherited from BasicAuthPlugin

#basic_auth_api

Methods inherited from Aspera::Cli::Plugin

#config, #entity_action, #entity_command, #format, #options, #transfer

Constructor Details

#initialize(env) ⇒ Server

Returns a new instance of Server.



18
19
20
21
22
23
24
25
26
# File 'lib/aspera/cli/plugins/server.rb', line 18

def initialize(env)
  super(env)
  self.options.add_opt_simple(:ssh_keys,'ssh key path list (Array or single)')
  self.options.add_opt_simple(:ssh_options,'ssh options (Hash)')
  self.options.add_opt_simple(:cmd_prefix,'prefix to add for as cmd execution, e.g. sudo or /opt/aspera/bin ')
  self.options.set_option(:ssh_keys,[])
  self.options.set_option(:ssh_options,{})
  self.options.parse_options!
end

Instance Method Details

#asctl_parse(text) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/aspera/cli/plugins/server.rb', line 36

def asctl_parse(text)
  r=/:\s*/
  return text.split("\n").map do |line|
    # console
    line.gsub!(/(SessionDataCollector)/,'\1 ')
    # orchestrator
    line.gsub!(/ with pid:.*/,'')
    line.gsub!(/ is /,': ')
    x=line.split(r)
    next unless x.length.eql?(2)
    y={'process'=>x.first,'state'=>x.last}
    # console
    y['state'].gsub!(/\.+$/,'')
    # console
    y['process'].gsub!(/^.+::/,'')
    # faspex
    y['process'].gsub!(/^Faspex /,'')
    # faspex
    y['process'].gsub!(/ Background/,'')
    y['process'].gsub!(/serving orchestrator on port /,'')
    # console
    r=/\s+/ if y['process'].eql?('Console')
    # orchestrator
    y['process'].gsub!(/^  -> /,'')
    y['process'].gsub!(/ Process/,'')
    y
  end.select{|i|!i.nil?}
end

#execute_actionObject



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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
# File 'lib/aspera/cli/plugins/server.rb', line 67

def execute_action
  server_uri=URI.parse(self.options.get_option(:url,:mandatory))
  Log.log.debug("URI : #{server_uri}, port=#{server_uri.port}, scheme:#{server_uri.scheme}")
  shell_executor=nil
  case server_uri.scheme
  when 'ssh'
    server_transfer_spec={
      'remote_host'=>server_uri.hostname,
      'remote_user'=>self.options.get_option(:username,:mandatory),
    }
    ssh_options=self.options.get_option(:ssh_options,:optional)
    raise 'expecting a Hash for ssh_options' unless ssh_options.is_a?(Hash)
    if !server_uri.port.nil?
      ssh_options[:port]=server_uri.port
      server_transfer_spec['ssh_port']=server_uri.port
    end
    cred_set=false
    password=self.options.get_option(:password,:optional)
    if !password.nil?
      ssh_options[:password]=password
      server_transfer_spec['remote_password']=password
      cred_set=true
    end
    ssh_keys=self.options.get_option(:ssh_keys,:optional)
    if !ssh_keys.nil?
      raise 'expecting single value or array for ssh_keys' unless ssh_keys.is_a?(Array) or ssh_keys.is_a?(String)
      ssh_keys=[ssh_keys] if ssh_keys.is_a?(String)
      ssh_keys.map!{|p|File.expand_path(p)}
      Log.log.debug("ssh keys=#{ssh_keys}")
      ssh_options[:keys]=ssh_keys
      server_transfer_spec['EX_ssh_key_paths']=ssh_keys
      ssh_keys.each do |k|
        Log.log.warn("no such key file: #{k}") unless File.exist?(k)
      end
      cred_set=true
    end
    raise 'either password or key must be provided' if !cred_set
    shell_executor=Ssh.new(server_transfer_spec['remote_host'],server_transfer_spec['remote_user'],ssh_options)
  when 'local'
    shell_executor=LocalExecutor.new
  else
    raise CliError,'Only ssh scheme is supported in url' if !server_uri.scheme.eql?('ssh')
  end

  # get command and set aliases
  command=self.options.get_next_command(ACTIONS)
  command=:ls if command.eql?(:browse)
  command=:rm if command.eql?(:delete)
  command=:mv if command.eql?(:rename)
  case command
  when :nagios
    nagios=Nagios.new
    command_nagios=self.options.get_next_command([ :app_services, :transfer ])
    case command_nagios
    when :app_services
      # will not work with aspshell, requires Linux/bash
      procs=shell_executor.execute('ps -A -o comm').split("\n")
      Log.log.debug("found: #{procs}")
      ['asperanoded','asperaredisd'].each do |name|
        nagios.add_critical('general',"missing process #{name}") unless procs.include?(name)
      end
      nagios.add_ok('daemons','ok') if nagios.data.empty?
      return nagios.result
    when :transfer
      file = Tempfile.new('transfer_test')
      filepath=file.path
      file.write("This is a test file for transfer test")
      file.close
      probe_ts=server_transfer_spec.merge({
        'direction'     => 'send',
        'cookie'        => 'aspera.sync', # hide in console
        'resume_policy' => 'none',
        'paths'         => [{'source'=>filepath,'destination'=>'.fasping'}]
      })
      statuses=self.transfer.start(probe_ts,{:src=>:direct})
      file.unlink
      if TransferAgent.session_status(statuses).eql?(:success)
        nagios.add_ok('transfer','ok')
      else
        nagios.add_critical('transfer',statuses.select{|i|!i.eql?(:success)}.first.to_s)
      end
    else raise "ERROR"
    end
    return nagios.result
  when :nodeadmin,:userdata,:configurator,:ctl
    realcmd='as'+command.to_s
    prefix=self.options.get_option(:cmd_prefix,:optional)
    if !prefix.nil?
      realcmd="#{prefix}#{realcmd}"
    end
    args = self.options.get_next_argument("#{realcmd} arguments",:multiple)
    result=shell_executor.execute(args.unshift(realcmd))
    case command
    when :ctl
      return {:type=>:object_list,:data=>asctl_parse(result)}#
    when :configurator
      lines=result.split("\n")
      Log.log.debug(`type asconfigurator`)
      result=lines
      if lines.first.eql?('success')
        lines.shift
        result={}
        lines.each do |line|
          Log.log.debug("#{line}")
          data=line.split(',').map{|i|i.gsub(/^"/,'').gsub(/"$/,'')}.map{|i|case i;when'AS_NULL';nil;when'true';true;when'false';false;else i;end}
          Log.log.debug("#{data}")
          section=data.shift
          datapart=result[section]||={}
          if section.eql?('user')
            name=data.shift
            datapart=datapart[name]||={}
          end
          datapart=datapart[data.shift]={}
          datapart['default']=data.pop
          datapart['value']=data.pop
        end
        return {:type=>:single_object,:data=>result,:fields=>['section','name','value','default'],:option_expand_last=>true}
      end
    end
    return Main.result_status(result)
  when :upload
    return Main.result_transfer(self.transfer.start(server_transfer_spec.merge('direction'=>'send'),{:src=>:direct}))
  when :download
    return Main.result_transfer(self.transfer.start(server_transfer_spec.merge('direction'=>'receive'),{:src=>:direct}))
  when *Aspera::AsCmd::OPERATIONS
    args=self.options.get_next_argument('ascmd command arguments',:multiple,:optional)
    ascmd=Aspera::AsCmd.new(shell_executor)
    begin
      result=ascmd.send(:execute_single,command,args)
      case command
      when :mkdir;  return Main.result_success
      when :mv;     return Main.result_success
      when :cp;     return Main.result_success
      when :rm;     return Main.result_success
      when :ls;     return {:type=>:object_list,:data=>key_symb_to_str_list(result),:fields=>['zmode','zuid','zgid','size','mtime','name']}
      when :info;   return {:type=>:single_object,:data=>key_symb_to_str_single(result)}
      when :df;     return {:type=>:object_list,:data=>key_symb_to_str_list(result)}
      when :du;     return {:type=>:single_object,:data=>key_symb_to_str_single(result)}
      when :md5sum; return {:type=>:single_object,:data=>key_symb_to_str_single(result)}
      end
    rescue Aspera::AsCmd::Error => e
      raise CliBadArgument,e.extended_message
    end
  else raise "internal error: unexpected action"
  end
end

#key_symb_to_str_list(source) ⇒ Object



32
33
34
# File 'lib/aspera/cli/plugins/server.rb', line 32

def key_symb_to_str_list(source)
  return source.map{|o| key_symb_to_str_single(o)}
end

#key_symb_to_str_single(source) ⇒ Object



28
29
30
# File 'lib/aspera/cli/plugins/server.rb', line 28

def key_symb_to_str_single(source)
  return source.inject({}){|memo,(k,v)| memo[k.to_s] = v; memo}
end