1module MCollective
2  class Application::Service < Application
3    description "Manages system services"
4
5    usage <<-END_OF_USAGE
6mco service <SERVICE> <ACTION>
7
8ACTION can be one of the following :
9
10    start   - start service
11    stop    - stop service
12    restart - restart or reload service
13    status  - determine the current staus of the remote service
14END_OF_USAGE
15
16    option :yes,
17           :arguments   => ["--yes", "-y"],
18           :description => "Assume yes on any prompts",
19           :type        => :bool
20
21    def handle_message(action, message, *args)
22      messages = {1 => "Please specify service name and action",
23                  2 => "Action has to be one of start, stop, restart or status",
24                  3 => "Do you really want to operate on services unfiltered? (y/n): "}
25
26      send(action, messages[message] % args)
27    end
28
29    def post_option_parser(configuration)
30      if ARGV.size < 2
31        handle_message(:raise, 1)
32      else
33        valid_actions = ['start', 'stop', 'restart', 'status']
34
35        if valid_actions.include?(ARGV[0])
36          configuration[:action] = ARGV.shift
37          configuration[:service] = ARGV.shift
38        elsif valid_actions.include?(ARGV[1])
39          configuration[:service] = ARGV.shift
40          configuration[:action] = ARGV.shift
41        else
42          handle_message(:raise, 2)
43        end
44      end
45    end
46
47    def validate_configuration(configuration)
48      unless configuration[:action] == 'status'
49        if Util.empty_filter?(options[:filter]) && !configuration[:yes]
50          handle_message(:print, 3)
51
52          STDOUT.flush
53
54          exit(1) unless STDIN.gets.strip.match(/^(?:y|yes)$/i)
55        end
56      end
57    end
58
59    def main
60      # We have to change our process name in order to hide name of the
61      # service we are looking for from our execution arguments. Puppet
62      # provider will look at the process list for the name of the service
63      # it wants to manage and it might find us with our arguments there
64      # which is not what we really want ...
65      $0 = 'mco'
66
67      service = rpcclient('service')
68      service_result = service.send(configuration[:action], :service => configuration[:service])
69
70      if !service_result.empty?
71        sender_width = service_result.map{|s| s[:sender]}.map{|s| s.length}.max + 3
72        pattern = "%%%ds: %%s" % sender_width
73
74        service_result.each do |result|
75          if result[:statuscode] == 0
76            if service.verbose
77              puts pattern % [result[:sender], result[:data][:status]]
78            else
79              case configuration[:action]
80              when 'start', 'restart'
81                puts(pattern % [result[:sender], result[:data][:status]]) unless result[:data][:status] == 'running'
82              when 'stop'
83                puts(pattern % [result[:sender], result[:data][:status]]) unless result[:data][:status] == 'stopped'
84              when 'status'
85                puts(pattern % [result[:sender], result[:data][:status]])
86              end
87            end
88          else
89            puts(pattern % [result[:sender], result[:statusmsg]])
90          end
91        end
92
93        puts
94      end
95
96      printrpcstats :summarize => true, :caption => "%s Service results" % configuration[:action]
97      halt(service.stats)
98    end
99  end
100end
101