~ubuntu-branches/ubuntu/utopic/pacemaker/utopic-proposed

« back to all changes in this revision

Viewing changes to tools/crm_sh.in

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez
  • Date: 2013-07-16 16:40:24 UTC
  • mfrom: (1.1.11) (2.2.3 experimental)
  • Revision ID: package-import@ubuntu.com-20130716164024-lvwrf4xivk1wdr3c
Tags: 1.1.9+git20130321-1ubuntu1
* Resync from debian expiremental.
* debian/control:
  - Use lower version for Build-Depends on libcorosync-dev
    and libqb-dev.
  - Build-Depends on libcfg-dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!@PYTHON@
2
 
#
3
 
# Copyright (c) 2006 Andrew Beekhof
4
 
#                    All Rights Reserved.
5
 
#
6
 
# This program is free software; you can redistribute it and/or modify
7
 
# it under the terms of version 2 of the GNU General Public License as
8
 
# published by the Free Software Foundation.
9
 
#
10
 
# This program is distributed in the hope that it would be useful, but
11
 
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
 
#
14
 
# Further, this software is distributed without any warranty that it is
15
 
# free of the rightful claim of any third person regarding infringement
16
 
# or the like.  Any license provided herein, whether implied or
17
 
# otherwise, applies only to this software file.  Patent licenses, if
18
 
# any, provided herein do not apply to combinations of this program with
19
 
# other software, or any other product whatsoever.
20
 
#
21
 
# You should have received a copy of the GNU General Public License
22
 
# along with this program; if not, write the Free Software Foundation,
23
 
# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
24
 
#
25
 
#######################################################################
26
 
 
27
 
import os
28
 
import sys
29
 
import readline
30
 
import traceback
31
 
from popen2 import Popen3
32
 
 
33
 
# Module copied from Mercurial
34
 
 
35
 
sys.path.append("@CRM_DAEMON_DIR@")
36
 
import crm_utils as utl
37
 
import crm_commands as crm 
38
 
 
39
 
 
40
 
class ParseError(Exception):
41
 
    """Exception raised on errors in parsing the command line."""
42
 
class QuotingError(Exception):
43
 
    """Exception raised on errors in parsing the command line."""
44
 
class UnknownCommand(Exception):
45
 
    """Exception raised if command is not in the command table."""
46
 
class AmbiguousCommand(Exception):
47
 
    """Exception raised if command shortcut matches more than one command."""
48
 
 
49
 
table = {
50
 
    "^help": (
51
 
        crm.help, None, [('v', 'verbose', None, 'extra information')],
52
 
        "[-v]"),
53
 
    "^up":        (crm.up, None, [], None, "Move up a level in the heirarchy"),
54
 
    "^crm":       (crm.cd_, ["crm"], [], None),
55
 
    "^nodes":     (crm.cd_, ["crm"], [], None),
56
 
    "^resources": (crm.cd_, ["crm"], [], None),
57
 
    "^config":    (crm.cd_, ["crm"], [], None),
58
 
    "^list": (
59
 
        crm.do_list, ["nodes", "resources"], [('t', 'topic', "", '')],
60
 
        None),
61
 
    "^status": (
62
 
        crm.do_status, ["nodes", "resources"], [],
63
 
        "[list of objects]"),
64
 
    "^debug": (crm.toggle_flag, None, [('f', 'flag', 'debug', '')], None, "Toggle debugging information"),
65
 
    "^exit": (crm.exit, None, [], "exit"),
66
 
    "^debugstate": (
67
 
        crm.debugstate, None, [], 
68
 
        None,
69
 
        "Dump information about the internal state of the program"),
70
 
    }
71
 
 
72
 
