63e751658459bd604ced95b2c65bbd322b047652
[packages/precise/mcollective.git] / ext / mc-irb
1 #!/usr/bin/env ruby
2
3 # Simple IRB shell for mcollective
4 #
5 #    mc-irb nrpe
6 #    Determining the amount of hosts matching filter for 2 seconds .... 47
7 #    >> rpc :runcommand, :command => "check_disks"
8 #
9 #     * [ ============================================================> ] 47 / 47
10 #
11 #
12 #     dev1.your.net                      Request Aborted
13 #        CRITICAL
14 #                     Output: DISK CRITICAL - free space: / 176 MB (4% inode=86%);
15 #                  Exit Code: 2
16 #           Performance Data:  /=3959MB;3706;3924;0;4361 /boot=26MB;83;88;0;98 /dev/shm=0MB;217;230;0;256
17 #
18 #    => true
19 #    >> mchelp
20 #    <shows the DDL based help for the chosen agent>
21 #    => true
22 #    >> rpc(:runcommand, :command => "check_disks") do |resp|
23 #    ?> puts resp[:sender] + ":   " + resp[:data][:output]
24 #    >> end
25 #
26 #     * [ ============================================================> ] 47 / 47
27 #
28 #     dev1.your.net:   DISK OK
29 #     <snip>
30 #    => true
31 #    >>
32 #
33 # You can access the agent variable via @agent from where you can do the usual manipulation of filters etc,
34 # if you wish to switch to a different agent mid run just do newagent("some_other_agent")
35 #
36 # If you install the Bond gem you'll get some DDL assisted completion in the rpc method
37 require 'rubygems'
38 require 'irb'
39
40 def consolize &block
41     yield
42
43     IRB.setup(nil)
44     irb = IRB::Irb.new
45     IRB.conf[:MAIN_CONTEXT] = irb.context
46     irb.context.evaluate("require 'irb/completion'", 0)
47
48     begin
49         require 'bond'
50         Bond.start
51
52         Bond.complete(:method => "rpc") do |e|
53             begin
54                 if e.argument == 1
55                     if e.arguments.last == "?"
56                         puts "\n\nActions for #{@agent_name}:\n"
57
58                         @agent.ddl.actions.each do |action|
59                            puts "%20s - %s" % [ ":#{action}", @agent.ddl.action_interface(action)[:description] ]
60                         end
61
62                         print "\n" + e.line
63                     end
64
65                     @agent.ddl.actions
66
67                 elsif e.argument > 1
68                     action = eval(e.arguments[0]).to_s
69                     ddl = @agent.ddl.action_interface(action)
70
71                     if e.arguments.last == "?"
72                         puts "\n\nArguments for #{action}:\n"
73                         ddl[:input].keys.each do |input|
74                             puts "%20s - %s" % [ ":#{input}", ddl[:input][input][:description] ]
75                         end
76
77                         print "\n" + e.line
78                     end
79
80                     [ddl[:input].keys, :verbose].flatten
81                 end
82             rescue Exception
83                 []
84             end
85         end
86     rescue Exception
87     end
88
89     trap("SIGINT") do
90         irb.signal_handle
91     end
92     catch(:IRB_EXIT) do
93         irb.eval_input
94     end
95 end
96
97 def mchelp
98     system("mc-rpc --agent-help #{@agent_name}|less")
99     true
100 end
101
102 def rpc(method_name, *args, &block)
103     unless block_given?
104         if args.size > 0
105             args = args.first
106         else
107             args = {}
108         end
109
110         if args[:verbose]
111             args.delete(:verbose)
112
113             printrpc(@agent.send(method_name, args), :verbose => true)
114             printrpcstats
115         else
116             printrpc @agent.send(method_name, args)
117             printrpcstats
118         end
119
120     else
121         @agent.send(method_name, args.first).each do |resp|
122             yield resp
123         end
124
125         printrpcstats
126     end
127
128     true
129 rescue MCollective::DDLValidationError => e
130     puts "Request did not pass DDL validation: #{e}"
131 end
132
133 def print_filter
134     puts "Active Filter matched #{discover.size} hosts:"
135     puts "\tIdentity: #{@agent.filter['identity'].pretty_inspect}"
136     puts "\t Classes: #{@agent.filter['cf_class'].pretty_inspect}"
137     puts "\t   Facts: #{@agent.filter['fact'].pretty_inspect}"
138     puts "\t  Agents: #{@agent.filter['agent'].pretty_inspect}"
139
140     discover.size > 0 ? true : false
141 end
142
143 def newagent(agent)
144     @agent_name = agent
145
146     @options[:filter]["agent"] = []
147     @agent = rpcclient(@agent_name, :options => @options)
148
149     discover
150
151     @agent.progress = true
152
153     print_filter
154 end
155
156 def identity_filter(*args)
157     @agent.identity_filter(*args)
158
159     print_filter
160 end
161
162 def fact_filter(*args)
163     @agent.fact_filter(*args)
164
165     print_filter
166 end
167
168 def agent_filter(*args)
169     @agent.agent_filter(*args)
170
171     print_filter
172 end
173
174 def class_filter(*args)
175     @agent.class_filter(*args)
176
177     print_filter
178 end
179
180 def reset_filter
181     @agent.reset_filter
182
183     print_filter
184 end
185
186 def reset
187     @agent.reset
188
189     print_filter
190 end
191
192 def discover
193     @agent.discover
194 end
195
196 def mc?
197     puts <<EOF
198     Available Commands:
199
200         rpc                                 - Performs an RPC request
201         reset                               - Resets the discovered knowledge
202         discover                            - Performs a new discovery showing
203                                               hosts that was found
204         newagent                            - Switches to a new agent
205         mchelp                              - The DDL created help for the agent
206
207     Filter Commands:
208         Filter arguments should be enclosed in "your.host.com" if they are strings
209         else use /your.host/ to match Regular expressions
210
211         identity_filter [identity]          - Sets an identity filter
212         fact_filter [factname], [factvalue] - Sets a fact filter
213         class_filter [classname]            - Sets a class filter
214         agent_filter [agentname]            - Sets an agent filter
215         reset_filter                        - Resets to the filter to blank
216         print_filter                        - Displays current filter
217
218     Available Variables:
219
220         @agent_name                         - The name of the active agent
221         @agent                              - The active RPC client
222
223     Completions:
224
225         While doing an RPC request, press ?<tab> for a list of actions or
226         arguments, do simple :<tab> to get completion on action names and
227         arguments without description of each
228
229 EOF
230     true
231 end
232
233 consolize do
234     require 'mcollective'
235
236
237     include MCollective::RPC
238
239     @options = rpcoptions
240
241     unless ARGV.size == 1
242         puts "Please specify an agent name on the command line"
243         exit 1
244     end
245
246     puts "The Marionette Collective Interactive Ruby Shell version #{MCollective.version}"
247
248     puts
249     newagent(ARGV[0])
250     puts
251     puts "Use mc? to get help on using this shell"
252 end