Class: DTK::Client::Node

Inherits:
CommandBaseThor show all
Includes:
AssemblyWorkspaceMixin, NodeMixin
Defined in:
lib/commands/thor/node.rb

Constant Summary collapse

GETNETSTATSTRIES =
6
GETNETSTATSSLEEP =
0.5
GETPSTRIES =
6
GETPSSLEEP =
0.5

Constants included from NodeMixin

DTK::Client::NodeMixin::DefaultLoginByOSType

Constants included from AssemblyWorkspaceMixin

AssemblyWorkspaceMixin::REQ_ASSEMBLY_OR_WS_ID

Constants inherited from CommandBaseThor

CommandBaseThor::ALT_IDENTIFIER_SEPARATOR, CommandBaseThor::EXTENDED_TIMEOUT, CommandBaseThor::HIDE_FROM_BASE_CONTEXT, CommandBaseThor::TIME_DIFF

Constants included from CommandHelperMixin

CommandHelperMixin::Loaded

Constants included from ReparseMixin

ReparseMixin::YamlDTKMetaFiles

Constants included from Poller

Poller::PERIOD_WAIT_TIME

Constants inherited from Thor

Thor::HIDE_FROM_BASE_CONTEXT_HELP

Class Method Summary collapse

Instance Method Summary collapse

Methods included from NodeMixin

default_login_user?, #get_node_info_for_ssh_login

Methods included from AssemblyWorkspaceMixin

#action_info_aux, #add_assembly, #assembly_start, #assembly_stop, #cancel_task_aux, #clear_tasks_aux, #converge_aux, #create_attribute_aux, #create_component_aux, #create_node_aux, #create_node_group_aux, #create_workspace_aux, #delete_and_destroy, #delete_and_destroy_aux, #delete_aux, #delete_component_aux, #delete_node_aux, #delete_node_group_aux, #deploy_aux, #destroy_and_reset_nodes_aux, #edit_attributes_aux, #edit_module_aux, #edit_or_create_workflow_aux, #exec_aux, #exec_sync_aux, #execute_ad_hoc_action_aux, #execute_tests_aux, #get_assembly_id, #get_deploy_or_stage_context, #get_name, #get_netstats_aux, #get_ps_aux, #grant_access_aux, #grep_aux, #info_aux, #link_attribute_aux, #link_attributes_aux, #link_components_aux, #link_unlink_components__ret_post_body, #list_actions_aux, #list_ad_hoc_actions_aux, #list_attributes_aux, #list_aux, #list_component_links_aux, #list_components_aux, #list_connections_aux, #list_modules_aux, #list_nodes_aux, #list_remote_module_diffs, #list_ssh_access_aux, #list_tasks_aux, #list_violations_aux, #prepare_for_edit_module, #print_includes_aux, #promote_assembly_aux, #pull_base_component_module_aux, #purge_aux, #push_module_updates_aux, #revoke_access_aux, #set_attribute_aux, #set_default_target_aux, #set_required_attributes_converge_aux, #set_target_aux, #stage_aux, #start_aux, #stop_aux, #tail_aux, #task_action_detail_aw_aux, #task_status_aw_aux, #unlink_components_aux, #unset, #validate_service_instance_node_or_cmp_attrs, #workflow_list_aux

Methods included from AssemblyTemplateMixin

#get_assembly_name, #get_assembly_stage_name, #parse_service_settings

Methods included from ListDiffsMixin

#list_component_module_diffs, #list_diffs_aux, #list_remote_diffs_aux, #print_diffs

Methods inherited from CommandBaseThor

action_on_revalidation_response, basename, create_context_arguments, execute_from_cli, generate_cached_id, get_cached_response, get_identifiers, get_usage_info, #help, #initialize, invalidate_entities, invisible_context_list, list_method_supported?, task_names, tiered_task_names, valid_id?

Methods included from CommandBase

#get, #get_connection, handle_argument_error, #post, #post_file, #rest_url, #rotate_args

Methods included from TaskStatusMixin

#list_task_info_aux, #task_status_aux, #task_status_stream

Methods included from Console

confirmation_prompt, confirmation_prompt_additional_options, confirmation_prompt_multiple_choice, confirmation_prompt_simple, unix_shell, wait_animation

Methods included from CommandHelperMixin

#Helper

Methods included from ReparseMixin

#reparse_aux

Methods included from PushCloneChangesMixin

#push_clone_changes_aux

Methods included from CommandBaseThor::CommonOptionDefs::ClassMixin

#version_method_option

Methods included from Poller

#poller_response, #print_response, #resolve_type

Methods inherited from Thor