global_opt_table = [
73
 
    ('q', 'quiet', None, 'suppress output'),
74
 
    ('v', 'verbose', None, 'enable additional output'),
75
 
    ('', 'debug', None, 'enable debugging output'),
76
 
    ('', 'devlog', None, 'enable developmental debugging output'),
77
 
    ('', 'debugger', None, 'start debugger'),
78
 
    ('', 'lsprof', None, 'print improved command execution profile'),
79
 
    ('', 'traceback', None, 'print traceback on exception'),
80
 
    ('', 'time', None, 'time how long the command takes'),
81
 
    ('', 'profile', None, 'print command execution profile'),
82
 
    ('', 'version', None, 'output version information and exit'),
83
 
    ('i', 'interactive', None, 'run in interactive mode'),
84
 
    ('h', 'help', None, 'display help and exit'),
85
 
    ]
86
 
 
87
 
def help_(text):
88
 
    utl.log_dev("Looking up help text for: %s" % text)
89
 
    if text == "short":
90
 
        utl.log_info("cluster.py [global options] [topic [topic...]] [command]")
91
 
        return
92
 
    if text:
93
 
        choice = findpossible(text, None, False)
94
 
        for key in choice.keys():
95
 
            alias, e = choice[key]
96
 
            text = alias[0]
97
 
            utl.log_dev("Help text for: %s" % text)
98
 
            if e:
99
 
                sub_cmd=""
100
 
                if len(e) > 4:
101
 
                    utl.log_info("\n"+e[4]+"\n")
102
 
                possible = findpossible("", text).keys()
103
 
                utl.log_dev("Possible sub-commands: "+repr(possible))
104
 
                possible.remove("up")
105
 
                possible.remove("help")
106
 
                possible.remove("exit")
107
 
                if text in possible:
108
 
                    possible.remove(text)
109
 
                if possible:
110
 
                        sub_cmd=' ('+'|'.join(possible)+')'
111
 
                if e[3]:
112
 
                    utl.log_info("Usage: %s %s%s" % (text, e[3], sub_cmd))
113
 
                else:
114
 
                    utl.log_info("Usage: %s%s" % (text, sub_cmd))
115
 
        if choice:
116
 
            return;
117
 
    utl.log_err("No help text available for: %s" % text)
118
 
 
119
 
 
120
 
# Stolen from Mercurial commands.py
121
 
 
122
 
def findpossible(cmd, topic=None, filter=True):
123
 
    """
124
 
    Return cmd -> (aliases, command table entry)
125
 
    for each matching command.
126
 
    Return debug commands (or their aliases) only if no normal command matches.
127
 
    """
128
 
    if not topic:
129
 
        topic = utl.crm_topic
130
 
        utl.log_dev("Searching in default topic: %s" % topic)
131
 
        
132
 
    utl.log_dev("Looking for completions of %s in %s" % (cmd, topic))
133
 
    choice = {}
134
 
    debugchoice = {}
135
 
    topicchoice = {}
136
 
    for e in table.keys():
137
 
        t = table[e]
138
 
        #utl.log_dev("Processing: %s / %s" % (e, repr(t)))
139
 
        aliases = e.lstrip("^").split("|")
140
 
        found = None
141
 
        if "^%s"%topic == e and t[0] == crm.cd_:
142
 
            #utl.log_dev("Found: topic")
143
 
            topicchoice[topic] = (aliases, table[e])
144
 
        if filter and t[1] and topic not in t[1]:
145
 
            #utl.log_dev("Skip: filter")
146
 
            continue
147
 
        elif cmd in aliases:
148
 
            #utl.log_dev("Found: alias")
149
 
            found = cmd
150
 
        else:
151
 
            for a in aliases:
152
 
                if a.startswith(cmd):
153
 
                    #utl.log_dev("Found: alias prefix")
154
 
                    found = a
155
 
                    break
156
 
        if found is not None:
157
 
            if aliases[0].startswith("debug"):
158
 
                debugchoice[found] = (aliases, table[e])
159
 
            else:
160
 
                choice[found] = (aliases, table[e])
161
 
 
162
 
    if not choice and debugchoice:
163
 
        choice = debugchoice
164
 
 
165
 
    if not choice and topicchoice:
