/usr/lib/python2.7/dist-packages/crmsh/main.py is in crmsh 2.2.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 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 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 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 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 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 282 283 284 285 286 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 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | # Copyright (C) 2008-2011 Dejan Muhamedagic <dmuhamedagic@suse.de>
# See COPYING for license information.
import sys
import os
import atexit
import random
from . import config
from . import options
from . import constants
from .msg import err_buf, common_err
from . import clidisplay
from . import term
from . import utils
from . import userdir
from . import ui_root
from . import ui_context
random.seed()
def load_rc(context, rcfile):
# only load the RC file if there is no new-style user config
if config.has_user_config():
return
try:
f = open(rcfile)
except:
return
save_stdin = sys.stdin
sys.stdin = f
while True:
inp = utils.multi_input()
if inp is None:
break
try:
if not context.run(inp):
raise ValueError("Error in RC file: " + rcfile)
except ValueError as msg:
common_err(msg)
f.close()
sys.stdin = save_stdin
def exit_handler():
'''
Write the history file. Remove tmp files.
'''
if options.interactive and not options.batch:
try:
from readline import write_history_file
write_history_file(userdir.HISTORY_FILE)
except:
pass
# prefer the user set PATH
def envsetup():
mybinpath = os.path.dirname(sys.argv[0])
path = os.environ["PATH"].split(':')
for p in mybinpath, config.path.crm_daemon_dir:
if p not in path:
os.environ['PATH'] = "%s:%s" % (os.environ['PATH'], p)
# three modes: interactive (no args supplied), batch (input from
# a file), half-interactive (args supplied, but not batch)
def cib_prompt():
shadow = utils.get_cib_in_use()
if not shadow:
return constants.live_cib_prompt
if constants.tmp_cib:
return constants.tmp_cib_prompt
return shadow
def make_option_parser():
from optparse import OptionParser
parser = OptionParser(usage="""%prog [-h|--help] [OPTIONS] [SUBCOMMAND ARGS...]
or %prog help SUBCOMMAND
For a list of available subcommands, use %prog help.
Use %prog without arguments for an interactive session.
Call a subcommand directly for a "single-shot" use.
Call %prog with a level name as argument to start an interactive
session from that level.
See the crm(8) man page or call %prog help for more details.""",
version="%prog " + config.CRM_VERSION)
parser.disable_interspersed_args()
parser.add_option("-f", "--file", dest="filename", metavar="FILE",
help="Load commands from the given file. If a dash (-) " +
"is used in place of a file name, crm will read commands " +
"from the shell standard input (stdin).")
parser.add_option("-c", "--cib", dest="cib", metavar="CIB",
help="Start the session using the given shadow CIB file. " +
"Equivalent to `cib use <CIB>`.")
parser.add_option("-D", "--display", dest="display", metavar="OUTPUT_TYPE",
help="Choose one of the output options: plain, color-always, color, or uppercase. " +
"The default is color if the terminal emulation supports colors, " +
"else plain.")
parser.add_option("-F", "--force", action="store_true", default=False, dest="force",
help="Make crm proceed with applying changes where it would normally " +
"ask the user to confirm before proceeding. This option is mainly useful " +
"in scripts, and should be used with care.")
parser.add_option("-n", "--no", action="store_true", default=False, dest="ask_no",
help="Automatically answer no when prompted")
parser.add_option("-w", "--wait", action="store_true", default=False, dest="wait",
help="Make crm wait for the cluster transition to finish " +
"(for the changes to take effect) after each processed line.")
parser.add_option("-H", "--history", dest="history", metavar="DIR|FILE|SESSION",
help="A directory or file containing a cluster report to load " +
"into history, or the name of a previously saved history session.")
parser.add_option("-d", "--debug", action="store_true", default=False, dest="debug",
help="Print verbose debugging information.")
parser.add_option("-R", "--regression-tests", action="store_true", default=False,
dest="regression_tests",
help="Enables extra verbose trace logging used by the regression " +
"tests. Logs all external calls made by crmsh.")
parser.add_option("--scriptdir", dest="scriptdir", metavar="DIR",
help="Extra directory where crm looks for cluster scripts, or a list " +
"of directories separated by semi-colons (e.g. /dir1;/dir2;etc.).")
parser.add_option("-X", dest="profile", metavar="PROFILE",
help="Collect profiling data and save in PROFILE.")
return parser
option_parser = make_option_parser()
def usage(rc):
option_parser.print_usage(file=(sys.stderr if rc != 0 else sys.stdout))
sys.exit(rc)
def set_interactive():
'''Set the interactive option only if we're on a tty.'''
if utils.can_ask():
options.interactive = True
def compatibility_setup():
if not utils.is_pcmk_118():
del constants.attr_defaults["node"]
constants.cib_no_section_rc = 22
def add_quotes(args):
'''
Add quotes if there's whitespace in one of the
arguments; so that the user doesn't need to protect the
quotes.
If there are two kinds of quotes which actually _survive_
the getopt, then we're _probably_ screwed.
At any rate, stuff like ... '..."..."'
as well as '...\'...\'' do work.
'''
l = []
for s in args:
if config.core.add_quotes and ' ' in s:
q = '"' in s and "'" or '"'
if q not in s:
s = "%s%s%s" % (q, s, q)
l.append(s)
return l
def handle_noninteractive_use(context, user_args):
"""
returns: either a status code of 0 or 1, or
None to indicate that nothing was done here.
"""
if options.shadow:
if not context.run("cib use " + options.shadow):
return 1
# this special case is silly, but we have to keep it to
# preserve the backward compatibility
if len(user_args) == 1 and user_args[0].startswith("conf"):
if not context.run("configure"):
return 1
elif len(user_args) > 0:
# we're not sure yet whether it's an interactive session or not
# (single-shot commands aren't)
err_buf.reset_lineno()
options.interactive = False
l = add_quotes(user_args)
if context.run(' '.join(l)):
# if the user entered a level, then just continue
if not context.previous_level():
return 0
set_interactive()
if options.interactive:
err_buf.reset_lineno(-1)
else:
return 1
return None
def render_prompt(context):
rendered_prompt = constants.prompt
if options.interactive and not options.batch:
# TODO: fix how color interacts with readline,
# seems the color prompt messes it up
promptstr = "crm(%s)%s# " % (cib_prompt(), context.prompt())
constants.prompt = promptstr
if clidisplay.colors_enabled():
rendered_prompt = term.render(clidisplay.prompt(promptstr))
else:
rendered_prompt = promptstr
return rendered_prompt
def setup_context(context):
if options.input_file and options.input_file != "-":
try:
sys.stdin = open(options.input_file)
except IOError as msg:
common_err(msg)
usage(2)
if options.interactive and not options.batch:
context.setup_readline()
def main_input_loop(context, user_args):
"""
Main input loop for crmsh. Parses input
line by line.
"""
compatibility_setup()
rc = handle_noninteractive_use(context, user_args)
if rc is not None:
return rc
setup_context(context)
rc = 0
while True:
try:
inp = utils.multi_input(render_prompt(context))
if inp is None:
if options.interactive:
rc = 0
context.quit(rc)
try:
if not context.run(inp):
rc = 1
except ValueError as msg:
rc = 1
common_err(msg)
except KeyboardInterrupt:
if options.interactive and not options.batch:
print("Ctrl-C, leaving")
context.quit(1)
return rc
def compgen():
args = sys.argv[2:]
if len(args) < 2:
return
options.shell_completion = True
# point = int(args[0])
line = args[1]
# remove [*]crm from commandline
idx = line.find('crm')
if idx >= 0:
line = line[idx+3:].lstrip()
options.interactive = False
ui = ui_root.Root()
context = ui_context.Context(ui)
last_word = line.rsplit(' ', 1)
if len(last_word) > 1 and ':' in last_word[1]:
idx = last_word[1].rfind(':')
for w in context.complete(line):
print(w[idx+1:])
else:
for w in context.complete(line):
print(w)
def parse_options():
opts, args = option_parser.parse_args()
config.core.debug = "yes" if opts.debug else config.core.debug
options.profile = opts.profile or options.profile
options.regression_tests = opts.regression_tests or options.regression_tests
config.color.style = opts.display or config.color.style
config.core.force = opts.force or config.core.force
if opts.filename:
err_buf.reset_lineno()
options.input_file, options.batch, options.interactive = opts.filename, True, False
options.history = opts.history or options.history
config.core.wait = opts.wait or config.core.wait
options.shadow = opts.cib or options.shadow
options.scriptdir = opts.scriptdir or options.scriptdir
options.ask_no = opts.ask_no
return args
def profile_run(context, user_args):
import cProfile
cProfile.runctx('main_input_loop(context, user_args)',
globals(),
{'context': context, 'user_args': user_args},
filename=options.profile)
# print how to use the profile file, but don't disturb
# the regression tests
if not options.regression_tests:
stats_cmd = "; ".join(['import pstats',
's = pstats.Stats("%s")' % options.profile,
's.sort_stats("cumulative").print_stats()'])
print("python -c '%s' | less" % (stats_cmd))
return 0
def run():
try:
if len(sys.argv) >= 2 and sys.argv[1] == '--compgen':
compgen()
return 0
envsetup()
userdir.mv_user_files()
ui = ui_root.Root()
context = ui_context.Context(ui)
load_rc(context, userdir.RC_FILE)
atexit.register(exit_handler)
options.interactive = utils.can_ask()
if not options.interactive:
err_buf.reset_lineno()
options.batch = True
user_args = parse_options()
term._init()
if options.profile:
return profile_run(context, user_args)
else:
return main_input_loop(context, user_args)
except KeyboardInterrupt:
print("Ctrl-C, leaving")
sys.exit(1)
except ValueError as e:
if config.core.debug:
import traceback
traceback.print_exc()
common_err(str(e))
# vim:ts=4:sw=4:et:
|