get_alternative_identifiers, help, match_help_item_changes, overriden_help, printable_tasks, replace_if_matched!, set_context

Constructor Details

This class inherits a constructor from DTK::Client::CommandBaseThor

Class Method Details

.all_childrenObject



47
48
49
50
# File 'lib/commands/thor/node.rb', line 47

def self.all_children()
  [:component, :attribute]
  # [:node]
end

.extended_contextObject

using extended_context when we want to use autocomplete from other context e.g. we are in assembly/apache context and want to create-component we will use extended context to add component-templates to autocomplete



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/commands/thor/node.rb', line 55

def self.extended_context()
  {
    :context => {
    },
    :command => {
      :add_component => {
        :endpoint => "component_template",
        :url => "component/list",
        :opts => {:subtype=>"template", :ignore => "test_module", :hide_assembly_cmps => "true"}
      },
      :delete_component => {
        :endpoint => "assembly",
        :url => "assembly/info_about",
        :opts => {:subtype=>"instance", :about=>"components"}
      }
    }
  }
end

.multi_context_childrenObject



43
44
45
# File 'lib/commands/thor/node.rb', line 43

def self.multi_context_children()
  [:utils]
end

.override_allowed_methodsObject



99
100
101
102
103
104
105
106
107
108
# File 'lib/commands/thor/node.rb', line 99

def self.override_allowed_methods()
  return DTK::Shell::OverrideTasks.new({
    :command_only => {
      :utils => [
        ['get-netstats',"get-netstats","# Get netstats."],
        ['get-ps',"get-ps [--filter PATTERN]","# Get ps."]
      ]
    }
  })
end

.pretty_print_colsObject



34
35
36
# File 'lib/commands/thor/node.rb', line 34

def self.pretty_print_cols()
  PPColumns.get(:node)
end

.valid_child?(name_of_sub_context) ⇒ Boolean

Returns:

  • (Boolean)


74
75
76
# File 'lib/commands/thor/node.rb', line 74

def self.valid_child?(name_of_sub_context)
  return Node.valid_children().include?(name_of_sub_context.to_sym)
end

.valid_childrenObject



38
39
40
41
# File 'lib/commands/thor/node.rb', line 38

def self.valid_children()
  # [:component, :utils]
  [:utils]
end

.validation_list(context_params) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/commands/thor/node.rb', line 78

def self.validation_list(context_params)
  assembly_id, workspace_id = context_params.retrieve_arguments([:service_id, :workspace_id])

  if (assembly_id || workspace_id)
    # if assebmly_id is present we're loading nodes filtered by assembly_id
    post_body = {
      :assembly_id => assembly_id||workspace_id,
      :subtype     => 'instance',
      :about       => 'nodes',
      :filter      => nil
    }

    response = get_cached_response(:service_node, "assembly/info_about", post_body)
  else
    # otherwise, load all nodes
    response = get_cached_response(:node, "node/list", nil)
  end

  return response
end

Instance Method Details

#add_component(context_params) ⇒ Object



238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/commands/thor/node.rb', line 238

def add_component(context_params)
  node_id,component_template_id = context_params.retrieve_arguments([:node_id!, :option_1!],method_argument_names)
  post_body = {
    :node_id => node_id,
    :component_template_name => component_template_id
  }
  post_body.merge!(:version => options[:version]) if options[:version]

  response = post rest_url("node/add_component"), post_body
  return response unless response.ok?

  @@invalidate_map << :node
  return response
end

#cancel_task(context_params) ⇒ Object



314
315
316
317
# File 'lib/commands/thor/node.rb', line 314

def cancel_task(context_params)
  task_id = context_params.retrieve_arguments([:option_1!],method_argument_names)
  cancel_task_aux(task_id)
end

#converge(context_params) ⇒ Object



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
# File 'lib/commands/thor/node.rb', line 274

def converge(context_params)
  node_id = context_params.retrieve_arguments([:node_id!],method_argument_names)
  # create task
  post_body = {
    :node_id => node_id
  }

  response = post rest_url("node/find_violations"), post_body
  return response unless response.ok?
  if response.data and response.data.size > 0
    #TODO: may not directly print here; isntead use a lower level fn
    error_message = "The following violations were found; they must be corrected before the node can be converged"
    OsUtil.print(error_message, :red)
    return response.render_table(:violation)
  end

  post_body.merge!(:commit_msg => options.commit_msg) if options.commit_msg

  response = post rest_url("node/create_task"), post_body
  return response unless response.ok?

  # execute task
  task_id = response.data(:task_id)
  post rest_url("task/execute"), "task_id" => task_id
end

#delete_component(context_params) ⇒ Object



255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/commands/thor/node.rb', line 255