166
 
        choice = topicchoice
167
 
 
168
 
    return choice
169
 
 
170
 
def findcmd(cmd):
171
 
    """Return (aliases, command table entry) for command string."""
172
 
    choice = findpossible(cmd)
173
 
 
174
 
    if choice.has_key(cmd):
175
 
        #utl.log_dev("Choice has: %s" % cmd)
176
 
        return choice[cmd]
177
 
 
178
 
    if len(choice) > 1:
179
 
        clist = choice.keys()
180
 
        clist.sort()
181
 
        raise AmbiguousCommand(cmd, clist)
182
 
 
183
 
    if choice:
184
 
        #utl.log_dev("Returning first: %s" % (repr(choice.values()[0])))
185
 
        return choice.values()[0]
186
 
 
187
 
    raise UnknownCommand(cmd)
188
 
 
189
 
def find_completer(start, i):
190
 
    choice = findpossible(start)
191
 
    if not choice:
192
 
        return None
193
 
    elif len(choice.keys()) < i:
194
 
        return None
195
 
    return choice.keys()[i]
196
 
 
197
 
def parse(args):
198
 
    options = {}
199
 
    cmdoptions = {}
200
 
    
201
 
    try:
202
 
        args = utl.fancyopts(args, global_opt_table, options)
203
 
    except utl.getopt.GetoptError, inst:
204
 
        raise ParseError(None, inst)
205
 
 
206
 
    if args:
207
 
        cmd, args = args[0], args[1:]
208
 
        utl.log_dev("Initial Command: %s" % cmd)
209
 
        aliases, i = findcmd(cmd)
210
 
        cmd = aliases[0]
211
 
        utl.log_dev("Found Command: %s" % cmd)
212
 
        defaults = []
213
 
        if defaults:
214
 
            args = defaults.split() + args
215
 
        c = list(i[2])
216
 
    else:
217
 
        cmd = None
218
 
        c = []
219
 
 
220
 
    # combine global options into local
221
 
    for o in global_opt_table:
222
 
        c.append((o[0], o[1], options[o[1]], o[3]))
223
 
        
224
 
    try:
225
 
        args = utl.fancyopts(args, c, cmdoptions)
226
 
    except utl.getopt.GetoptError, inst:
227
 
        raise ParseError(cmd, inst)
228
 
 
229
 
    # separate global options back out
230
 
    for o in global_opt_table:
231
 
        n = o[1]
232
 
        options[n] = cmdoptions[n]
233
 
        del cmdoptions[n]
234
 
 
235
 
    utl.log_dev("args: %s\ncmdoptions: %s" 
236
 
              % (repr(args), repr(cmdoptions)))
237
 
    return (cmd, cmd and i[0] or None, args, options, cmdoptions)
238
 
 
239
 
def main_loop(args):
240
 
    cmd = None
241
 
    if not args:
242
 
        return 0
243
 
 
244
 
    try:
245
 
        cmd, func, cmd_args, ignore, cmd_options = parse(args)
246
 
 
247
 
        if func == crm.cd_:
248
 
            cmd_options["topic"] = cmd
249
 
 
250
 
        utl.log_dev("Func Command: %s" % cmd)
251
 
        utl.log_dev("Func Args: %s" % repr(cmd_args))
252
 
        utl.log_dev("Func Opts: %s" % repr(cmd_options))
253
 
            
254
 
        if not cmd:
255
 
            utl.log_dev(repr(args))
256
 
            return 0
257
 
        d = lambda: func(*cmd_args, **cmd_options)
258
 
        return d()
259
 
 
260
 
    except crm.HelpRequest, inst:
261
 
        help_(inst.args[0])
262
 
        return 0
263
 
 
264
 
    except crm.ReparseRequest:
265
 
        return main_loop(cmd_args)
266
 
 
267
 
    except ParseError, inst:
268
 
        if inst.args[0]:
269
 
            utl.log_err("%s: %s\n" % (inst.args[0], inst.args[1]))
