Class: Omnibus::Ctl
- Inherits:
-
Object
- Object
- Omnibus::Ctl
- Defined in:
- lib/omnibus-ctl.rb,
lib/omnibus-ctl/version.rb
Constant Summary collapse
- SV_COMMAND_NAMES =
%w{status up down once pause cont hup alarm int quit term kill start stop restart shutdown force-stop force-reload force-restart force-shutdown check usr1 usr2}.freeze
- VERSION =
"0.6.13".freeze
Instance Attribute Summary collapse
-
#backup_dir ⇒ Object
readonly
Returns the value of attribute backup_dir.
-
#base_path ⇒ Object
Returns the value of attribute base_path.
-
#category_command_map ⇒ Object
Returns the value of attribute category_command_map.
-
#command_map ⇒ Object
Returns the value of attribute command_map.
-
#data_path ⇒ Object
Returns the value of attribute data_path.
-
#display_name ⇒ Object
Returns the value of attribute display_name.
-
#etc_path ⇒ Object
Returns the value of attribute etc_path.
-
#exe_name ⇒ Object
readonly
Returns the value of attribute exe_name.
-
#fh_output ⇒ Object
Returns the value of attribute fh_output.
-
#kill_users ⇒ Object
Returns the value of attribute kill_users.
-
#log_exclude ⇒ Object
Returns the value of attribute log_exclude.
-
#log_path ⇒ Object
Returns the value of attribute log_path.
-
#log_path_exclude ⇒ Object
Returns the value of attribute log_path_exclude.
-
#name ⇒ Object
Returns the value of attribute name.
-
#service_path ⇒ Object
Returns the value of attribute service_path.
-
#sv_path ⇒ Object
Returns the value of attribute sv_path.
-
#verbose ⇒ Object
Returns the value of attribute verbose.
Class Method Summary collapse
Instance Method Summary collapse
- #add_command(name, description, arity = 1, &block) ⇒ Object
- #add_command_under_category(name, category, description, arity = 1, &block) ⇒ Object
- #add_global_pre_hook(name, &block) ⇒ Object
- #ask_license_acceptance ⇒ Object
- #check_license_acceptance(override_accept = false) ⇒ Object
- #cleanse(*args) ⇒ Object
-
#cleanse_post_hook(*args) ⇒ Object
Data cleanup requirements for external services aren’t met by the standard ‘nuke /var/opt’ behavior - this hook allows each service to perform its own ‘cleanse’ operations.
- #cleanup_procs_and_nuke(filestr, calling_method = nil) ⇒ Object
-
#command_post_hook(*args) ⇒ Object
Executes after successful completion of a command If a post-hook provides a numeric return code, it will replace the return/exit of the original command.
-
#command_pre_hook(*args) ⇒ Object
If a command has a pre-hook defined we will run it.
- #error_external_service(command, service) ⇒ Object
- #exit!(code) ⇒ Object
-
#external_services ⇒ Object
Helper function that returns the hash of config hashes that have the key ‘external’ : true in the running config.
- #format_multiline_message(indent, message) ⇒ Object
-
#get_all_commands_hash ⇒ Object
merges category_command_map and command_map, removing categories.
- #get_all_services ⇒ Object
- #get_all_services_files ⇒ Object
- #get_pgrp_from_pid(pid) ⇒ Object
- #get_pids_from_pgrp(pgrp) ⇒ Object
-
#global_service_command_permitted(sv_cmd, service_name) ⇒ Object
if we’re running a global service command (like p-c-c status) across all of the services, there are certain cases where we want to prevent services files that exist in the service directory from being activated.
- #graceful_kill(*args) ⇒ Object
- #help(*args) ⇒ Object
-
#hidden_services ⇒ Object
hidden services are configured via the attributes file in the main omnibus cookbook.
-
#initialize(name, merge_service_commands = true, disp_name = nil) ⇒ Ctl
constructor
A new instance of Ctl.
- #is_integer?(string) ⇒ Boolean
-
#is_option?(arg) ⇒ Boolean
If it begins with a ‘-’, it is an option.
- #load_file(filepath) ⇒ Object
- #load_files(path) ⇒ Object
- #log(msg) ⇒ Object
- #log_external_service_header ⇒ Object
- #log_internal_service_header ⇒ Object
-
#package_name ⇒ Object
translate the name from the config to the package name.
-
#parse_options(args) ⇒ Object
Set global options and remove them from the args list we pass into commands.
- #project_license_path ⇒ Object
- #reconfigure(*args) ⇒ Object
- #remove_old_node_state ⇒ Object
-
#removed_services ⇒ Object
removed services are configured via the attributes file in the main omnibus cookbook.
-
#retrieve_command(command_to_run) ⇒ Object
retrieves the commmand from either the command_map or the category_command_map, if the command is not found return nil.
-
#run(args) ⇒ Object
Previously this would exit immediately with the provided exit code; however this would prevent post-run hooks from continuing Instead, we’ll just track whether a an exit was requested and use that to determine how we exit from ‘run’.
- #run_chef(attr_location, args = "") ⇒ Object
- #run_command(command) ⇒ Object
- #run_global_pre_hooks ⇒ Object
- #run_sv_command(sv_cmd, service = nil) ⇒ Object
-
#run_sv_command_for_service(sv_cmd, service_name) ⇒ Object
run an sv command for a specific service name.
-
#running_config ⇒ Object
returns nil when chef-server-running.json does not exist.
-
#running_package_config ⇒ Object
Gives package config from the running_config.
-
#running_service_config(service) ⇒ Object
This returns running_config[service].
- #scary_cleanse_warning(*args) ⇒ Object
- #service_commands? ⇒ Boolean
- #service_enabled?(service_name) ⇒ Boolean
-
#service_external?(service) ⇒ Boolean
Helper function that returns true if an external service entry exists for the named service.
- #service_list(*args) ⇒ Object
-
#service_list_post_hook ⇒ Object
Capture external services in the output list as well.
-
#service_list_pre_hook ⇒ Object
Add some output headers if we have external services enabled.
- #show_config(*args) ⇒ Object
- #sigkill_pgrp(pgrp) ⇒ Object
-
#status_post_hook(service = nil) ⇒ Object
Status gets its own hook because each externalized service will have its own things to do in order to report status.
-
#status_pre_hook(service = nil) ⇒ Object
If we’re listing status for all services and have external services to show, we’ll include an output header to show that we’re reporting internal services.
- #tail(*args) ⇒ Object
- #to_method_name(name) ⇒ Object
- #uninstall(*args) ⇒ Object
Constructor Details
#initialize(name, merge_service_commands = true, disp_name = nil) ⇒ Ctl
Returns a new instance of Ctl.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 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 |
# File 'lib/omnibus-ctl.rb', line 41 def initialize(name, merge_service_commands = true, disp_name = nil) @name = name @service_commands = merge_service_commands @display_name = disp_name || name @base_path = "/opt/#{name}" @sv_path = File.join(@base_path, "sv") @service_path = File.join(@base_path, "service") @log_path = "/var/log/#{name}" @data_path = "/var/opt/#{name}" @etc_path = "/etc/#{name}" @log_exclude = "(config|lock|@|bz2|gz|gzip|tbz2|tgz|txz|xz|zip)" @log_path_exclude = ["*/sasl/*"] @fh_output = STDOUT @kill_users = [] @verbose = false @quiet = false @exe_name = File.basename($0) @force_exit = false @global_pre_hooks = {} # TODO(ssd) 2017-03-28: Set SVDIR explicitly. Once we fix a bug # in our debian support, where we rely on system-installed # runit, we can likely change this back to ENV.delete("SVDIR") ENV["SVDIR"] = service_path # backwards compat command map that does not have categories @command_map = {} # categoired commands that we want by default @category_command_map = { "general" => { "show-config" => { desc: "Show the configuration that would be generated by reconfigure.", arity: 1, }, "reconfigure" => { desc: "Reconfigure the application.", arity: 2, }, "cleanse" => { desc: "Delete *all* #{display_name} data, and start from scratch.", arity: 2, }, "uninstall" => { arity: 1, desc: "Kill all processes and uninstall the process supervisor (data will be preserved).", }, "help" => { arity: 1, desc: "Print this help message.", }, }, } service_command_map = { "service-management" => { "service-list" => { arity: 1, desc: "List all the services (enabled services appear with a *.)", }, "status" => { desc: "Show the status of all the services.", arity: 2, }, "tail" => { desc: "Watch the service logs of all enabled services.", arity: 2, }, "start" => { desc: "Start services if they are down, and restart them if they stop.", arity: 2, }, "stop" => { desc: "Stop the services, and do not restart them.", arity: 2, }, "restart" => { desc: "Stop the services if they are running, then start them again.", arity: 2, }, "once" => { desc: "Start the services if they are down. Do not restart them if they stop.", arity: 2, }, "hup" => { desc: "Send the services a HUP.", arity: 2, }, "term" => { desc: "Send the services a TERM.", arity: 2, }, "int" => { desc: "Send the services an INT.", arity: 2, }, "kill" => { desc: "Send the services a KILL.", arity: 2, }, "graceful-kill" => { desc: "Attempt a graceful stop, then SIGKILL the entire process group.", arity: 2, }, "usr1" => { desc: "Send the services a USR1.", arity: 2, }, "usr2" => { desc: "Send the services a USR2.", arity: 2, }, }, } @category_command_map.merge!(service_command_map) if service_commands? end |
Instance Attribute Details
#backup_dir ⇒ Object (readonly)
Returns the value of attribute backup_dir.
39 40 41 |
# File 'lib/omnibus-ctl.rb', line 39 def backup_dir @backup_dir end |
#base_path ⇒ Object
Returns the value of attribute base_path.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def base_path @base_path end |
#category_command_map ⇒ Object
Returns the value of attribute category_command_map.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def category_command_map @category_command_map end |
#command_map ⇒ Object
Returns the value of attribute command_map.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def command_map @command_map end |
#data_path ⇒ Object
Returns the value of attribute data_path.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def data_path @data_path end |
#display_name ⇒ Object
Returns the value of attribute display_name.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def display_name @display_name end |
#etc_path ⇒ Object
Returns the value of attribute etc_path.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def etc_path @etc_path end |
#exe_name ⇒ Object (readonly)
Returns the value of attribute exe_name.
39 40 41 |
# File 'lib/omnibus-ctl.rb', line 39 def exe_name @exe_name end |
#fh_output ⇒ Object
Returns the value of attribute fh_output.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def fh_output @fh_output end |
#kill_users ⇒ Object
Returns the value of attribute kill_users.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def kill_users @kill_users end |
#log_exclude ⇒ Object
Returns the value of attribute log_exclude.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def log_exclude @log_exclude end |
#log_path ⇒ Object
Returns the value of attribute log_path.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def log_path @log_path end |
#log_path_exclude ⇒ Object
Returns the value of attribute log_path_exclude.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def log_path_exclude @log_path_exclude end |
#name ⇒ Object
Returns the value of attribute name.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def name @name end |
#service_path ⇒ Object
Returns the value of attribute service_path.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def service_path @service_path end |
#sv_path ⇒ Object
Returns the value of attribute sv_path.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def sv_path @sv_path end |
#verbose ⇒ Object
Returns the value of attribute verbose.
35 36 37 |
# File 'lib/omnibus-ctl.rb', line 35 def verbose @verbose end |
Class Method Details
.to_method_name(name) ⇒ Object
157 158 159 |
# File 'lib/omnibus-ctl.rb', line 157 def self.to_method_name(name) name.gsub(/-/, "_").to_sym end |
Instance Method Details
#add_command(name, description, arity = 1, &block) ⇒ Object
195 196 197 198 |
# File 'lib/omnibus-ctl.rb', line 195 def add_command(name, description, arity = 1, &block) @command_map[name] = { desc: description, arity: arity } self.class.send(:define_method, to_method_name(name).to_sym) { |*args| block.call(*args) } end |
#add_command_under_category(name, category, description, arity = 1, &block) ⇒ Object
200 201 202 203 204 205 |
# File 'lib/omnibus-ctl.rb', line 200 def add_command_under_category(name, category, description, arity = 1, &block) # add new category if it doesn't exist @category_command_map[category] ||= {} @category_command_map[category][name] = { desc: description, arity: arity } self.class.send(:define_method, to_method_name(name).to_sym) { |*args| block.call(*args) } end |
#add_global_pre_hook(name, &block) ⇒ Object
207 208 209 210 211 |
# File 'lib/omnibus-ctl.rb', line 207 def add_global_pre_hook(name, &block) method_name = to_method_name("#{name}_global_pre_hook").to_sym @global_pre_hooks[name] = method_name self.class.send(:define_method, method_name, block) end |
#ask_license_acceptance ⇒ Object
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 |
# File 'lib/omnibus-ctl.rb', line 544 def ask_license_acceptance log "To use this software, you must agree to the terms of the software license agreement." unless STDIN.tty? log "Please view and accept the software license agreement, or pass --accept-license." exit(1) end log "Press any key to continue." user_input = STDIN.getch user_input << STDIN.getch while STDIN.ready? # No need to check for user input system("less #{project_license_path}") loop do log "Type 'yes' to accept the software license agreement, or anything else to cancel." user_input = STDIN.gets.chomp.downcase case user_input when "yes" return true else log "You have not accepted the software license agreement." return false end end end |
#check_license_acceptance(override_accept = false) ⇒ Object
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 |
# File 'lib/omnibus-ctl.rb', line 526 def check_license_acceptance(override_accept = false) license_guard_file_path = File.join(data_path, ".license.accepted") # If the project does not have a license we do not have # any license to accept. return unless File.exist?(project_license_path) unless File.exist?(license_guard_file_path) if override_accept || ask_license_acceptance FileUtils.mkdir_p(data_path) FileUtils.touch(license_guard_file_path) else log "Please accept the software license agreement to continue." exit(1) end end end |
#cleanse(*args) ⇒ Object
330 331 332 333 |
# File 'lib/omnibus-ctl.rb', line 330 def cleanse(*args) scary_cleanse_warning(*args) cleanup_procs_and_nuke("#{service_path}/* /tmp/opt #{data_path} #{etc_path} #{log_path}", "cleanse") end |
#cleanse_post_hook(*args) ⇒ Object
Data cleanup requirements for external services aren’t met by the standard ‘nuke /var/opt’ behavior - this hook allows each service to perform its own ‘cleanse’ operations.
Your callback for this function should be in the form ‘external_cleanup_#service_name(do_clean) where do_cliean is true if the delete should actually be performed, and false if it’s expected to inform the user how to perform the data cleanup without doing any cleanup itself.
862 863 864 865 866 867 868 869 870 |
# File 'lib/omnibus-ctl.rb', line 862 def cleanse_post_hook(*args) external_services.each_key do |service_name| perform_delete = ARGV.include?("--with-external") if perform_delete log "Deleting data from external service: #{service_name}" end send(to_method_name("external_cleanse_#{service_name}"), perform_delete) end end |
#cleanup_procs_and_nuke(filestr, calling_method = nil) ⇒ Object
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 |
# File 'lib/omnibus-ctl.rb', line 251 def cleanup_procs_and_nuke(filestr, calling_method = nil) run_sv_command("stop") FileUtils.rm_f("/etc/init/#{name}-runsvdir.conf") if File.exist?("/etc/init/#{name}-runsvdir.conf") run_command("egrep -v '#{base_path}/embedded/bin/runsvdir-start' /etc/inittab > /etc/inittab.new && mv /etc/inittab.new /etc/inittab") if File.exist?("/etc/inittab") run_command("kill -1 1") @backup_dir = Time.now.strftime("/root/#{name}-cleanse-%FT%R") FileUtils.mkdir_p("/root") unless File.exist?("/root") FileUtils.rm_rf(backup_dir) FileUtils.cp_r(etc_path, backup_dir) if File.exist?(etc_path) run_command("rm -rf #{filestr}") graceful_kill log "Terminating processes running under application users. This will take a few seconds." run_command("pkill -HUP -u #{kill_users.join(",")}") if kill_users.length > 0 run_command("pkill -HUP -f 'runsvdir -P #{service_path}'") sleep 3 run_command("pkill -TERM -u #{kill_users.join(",")}") if kill_users.length > 0 run_command("pkill -TERM -f 'runsvdir -P #{service_path}'") sleep 3 run_command("pkill -KILL -u #{kill_users.join(",")}") if kill_users.length > 0 run_command("pkill -KILL -f 'runsvdir -P #{service_path}'") get_all_services.each do |die_daemon_die| run_command("pkill -KILL -f 'runsv #{die_daemon_die}'") end log "Your config files have been backed up to #{backup_dir}." exit! 0 end |
#command_post_hook(*args) ⇒ Object
Executes after successful completion of a command If a post-hook provides a numeric return code, it will replace the return/exit of the original command
809 810 811 812 813 814 815 |
# File 'lib/omnibus-ctl.rb', line 809 def command_post_hook(*args) command = args.shift method = to_method_name("#{command}_post_hook") if respond_to?(method) send(method, *args) end end |
#command_pre_hook(*args) ⇒ Object
If a command has a pre-hook defined we will run it. Otherwise, if it is a run-sv command and the service it refers to is an external service, we will show an error since we can’t control external services from here.
If any pre-hook returns false, it will prevent execution of the command and exit the command with exit code 8.
788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 |
# File 'lib/omnibus-ctl.rb', line 788 def command_pre_hook(*args) command = args.shift method = to_method_name("#{command}_pre_hook") if respond_to?(method) send(method, *args) else return true if args.empty? if SV_COMMAND_NAMES.include? command if service_external? args[0] log error_external_service(command, args[0]) return false end end true end end |
#error_external_service(command, service) ⇒ Object
886 887 888 889 890 891 892 893 894 |
# File 'lib/omnibus-ctl.rb', line 886 def error_external_service(command, service) <<EOM ------------------------------------------------------------------- The service #{service} is running externally and cannot be managed vi chef-server-ctl. Please log into #{external_services[service]["vip"]} to manage it directly. ------------------------------------------------------------------- EOM end |
#exit!(code) ⇒ Object
213 214 215 216 |
# File 'lib/omnibus-ctl.rb', line 213 def exit!(code) @force_exit = true code end |
#external_services ⇒ Object
Helper function that returns the hash of config hashes that have the key ‘external’ : true in the running config. If none exist it will return an empty hash.
450 451 452 |
# File 'lib/omnibus-ctl.rb', line 450 def external_services @external_services ||= running_package_config.select { |k, v| v.class == Hash and v["external"] == true } end |
#format_multiline_message(indent, message) ⇒ Object
896 897 898 899 900 901 902 903 |
# File 'lib/omnibus-ctl.rb', line 896 def (indent, ) if .class == String = .split("\n") end spaces = " " * indent .map! { |line| "#{spaces}#{line.strip}" } .join("\n") end |
#get_all_commands_hash ⇒ Object
merges category_command_map and command_map, removing categories
173 174 175 176 177 178 179 |
# File 'lib/omnibus-ctl.rb', line 173 def get_all_commands_hash without_categories = {} category_command_map.each do |category, commands| without_categories.merge!(commands) end command_map.merge(without_categories) end |
#get_all_services ⇒ Object
339 340 341 |
# File 'lib/omnibus-ctl.rb', line 339 def get_all_services get_all_services_files.map { |f| File.basename(f) }.sort end |
#get_all_services_files ⇒ Object
335 336 337 |
# File 'lib/omnibus-ctl.rb', line 335 def get_all_services_files Dir[File.join(sv_path, "*")] end |
#get_pgrp_from_pid(pid) ⇒ Object
222 223 224 225 |
# File 'lib/omnibus-ctl.rb', line 222 def get_pgrp_from_pid(pid) ps = `which ps`.chomp `#{ps} -p #{pid} -o pgrp=`.chomp end |
#get_pids_from_pgrp(pgrp) ⇒ Object
227 228 229 230 |
# File 'lib/omnibus-ctl.rb', line 227 def get_pids_from_pgrp(pgrp) pgrep = `which pgrep`.chomp `#{pgrep} -g #{pgrp}`.split(/\n/).join(" ") end |
#global_service_command_permitted(sv_cmd, service_name) ⇒ Object
if we’re running a global service command (like p-c-c status) across all of the services, there are certain cases where we want to prevent services files that exist in the service directory from being activated. This method is the logic that blocks those services
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 |
# File 'lib/omnibus-ctl.rb', line 377 def global_service_command_permitted(sv_cmd, service_name) # For services that have been removed, we only want to # them to respond to the stop command. They should not show # up in status, and they should not be started. if removed_services.include?(service_name) return sv_cmd == "stop" end # For keepalived, we only want it to respond to the status # command when running global service commands like p-c-c start # and p-c-c stop if service_name == "keepalived" return sv_cmd == "status" end # If c-s-c status is called, check to see if the service # is hidden supposed to be hidden from the status results # (mover for example should be hidden). if sv_cmd == "status" return !(hidden_services.include?(service_name)) end # All other services respond normally to p-c-c * commands true end |
#graceful_kill(*args) ⇒ Object
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 |
# File 'lib/omnibus-ctl.rb', line 592 def graceful_kill(*args) service = args[1] exit_status = 0 get_all_services.each do |service_name| next if !service.nil? && service_name != service if service_enabled?(service_name) pidfile = "#{sv_path}/#{service_name}/supervise/pid" pid = File.read(pidfile).chomp if File.exist?(pidfile) if pid.nil? || !is_integer?(pid) log "could not find #{service_name} runit pidfile (service already stopped?), cannot attempt SIGKILL..." status = run_command("#{base_path}/init/#{service_name} stop") exit_status = status.exitstatus if exit_status == 0 && !status.success? next end pgrp = get_pgrp_from_pid(pid) if pgrp.nil? || !is_integer?(pgrp) log "could not find pgrp of pid #{pid} (not running?), cannot attempt SIGKILL..." status = run_command("#{base_path}/init/#{service_name} stop") exit_status = status.exitstatus if exit_status == 0 && !status.success? next end run_command("#{base_path}/init/#{service_name} stop") pids = get_pids_from_pgrp(pgrp) unless pids.empty? log "found stuck pids still running in process group: #{pids}, sending SIGKILL" unless pids.empty? sigkill_pgrp(pgrp) end else log "#{service_name} disabled, not stopping" exit_status = 1 end end exit! exit_status end |
#help(*args) ⇒ Object
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 |
# File 'lib/omnibus-ctl.rb', line 628 def help(*args) log "#{exe_name}: command (subcommand)\n" command_map.keys.sort.each do |command| log command log " #{command_map[command][:desc]}" end category_command_map.each do |category, commands| # Remove "-" and replace with spaces in category and capalize for output category_string = category.gsub("-", " ").split.map(&:capitalize).join(" ") log "#{category_string} Commands:\n" # Print each command in this category commands.keys.sort.each do |command| log " #{command}" log " #{commands[command][:desc]}" end end # Help is not an error so exit with 0. In cases where we display help as a result of an error # the framework will handle setting proper exit code. exit! 0 end |
#hidden_services ⇒ Object
hidden services are configured via the attributes file in the main omnibus cookbook
hidden services are services that we do not want to show up in c-s-c status.
418 419 420 421 422 423 424 |
# File 'lib/omnibus-ctl.rb', line 418 def hidden_services # in the case that there is no running_config (the config file does # not exist), we don't want to return nil, just return an empty array. # worse result with doing that is services that we don't want to show up in # c-s-c status will show up. running_package_config["hidden_services"] || [] end |
#is_integer?(string) ⇒ Boolean
588 589 590 |
# File 'lib/omnibus-ctl.rb', line 588 def is_integer?(string) return true if Integer(string) rescue false end |
#is_option?(arg) ⇒ Boolean
If it begins with a ‘-’, it is an option.
666 667 668 |
# File 'lib/omnibus-ctl.rb', line 666 def is_option?(arg) arg && arg[0] == "-" end |
#load_file(filepath) ⇒ Object
191 192 193 |
# File 'lib/omnibus-ctl.rb', line 191 def load_file(filepath) eval(IO.read(filepath), nil, filepath, 1) # rubocop: disable Security/Eval end |
#load_files(path) ⇒ Object
185 186 187 188 189 |
# File 'lib/omnibus-ctl.rb', line 185 def load_files(path) Dir["#{path}/*.rb"].each do |file| load_file(file) end end |
#log(msg) ⇒ Object
218 219 220 |
# File 'lib/omnibus-ctl.rb', line 218 def log(msg) fh_output.puts msg end |
#log_external_service_header ⇒ Object
915 916 917 918 919 920 921 |
# File 'lib/omnibus-ctl.rb', line 915 def log_external_service_header return if external_services.empty? log "-------------------" log " External Services " log "-------------------" end |
#log_internal_service_header ⇒ Object
905 906 907 908 909 910 911 912 913 |
# File 'lib/omnibus-ctl.rb', line 905 def log_internal_service_header # Don't decorate output unless we have # external services to report on. return if external_services.empty? log "-------------------" log " Internal Services " log "-------------------" end |
#package_name ⇒ Object
translate the name from the config to the package name. this is a special case for the private-chef package because it is configured to use the name and directory structure of ‘opscode’, not ‘private-chef’
430 431 432 433 434 435 436 437 438 |
# File 'lib/omnibus-ctl.rb', line 430 def package_name case @name # The "opscode" in /opt/opscode when ::ChefUtils::Dist::Org::LEGACY_CONF_DIR "private-chef" else @name end end |
#parse_options(args) ⇒ Object
Set global options and remove them from the args list we pass into commands.
652 653 654 655 656 657 658 659 660 661 662 663 |
# File 'lib/omnibus-ctl.rb', line 652 def (args) args.select do |option| case option when "--quiet", "-q" @quiet = true false when "--verbose", "-v" @verbose = true false end end end |
#project_license_path ⇒ Object
573 574 575 |
# File 'lib/omnibus-ctl.rb', line 573 def project_license_path File.join(base_path, "LICENSE") end |
#reconfigure(*args) ⇒ Object
511 512 513 514 515 516 517 518 519 520 521 522 523 524 |
# File 'lib/omnibus-ctl.rb', line 511 def reconfigure(*args) # args being passed to this command does not include the ones that are # starting with "-". See #is_option? method. If it is starting with "-" # then it is treated as a option and we need to look for them in ARGV. check_license_acceptance(ARGV.include?("--accept-license")) status = run_chef("#{base_path}/embedded/cookbooks/dna.json") if status.success? log "#{display_name} Reconfigured!" exit! 0 else exit! 1 end end |
#remove_old_node_state ⇒ Object
481 482 483 484 485 486 487 488 |
# File 'lib/omnibus-ctl.rb', line 481 def remove_old_node_state node_cache_path = "#{base_path}/embedded/nodes/" status = run_command("rm -rf #{node_cache_path}") unless status.success? log "Could not remove cached node state!" exit 1 end end |
#removed_services ⇒ Object
removed services are configured via the attributes file in the main omnibus cookbook
405 406 407 408 409 410 411 |
# File 'lib/omnibus-ctl.rb', line 405 def removed_services # in the case that there is no running_config (the config file does # not exist), we know that this will be a new server, and we don't # have to worry about pre-upgrade services hanging around. We can safely # return an empty array when running_config is nil running_package_config["removed_services"] || [] end |
#retrieve_command(command_to_run) ⇒ Object
retrieves the commmand from either the command_map or the category_command_map, if the command is not found return nil
673 674 675 676 677 678 679 680 681 682 683 684 |
# File 'lib/omnibus-ctl.rb', line 673 def retrieve_command(command_to_run) if command_map.key?(command_to_run) command_map[command_to_run] else command = nil category_command_map.each do |category, commands| command = commands[command_to_run] if commands.key?(command_to_run) end # return the command, or nil if it wasn't found command end end |
#run(args) ⇒ Object
Previously this would exit immediately with the provided exit code; however this would prevent post-run hooks from continuing Instead, we’ll just track whether a an exit was requested and use that to determine how we exit from ‘run’
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 |
# File 'lib/omnibus-ctl.rb', line 690 def run(args) # Ensure Omnibus related binaries are in the PATH ENV["PATH"] = [File.join(base_path, "bin"), File.join(base_path, "embedded", "bin"), ENV["PATH"]].join(":") command_to_run = args[0] ## when --help is run as the command itself, we need to strip off the ## `--` to ensure the command maps correctly. if command_to_run == "--help" command_to_run = "help" end # This piece of code checks if the argument is an option. If it is, # then it sets service to nil and adds the argument into the options # argument. This is ugly. A better solution is having a proper parser. # But if we are going to implement a proper parser, we might as well # port this to Thor rather than reinventing Thor. For now, this preserves # the behavior to complain and exit with an error if one attempts to invoke # a pcc command that does not accept an argument. Like "help". = args[2..-1] || [] if is_option?(args[1]) .unshift(args[1]) service = nil else service = args[1] end # returns either hash content of command or nil command = retrieve_command(command_to_run) if command.nil? log "I don't know that command." if args.length == 2 log "Did you mean: #{exe_name} #{service} #{command_to_run}?" end help Kernel.exit 1 end if args.length > 1 && command[:arity] != 2 log "The command #{command_to_run} does not accept any arguments" Kernel.exit 2 end @force_exit = false exit_code = 0 run_global_pre_hooks # Filter args to just command and service. If you are loading # custom commands and need access to the command line argument, # use ARGV directly. actual_args = [command_to_run, service].reject(&:nil?) if command_pre_hook(*actual_args) method_to_call = to_method_name(command_to_run) begin ret = send(method_to_call, *actual_args) rescue SystemExit => e @force_exit = true ret = e.status end command_post_hook(*actual_args) exit_code = ret unless ret.nil? else exit_code = 8 @force_exit = true end if @force_exit Kernel.exit exit_code else exit_code end end |
#run_chef(attr_location, args = "") ⇒ Object
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 |
# File 'lib/omnibus-ctl.rb', line 490 def run_chef(attr_location, args = "") if @verbose log_level = "-l debug" elsif @quiet # null formatter is awfully quiet, so let them know we're doing something. log "Reconfiguring #{display_name}." log_level = "-l fatal -F null" else log_level = "" end remove_old_node_state cmd = "#{base_path}/embedded/bin/cinc-client #{log_level} -z -c #{base_path}/embedded/cookbooks/solo.rb -j #{attr_location}" cmd += " #{args}" unless args.empty? run_command(cmd) end |
#run_command(command) ⇒ Object
237 238 239 240 |
# File 'lib/omnibus-ctl.rb', line 237 def run_command(command) system(command) $? end |
#run_global_pre_hooks ⇒ Object
767 768 769 770 771 772 773 774 775 776 |
# File 'lib/omnibus-ctl.rb', line 767 def run_global_pre_hooks @global_pre_hooks.each do |hook_name, method_name| send(method_name) rescue => e $stderr.puts("Global pre-hook '#{hook_name}' failed with: '#{e.}'") exit(1) end end |
#run_sv_command(sv_cmd, service = nil) ⇒ Object
347 348 349 350 351 352 353 354 355 356 357 358 359 |
# File 'lib/omnibus-ctl.rb', line 347 def run_sv_command(sv_cmd, service = nil) exit_status = 0 sv_cmd = "1" if sv_cmd == "usr1" sv_cmd = "2" if sv_cmd == "usr2" if service exit_status += run_sv_command_for_service(sv_cmd, service) else get_all_services.each do |service_name| exit_status += run_sv_command_for_service(sv_cmd, service_name) if global_service_command_permitted(sv_cmd, service_name) end end exit! exit_status end |
#run_sv_command_for_service(sv_cmd, service_name) ⇒ Object
run an sv command for a specific service name
362 363 364 365 366 367 368 369 370 |
# File 'lib/omnibus-ctl.rb', line 362 def run_sv_command_for_service(sv_cmd, service_name) if service_enabled?(service_name) status = run_command("#{base_path}/init/#{service_name} #{sv_cmd}") status.exitstatus else log "#{service_name} disabled" if sv_cmd == "status" && verbose 0 end end |
#running_config ⇒ Object
returns nil when chef-server-running.json does not exist
441 442 443 444 445 446 |
# File 'lib/omnibus-ctl.rb', line 441 def running_config fname = "#{etc_path}/#{::ChefUtils::Dist::Server::SERVER}-running.json" @running_config ||= if File.exist?(fname) JSON.parse(File.read(fname)) end end |
#running_package_config ⇒ Object
Gives package config from the running_config. If there is no running config or if package_name doens’t reference a valid key, this will return an empty hash
465 466 467 468 469 470 471 |
# File 'lib/omnibus-ctl.rb', line 465 def running_package_config if (cfg = running_config) cfg[package_name.gsub(/-/, "_")] || {} else {} end end |
#running_service_config(service) ⇒ Object
This returns running_config[service].
If there is no running_config or is no matching key it will return nil.
477 478 479 |
# File 'lib/omnibus-ctl.rb', line 477 def running_service_config(service) running_package_config[service] end |
#scary_cleanse_warning(*args) ⇒ Object
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 323 324 325 326 327 328 |
# File 'lib/omnibus-ctl.rb', line 287 def scary_cleanse_warning(*args) just_do_it = args.include?("yes") with_external = ARGV.include?("--with-external") log <<EOM ******************************************************************* * * * * * * * * * * * STOP AND READ * * * * * * * * * * ******************************************************************* This command will delete *all* local configuration, log, and variable data associated with #{display_name}. EOM if with_external log <<EOM This will also delete externally hosted #{display_name} data. This means that any service you have configured as 'external' will have any #{display_name} permanently deleted. EOM elsif not external_services.empty? log <<EOM Important note: If you also wish to delete externally hosted #{display_name} data, please hit CTRL+C now and run '#{exe_name} cleanse --with-external' EOM end unless just_do_it data = with_external ? "local, and remote data" : "and local data" log <<EOM You have 60 seconds to hit CTRL-C before configuration, logs, #{data} for this application are permanently deleted. ******************************************************************* EOM begin sleep 60 rescue Interrupt log "" exit 0 end end end |
#service_commands? ⇒ Boolean
181 182 183 |
# File 'lib/omnibus-ctl.rb', line 181 def service_commands? @service_commands end |
#service_enabled?(service_name) ⇒ Boolean
343 344 345 |
# File 'lib/omnibus-ctl.rb', line 343 def service_enabled?(service_name) File.symlink?("#{service_path}/#{service_name}") end |
#service_external?(service) ⇒ Boolean
Helper function that returns true if an external service entry exists for the named service
456 457 458 459 460 |
# File 'lib/omnibus-ctl.rb', line 456 def service_external?(service) return false if service.nil? external_services.key? service end |
#service_list(*args) ⇒ Object
242 243 244 245 246 247 248 249 |
# File 'lib/omnibus-ctl.rb', line 242 def service_list(*args) get_all_services.each do |service_name| print "#{service_name}" print "*" if service_enabled?(service_name) print "\n" end exit! 0 end |
#service_list_post_hook ⇒ Object
Capture external services in the output list as well.
879 880 881 882 883 884 |
# File 'lib/omnibus-ctl.rb', line 879 def service_list_post_hook log_external_service_header external_services.each do |name, settings| log " > #{name} on #{settings["vip"]}" end end |
#service_list_pre_hook ⇒ Object
Add some output headers if we have external services enabled
873 874 875 876 |
# File 'lib/omnibus-ctl.rb', line 873 def service_list_pre_hook log_internal_service_header true end |
#show_config(*args) ⇒ Object
506 507 508 509 |
# File 'lib/omnibus-ctl.rb', line 506 def show_config(*args) status = run_chef("#{base_path}/embedded/cookbooks/show-config.json", "-l fatal -F null") exit! status.success? ? 0 : 1 end |
#sigkill_pgrp(pgrp) ⇒ Object
232 233 234 235 |
# File 'lib/omnibus-ctl.rb', line 232 def sigkill_pgrp(pgrp) pkill = `which pkill`.chomp run_command("#{pkill} -9 -g #{pgrp}") end |
#status_post_hook(service = nil) ⇒ Object
Status gets its own hook because each externalized service will have its own things to do in order to report status. As above, we may also include an output header to show that we’re reporting on external services.
Your callback for this function should be in the form ‘external_status_#service_name(detail_level) where detail_level is :sparse|:verbose :sparse is used when it’s a summary service status list, eg “$appname-ctl status” :verbose is used when the specific service has been named, eg “$appname-ctl status postgresql”
837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 |
# File 'lib/omnibus-ctl.rb', line 837 def status_post_hook(service = nil) if service.nil? log_external_service_header external_services.each_key do |service_name| status = send(to_method_name("external_status_#{service_name}"), :sparse) log status end else # Request verbose status if the service is asked for by name. if service_external?(service) status = send(to_method_name("external_status_#{service}"), :verbose) log status end end end |
#status_pre_hook(service = nil) ⇒ Object
If we’re listing status for all services and have external services to show, we’ll include an output header to show that we’re reporting internal services
820 821 822 823 |
# File 'lib/omnibus-ctl.rb', line 820 def status_pre_hook(service = nil) log_internal_service_header if service.nil? true end |
#tail(*args) ⇒ Object
577 578 579 580 581 582 583 584 585 586 |
# File 'lib/omnibus-ctl.rb', line 577 def tail(*args) # find /var/log -type f -not -path '*/sasl/*' | grep -E -v '(lock|@|tgz|gzip)' | xargs tail --follow=name --retry command = "find -L #{log_path}" command << "/#{args[1]}" if args[1] command << " -type f" command << log_path_exclude.map { |path| " -not -path '#{path}'" }.join(" ") command << " | grep -E -v '#{log_exclude}' | xargs tail --follow=name --retry" system(command) end |
#to_method_name(name) ⇒ Object
161 162 163 |
# File 'lib/omnibus-ctl.rb', line 161 def to_method_name(name) Ctl.to_method_name(name) end |
#uninstall(*args) ⇒ Object
283 284 285 |
# File 'lib/omnibus-ctl.rb', line 283 def uninstall(*args) cleanup_procs_and_nuke("/tmp/opt") end |