def delete_component(context_params)
  node_id,component_id = context_params.retrieve_arguments([:node_id!, :option_1!],method_argument_names)

  unless options.force?
    return unless Console.confirmation_prompt("Are you sure you want to delete component '#{component_id}'"+'?')
  end

  post_body = {
    :node_id => node_id,
    :component_id => component_id
  }
  post rest_url("node/delete_component"), post_body
end

#destroy(context_params) ⇒ Object



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/commands/thor/node.rb', line 322

def destroy(context_params)
  node_id = context_params.retrieve_arguments([:option_1!],method_argument_names)
  post_body = {
    :node_id => node_id
  }
  unless options.force?
    # Ask user if really want to delete and destroy, if not then return to dtk-shell without deleting
    return unless Console.confirmation_prompt("Are you sure you want to destroy and delete node '#{node_id}'"+"?")
  end

  response = post rest_url("node/destroy_and_delete"), post_body
  @@invalidate_map << :node

  return response
end

#get_netstats(context_params) ⇒ Object



364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
# File 'lib/commands/thor/node.rb', line 364

def get_netstats(context_params)
  node_id = context_params.retrieve_arguments([:node_id!],method_argument_names)

  post_body = {
    :node_id => node_id
  }

  response = post(rest_url("node/initiate_get_netstats"), post_body)
  return response unless response.ok?

  action_results_id = response.data(:action_results_id)
  end_loop, response, count, ret_only_if_complete = false, nil, 0, true

  until end_loop do
    post_body = {
      :action_results_id => action_results_id,
      :return_only_if_complete => ret_only_if_complete,
      :disable_post_processing => false
    }
    response = post(rest_url("node/get_action_results"),post_body)
    count += 1
    if count > GETNETSTATSTRIES or response.data(:is_complete)
      end_loop = true
    else
      #last time in loop return whetever is teher
      if count == GETNETSTATSTRIES
        ret_only_if_complete = false
      end
      sleep GETNETSTATSSLEEP
    end
  end

  #TODO: needed better way to render what is one of teh feileds which is any array (:results in this case)
  response.set_data(*response.data(:results))
  response.render_table(:netstat_data)
end

#get_ps(context_params) ⇒ Object



405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
# File 'lib/commands/thor/node.rb', line 405

def get_ps(context_params)
  node_id, filter_pattern = context_params.retrieve_arguments([:node_id!, :option_1],method_argument_names)

  post_body = {
    :node_id => node_id
  }

  response = post(rest_url("node/initiate_get_ps"), post_body)
  return response unless response.ok?

  action_results_id = response.data(:action_results_id)
  end_loop, response, count, ret_only_if_complete = false, nil, 0, true

  until end_loop do
    post_body = {
      :action_results_id => action_results_id,
      :return_only_if_complete => ret_only_if_complete,
      :disable_post_processing => true
    }
    response = post(rest_url("node/get_action_results"),post_body)
    count += 1
    if count > GETPSTRIES or response.data(:is_complete)
      end_loop = true
    else
      #last time in loop return whetever is teher
      if count == GETPSTRIES
        ret_only_if_complete = false
      end
      sleep GETPSSLEEP
    end
  end

  response_processed = response.data['results'].values.flatten
  response_processed.reject! {|r| !r.to_s.include?(filter_pattern)} unless filter_pattern.nil?

  #TODO: needed better way to render what is one of teh feileds which is any array (:results in this case)
  response.set_data(*response_processed)
  response.render_table(:ps_data)
end

#info(context_params) ⇒ Object



111
112
113
114
115
116
117
118
119
# File 'lib/commands/thor/node.rb', line 111

def info(context_params)
  node_id = context_params.retrieve_arguments([:node_id!],method_argument_names)
  post_body = {
    :node_id => node_id,
    :subtype => 'instance',
  }

   post rest_url("node/info"), post_body
end

#list(context_params) ⇒ Object



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
# File 'lib/commands/thor/node.rb', line 188

def list(context_params)
  node_id, about = context_params.retrieve_arguments([:node_id,:option_1],method_argument_names)

  if node_id.nil?
    response = post rest_url("node/list")

    response.render_table(:node) unless options.list?
    return response
  else

    post_body = {
      :node_id => node_id,
      :subtype => 'instance',
      :about   => about
    }

    case about
      when "components"
        data_type = :component
      when "attributes"
        data_type = :attribute
      else
        raise_validation_error_method_usage('list')
    end

    response = post rest_url("node/info_about"), post_body
    return response.render_table(data_type)
  end
end

#list_attributes(context_params) ⇒ Object



181
182
183
184
# File 'lib/commands/thor/node.rb', line 181