270
 
            help_(inst.args[0])
271
 
        else:
272
 
            utl.log_err("%s\n" % inst.args[1])
273
 
            help_('short')
274
 
 
275
 
    except AmbiguousCommand, inst:
276
 
        utl.log_info("%s: command '%s' is ambiguous:\n    %s\n" 
277
 
                 % (" ".join(utl.topic_stack), inst.args[0], " ".join(inst.args[1])))
278
 
 
279
 
    except UnknownCommand, inst:
280
 
        utl.log_err("%s: unknown command '%s'\n" % (" ".join(utl.topic_stack), inst.args[0]))
281
 
        help_(utl.crm_topic)
282
 
 
283
 
    except IOError, inst:
284
 
        if hasattr(inst, "code"):
285
 
            utl.log_err("abort: %s\n" % inst)
286
 
        elif hasattr(inst, "reason"):
287
 
            utl.log_err("abort: error: %s\n" % inst.reason[1])
288
 
        elif hasattr(inst, "args"):
289
 
            utl.log_err("broken pipe\n")
290
 
        elif getattr(inst, "strerror", None):
291
 
            if getattr(inst, "filename", None):
292
 
                utl.log_err("abort: %s - %s\n" % (inst.strerror, inst.filename))
293
 
            else:
294
 
                utl.log_err("abort: %s\n" % inst.strerror)
295
 
        else:
296
 
            raise
297
 
    except OSError, inst:
298
 
        if hasattr(inst, "filename"):
299
 
            utl.log_err("abort: %s: %s\n" % (inst.strerror, inst.filename))
300
 
        else:
301
 
            utl.log_err("abort: %s\n" % inst.strerror)
302
 
            
303
 
    except TypeError, inst:
304
 
        # was this an argument error?
305
 
        tb = traceback.extract_tb(sys.exc_info()[2])
306
 
        if len(tb) > 2: # no
307
 
            raise
308
 
        utl.log_err((inst, "\n"))
309
 
        utl.log_err(("%s: invalid arguments\n" % cmd))
310
 
        help_(cmd)
311
 
        raise
312
 
    except SystemExit, inst:
313
 
        # Exit gracefully 
314
 
        utl.exit_(inst.code)
315
 
 
316
 
    except:
317
 
        utl.log_err("** unknown exception encountered, details follow\n")
318
 
        raise
319
 
        
320
 
    return -1
321
 
 
322
 
args = sys.argv[1:]
323
 
utl.init_readline(find_completer)
324
 
try:
325
 
    cmd, f_ignore, a_ignore, utl.global_opts, o_ignore = parse(args)
326
 
except:
327
 
    pass
328
 
 
329
 
if len(sys.argv) == 1:
330
 
    utl.global_opts["interactive"] = 1
331
 
elif not utl.global_opts.has_key("interactive"):
332
 
    utl.global_opts["interactive"] = 0
333
 
 
334
 
while True:
335
 
    rc = 0
336
 
    if args:
337
 
        utl.set_topic(utl.topic_stack[-1])
338
 
        rc = main_loop(args)
339
 
        utl.log_debug("rc: %s" % (repr(rc)))
340
 
 
341
 
    if not utl.global_opts["interactive"]:
342
 
        utl.exit_(rc)
343
 
 
344
 
    try:
345
 
        text = raw_input(" ".join(utl.topic_stack) +" # ")
346
 
        args = utl.create_argv(text)
347
 
 
348
 
    except QuotingError, inst:
349
 
        if inst.args[1]:
350
 
            utl.log_err("%s.  Found tokens: %s\n" % (inst.args[0], inst.args[1]))
351
 
        else:
352
 
            utl.log_err("%s\n" % inst.args[0])
353
 
 
354
 
    except KeyboardInterrupt:
355
 
        pass
356
 
 
357
 
    except EOFError:
358
 
        utl.exit_(0)
359
 
 
360
 
 
361