def list_attributes(context_params)
  context_params.method_arguments = ["attributes"]
  list(context_params)
end

#list_components(context_params) ⇒ Object



174
175
176
177
# File 'lib/commands/thor/node.rb', line 174

def list_components(context_params)
  context_params.method_arguments = ["components"]
  list(context_params)
end

#list_task_info(context_params) ⇒ Object



308
309
310
311
# File 'lib/commands/thor/node.rb', line 308

def list_task_info(context_params)
  node_id = context_params.retrieve_arguments([:node_id!],method_argument_names)
  list_task_info_aux("node", node_id)
end

#op_status(context_params) ⇒ Object



339
340
341
342
# File 'lib/commands/thor/node.rb', line 339

def op_status(context_params)
  node_id = context_params.retrieve_arguments([:node_id!],method_argument_names)
  post rest_url("node/get_op_status"), :node_id => node_id
end

#set(context_params) ⇒ Object



219
220
221
222
223
224
225
226
227
# File 'lib/commands/thor/node.rb', line 219

def set(context_params)
  node_id, attr_id, value = context_params.retrieve_arguments([:node_id!, :option_1!, :option_2!],method_argument_names)
  post_body = {
    :node_id => node_id,
    :pattern => attr_id,
    :value => value
  }
  post rest_url("node/set_attributes"), post_body
end

#set_required_attributes(context_params) ⇒ Object



230
231
232
233
# File 'lib/commands/thor/node.rb', line 230

def set_required_attributes(context_params)
  node_id = context_params.retrieve_arguments([:node_id!],method_argument_names)
  set_required_attributes_aux(node_id,:node)
end

#ssh(context_params) ⇒ Object



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
# File 'lib/commands/thor/node.rb', line 123

def ssh(context_params)
  if OsUtil.is_windows?
    puts "[NOTICE] SSH functionality is currenly not supported on Windows."
    return
  end

  node_id,  = context_params.retrieve_arguments([:node_id!,:option_1],method_argument_names)

  if identity_file_location = options['identity-file']
    unless File.exists?(identity_file_location)
      raise DtkError, "Not able to find identity file, '#{identity_file_location}'"
    end
  elsif default_identity_file = OsUtil.dtk_identity_file_location()
    if File.exists?(default_identity_file)
      identity_file_location = default_identity_file
    end
  end

  response = (node_id, context_params)
  return response unless response.ok?

  unless public_dns = response.data(:public_dns)
    raise DtkError, "Not able to resolve instance address, has instance been stopped?"
  end
  
  unless  ||= response.data(:default_login_user)
    raise DtkError, "Retry command with a specfic login user (a default login user could not be computed)"
  end

  connection_string = "#{}@#{public_dns}"

  ssh_command = 
    if identity_file_location
      # provided PEM key
      "ssh -o \"StrictHostKeyChecking no\" -o \"UserKnownHostsFile /dev/null\" -i #{identity_file_location} #{connection_string}"
    elsif SSHUtil.ssh_reachable?(, public_dns)
      # it has PUB key access
      "ssh -o \"StrictHostKeyChecking no\" -o \"UserKnownHostsFile /dev/null\" #{connection_string}"
    end

  unless ssh_command
    raise DtkError, "No public key access or PEM provided, please grant access or provide valid PEM key" 
  end
  
  OsUtil.print("You are entering SSH terminal (#{connection_string}) ...", :yellow)
  Kernel.system(ssh_command)
  OsUtil.print("You are leaving SSH terminal, and returning to DTK Shell ...", :yellow)
end

#start(context_params) ⇒ Object



345
346
347
348
349
350
351
# File 'lib/commands/thor/node.rb', line 345

def start(context_params)
  node_id = context_params.retrieve_arguments([:node_id!],method_argument_names)
  #TODO: Rich: took this out; think it is a bug
  #assembly_id,node_id = get_assembly_and_node_id(context_params)

  node_start(node_id)
end

#stop(context_params) ⇒ Object



354
355
356
357
358
359
360
361
# File 'lib/commands/thor/node.rb', line 354

def stop(context_params)
  node_id = context_params.retrieve_arguments([:node_id!],method_argument_names)
  # Retrieving assembly_id to stop a node.. TODO create server side method that takes only node id
  #TODO: Rich: took this out; think it is a bug
  #assembly_id, node_id = get_assembly_and_node_id(context_params)

  node_stop(node_id)
end

#task_status(context_params) ⇒ Object



302
303
304
305
# File 'lib/commands/thor/node.rb', line 302

def task_status(context_params)
  node_id = context_params.retrieve_arguments([:node_id!],method_argument_names)
  task_status_aux(node_id,:node,:wait => options.wait?)
end