Package ganeti :: Package client :: Module gnt_debug
[hide private]
[frames] | no frames]

Source Code for Module ganeti.client.gnt_debug

  1  # 
  2  # 
  3   
  4  # Copyright (C) 2006, 2007, 2010, 2011, 2012 Google Inc. 
  5  # All rights reserved. 
  6  # 
  7  # Redistribution and use in source and binary forms, with or without 
  8  # modification, are permitted provided that the following conditions are 
  9  # met: 
 10  # 
 11  # 1. Redistributions of source code must retain the above copyright notice, 
 12  # this list of conditions and the following disclaimer. 
 13  # 
 14  # 2. Redistributions in binary form must reproduce the above copyright 
 15  # notice, this list of conditions and the following disclaimer in the 
 16  # documentation and/or other materials provided with the distribution. 
 17  # 
 18  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
 19  # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
 20  # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 21  # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 22  # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 23  # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 24  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 25  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 26  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 27  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 28  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 29   
 30  """Debugging commands""" 
 31   
 32  # pylint: disable=W0401,W0614,C0103 
 33  # W0401: Wildcard import ganeti.cli 
 34  # W0614: Unused import %s from wildcard import (since we need cli) 
 35  # C0103: Invalid name gnt-backup 
 36   
 37  import simplejson 
 38  import time 
 39  import socket 
 40  import logging 
 41   
 42  from ganeti.cli import * 
 43  from ganeti import cli 
 44  from ganeti import constants 
 45  from ganeti import opcodes 
 46  from ganeti import utils 
 47  from ganeti import errors 
 48  from ganeti import compat 
 49  from ganeti import ht 
 50  from ganeti import wconfd 
 51   
 52   
 53  #: Default fields for L{ListLocks} 
 54  _LIST_LOCKS_DEF_FIELDS = [ 
 55    "name", 
 56    "mode", 
 57    "owner", 
 58    "pending", 
 59    ] 
 60   
 61   
62 -def Delay(opts, args):
63 """Sleeps for a while 64 65 @param opts: the command line options selected by the user 66 @type args: list 67 @param args: should contain only one element, the duration 68 the sleep 69 @rtype: int 70 @return: the desired exit code 71 72 """ 73 delay = float(args[0]) 74 op = opcodes.OpTestDelay(duration=delay, 75 on_master=opts.on_master, 76 on_nodes=opts.on_nodes, 77 repeat=opts.repeat, 78 interruptible=opts.interruptible, 79 no_locks=opts.no_locks) 80 SubmitOrSend(op, opts) 81 82 return 0
83 84
85 -def GenericOpCodes(opts, args):
86 """Send any opcode to the master. 87 88 @param opts: the command line options selected by the user 89 @type args: list 90 @param args: should contain only one element, the path of 91 the file with the opcode definition 92 @rtype: int 93 @return: the desired exit code 94 95 """ 96 cl = cli.GetClient() 97 jex = cli.JobExecutor(cl=cl, verbose=opts.verbose, opts=opts) 98 99 job_cnt = 0 100 op_cnt = 0 101 if opts.timing_stats: 102 ToStdout("Loading...") 103 for job_idx in range(opts.rep_job): 104 for fname in args: 105 # pylint: disable=W0142 106 op_data = simplejson.loads(utils.ReadFile(fname)) 107 op_list = [opcodes.OpCode.LoadOpCode(val) for val in op_data] 108 op_list = op_list * opts.rep_op 109 jex.QueueJob("file %s/%d" % (fname, job_idx), *op_list) 110 op_cnt += len(op_list) 111 job_cnt += 1 112 113 if opts.timing_stats: 114 t1 = time.time() 115 ToStdout("Submitting...") 116 117 jex.SubmitPending(each=opts.each) 118 119 if opts.timing_stats: 120 t2 = time.time() 121 ToStdout("Executing...") 122 123 jex.GetResults() 124 if opts.timing_stats: 125 t3 = time.time() 126 ToStdout("C:op %4d" % op_cnt) 127 ToStdout("C:job %4d" % job_cnt) 128 ToStdout("T:submit %4.4f" % (t2 - t1)) 129 ToStdout("T:exec %4.4f" % (t3 - t2)) 130 ToStdout("T:total %4.4f" % (t3 - t1)) 131 return 0
132 133
134 -def TestAllocator(opts, args):
135 """Runs the test allocator opcode. 136 137 @param opts: the command line options selected by the user 138 @type args: list 139 @param args: should contain only one element, the iallocator name 140 @rtype: int 141 @return: the desired exit code 142 143 """ 144 try: 145 disks = [{ 146 constants.IDISK_SIZE: utils.ParseUnit(val), 147 constants.IDISK_MODE: constants.DISK_RDWR, 148 } for val in opts.disks.split(",")] 149 except errors.UnitParseError, err: 150 ToStderr("Invalid disks parameter '%s': %s", opts.disks, err) 151 return 1 152 153 nics = [val.split("/") for val in opts.nics.split(",")] 154 for row in nics: 155 while len(row) < 3: 156 row.append(None) 157 for i in range(3): 158 if row[i] == "": 159 row[i] = None 160 nic_dict = [{ 161 constants.INIC_MAC: v[0], 162 constants.INIC_IP: v[1], 163 # The iallocator interface defines a "bridge" item 164 "bridge": v[2], 165 } for v in nics] 166 167 if opts.tags is None: 168 opts.tags = [] 169 else: 170 opts.tags = opts.tags.split(",") 171 if opts.target_groups is None: 172 target_groups = [] 173 else: 174 target_groups = opts.target_groups 175 176 op = opcodes.OpTestAllocator(mode=opts.mode, 177 name=args[0], 178 instances=args, 179 memory=opts.memory, 180 disks=disks, 181 disk_template=opts.disk_template, 182 nics=nic_dict, 183 os=opts.os, 184 vcpus=opts.vcpus, 185 tags=opts.tags, 186 direction=opts.direction, 187 iallocator=opts.iallocator, 188 evac_mode=opts.evac_mode, 189 target_groups=target_groups, 190 spindle_use=opts.spindle_use, 191 count=opts.count) 192 result = SubmitOpCode(op, opts=opts) 193 ToStdout("%s" % result) 194 return 0
195 196
197 -def _TestJobDependency(opts):
198 """Tests job dependencies. 199 200 """ 201 ToStdout("Testing job dependencies") 202 203 try: 204 cl = cli.GetClient() 205 SubmitOpCode(opcodes.OpTestDelay(duration=0, depends=[(-1, None)]), cl=cl) 206 except errors.GenericError, err: 207 if opts.debug: 208 ToStdout("Ignoring error for 'wrong dependencies' test: %s", err) 209 else: 210 raise errors.OpExecError("Submitting plain opcode with relative job ID" 211 " did not fail as expected") 212 213 # TODO: Test dependencies on errors 214 jobs = [ 215 [opcodes.OpTestDelay(duration=1)], 216 [opcodes.OpTestDelay(duration=1, 217 depends=[(-1, [])])], 218 [opcodes.OpTestDelay(duration=1, 219 depends=[(-2, [constants.JOB_STATUS_SUCCESS])])], 220 [opcodes.OpTestDelay(duration=1, 221 depends=[])], 222 [opcodes.OpTestDelay(duration=1, 223 depends=[(-2, [constants.JOB_STATUS_SUCCESS])])], 224 ] 225 226 # Function for checking result 227 check_fn = ht.TListOf(ht.TAnd(ht.TIsLength(2), 228 ht.TItems([ht.TBool, 229 ht.TOr(ht.TNonEmptyString, 230 ht.TJobId)]))) 231 232 cl = cli.GetClient() 233 result = cl.SubmitManyJobs(jobs) 234 if not check_fn(result): 235 raise errors.OpExecError("Job submission doesn't match %s: %s" % 236 (check_fn, result)) 237 238 # Wait for jobs to finish 239 jex = JobExecutor(cl=cl, opts=opts) 240 241 for (status, job_id) in result: 242 jex.AddJobId(None, status, job_id) 243 244 job_results = jex.GetResults() 245 if not compat.all(row[0] for row in job_results): 246 raise errors.OpExecError("At least one of the submitted jobs failed: %s" % 247 job_results) 248 249 # Get details about jobs 250 data = cl.QueryJobs([job_id for (_, job_id) in result], 251 ["id", "opexec", "ops"]) 252 data_job_id = [job_id for (job_id, _, _) in data] 253 data_opexec = [opexec for (_, opexec, _) in data] 254 data_op = [[opcodes.OpCode.LoadOpCode(op) for op in ops] 255 for (_, _, ops) in data] 256 257 assert compat.all(not op.depends or len(op.depends) == 1 258 for ops in data_op 259 for op in ops) 260 261 # Check resolved job IDs in dependencies 262 for (job_idx, res_jobdep) in [(1, data_job_id[0]), 263 (2, data_job_id[0]), 264 (4, data_job_id[2])]: 265 if data_op[job_idx][0].depends[0][0] != res_jobdep: 266 raise errors.OpExecError("Job %s's opcode doesn't depend on correct job" 267 " ID (%s)" % (job_idx, res_jobdep)) 268 269 # Check execution order 270 if not (data_opexec[0] <= data_opexec[1] and 271 data_opexec[0] <= data_opexec[2] and 272 data_opexec[2] <= data_opexec[4]): 273 raise errors.OpExecError("Jobs did not run in correct order: %s" % data) 274 275 assert len(jobs) == 5 and compat.all(len(ops) == 1 for ops in jobs) 276 277 ToStdout("Job dependency tests were successful")
278 279
280 -def _TestJobSubmission(opts):
281 """Tests submitting jobs. 282 283 """ 284 ToStdout("Testing job submission") 285 286 testdata = [ 287 (0, 0, constants.OP_PRIO_LOWEST), 288 (0, 0, constants.OP_PRIO_HIGHEST), 289 ] 290 291 for priority in (constants.OP_PRIO_SUBMIT_VALID | 292 frozenset([constants.OP_PRIO_LOWEST, 293 constants.OP_PRIO_HIGHEST])): 294 for offset in [-1, +1]: 295 testdata.extend([ 296 (0, 0, priority + offset), 297 (3, 0, priority + offset), 298 (0, 3, priority + offset), 299 (4, 2, priority + offset), 300 ]) 301 302 for before, after, failpriority in testdata: 303 ops = [] 304 ops.extend([opcodes.OpTestDelay(duration=0) for _ in range(before)]) 305 ops.append(opcodes.OpTestDelay(duration=0, priority=failpriority)) 306 ops.extend([opcodes.OpTestDelay(duration=0) for _ in range(after)]) 307 308 try: 309 cl = cli.GetClient() 310 cl.SubmitJob(ops) 311 except errors.GenericError, err: 312 if opts.debug: 313 ToStdout("Ignoring error for 'wrong priority' test: %s", err) 314 else: 315 raise errors.OpExecError("Submitting opcode with priority %s did not" 316 " fail when it should (allowed are %s)" % 317 (failpriority, constants.OP_PRIO_SUBMIT_VALID)) 318 319 jobs = [ 320 [opcodes.OpTestDelay(duration=0), 321 opcodes.OpTestDelay(duration=0, dry_run=False), 322 opcodes.OpTestDelay(duration=0, dry_run=True)], 323 ops, 324 ] 325 try: 326 cl = cli.GetClient() 327 cl.SubmitManyJobs(jobs) 328 except errors.GenericError, err: 329 if opts.debug: 330 ToStdout("Ignoring error for 'wrong priority' test: %s", err) 331 else: 332 raise errors.OpExecError("Submitting manyjobs with an incorrect one" 333 " did not fail when it should.") 334 ToStdout("Job submission tests were successful")
335 336
337 -class _JobQueueTestReporter(cli.StdioJobPollReportCb):
338 - def __init__(self):
339 """Initializes this class. 340 341 """ 342 cli.StdioJobPollReportCb.__init__(self) 343 self._expected_msgcount = 0 344 self._all_testmsgs = [] 345 self._testmsgs = None 346 self._job_id = None
347
348 - def GetTestMessages(self):
349 """Returns all test log messages received so far. 350 351 """ 352 return self._all_testmsgs
353
354 - def GetJobId(self):
355 """Returns the job ID. 356 357 """ 358 return self._job_id
359
360 - def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
361 """Handles a log message. 362 363 """ 364 if self._job_id is None: 365 self._job_id = job_id 366 elif self._job_id != job_id: 367 raise errors.ProgrammerError("The same reporter instance was used for" 368 " more than one job") 369 370 if log_type == constants.ELOG_JQUEUE_TEST: 371 (sockname, test, arg) = log_msg 372 return self._ProcessTestMessage(job_id, sockname, test, arg) 373 374 elif (log_type == constants.ELOG_MESSAGE and 375 log_msg.startswith(constants.JQT_MSGPREFIX)): 376 if self._testmsgs is None: 377 raise errors.OpExecError("Received test message without a preceding" 378 " start message") 379 testmsg = log_msg[len(constants.JQT_MSGPREFIX):] 380 self._testmsgs.append(testmsg) 381 self._all_testmsgs.append(testmsg) 382 return 383 384 return cli.StdioJobPollReportCb.ReportLogMessage(self, job_id, serial, 385 timestamp, log_type, 386 log_msg)
387
388 - def _ProcessTestMessage(self, job_id, sockname, test, arg):
389 """Handles a job queue test message. 390 391 """ 392 if test not in constants.JQT_ALL: 393 raise errors.OpExecError("Received invalid test message %s" % test) 394 395 sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 396 try: 397 sock.settimeout(30.0) 398 399 logging.debug("Connecting to %s", sockname) 400 sock.connect(sockname) 401 402 logging.debug("Checking status") 403 jobdetails = cli.GetClient().QueryJobs([job_id], ["status"])[0] 404 if not jobdetails: 405 raise errors.OpExecError("Can't find job %s" % job_id) 406 407 status = jobdetails[0] 408 409 logging.debug("Status of job %s is %s", job_id, status) 410 411 if test == constants.JQT_EXPANDNAMES: 412 if status != constants.JOB_STATUS_WAITING: 413 raise errors.OpExecError("Job status while expanding names is '%s'," 414 " not '%s' as expected" % 415 (status, constants.JOB_STATUS_WAITING)) 416 elif test in (constants.JQT_EXEC, constants.JQT_LOGMSG): 417 if status != constants.JOB_STATUS_RUNNING: 418 raise errors.OpExecError("Job status while executing opcode is '%s'," 419 " not '%s' as expected" % 420 (status, constants.JOB_STATUS_RUNNING)) 421 422 if test == constants.JQT_STARTMSG: 423 logging.debug("Expecting %s test messages", arg) 424 self._testmsgs = [] 425 elif test == constants.JQT_LOGMSG: 426 if len(self._testmsgs) != arg: 427 raise errors.OpExecError("Received %s test messages when %s are" 428 " expected" % (len(self._testmsgs), arg)) 429 finally: 430 logging.debug("Closing socket") 431 sock.close()
432 433
434 -def TestJobqueue(opts, _):
435 """Runs a few tests on the job queue. 436 437 """ 438 _TestJobSubmission(opts) 439 _TestJobDependency(opts) 440 441 (TM_SUCCESS, 442 TM_MULTISUCCESS, 443 TM_FAIL, 444 TM_PARTFAIL) = range(4) 445 TM_ALL = compat.UniqueFrozenset([ 446 TM_SUCCESS, 447 TM_MULTISUCCESS, 448 TM_FAIL, 449 TM_PARTFAIL, 450 ]) 451 452 for mode in TM_ALL: 453 test_messages = [ 454 "Testing mode %s" % mode, 455 "Hello World", 456 "A", 457 "", 458 "B", 459 "Foo|bar|baz", 460 utils.TimestampForFilename(), 461 ] 462 463 fail = mode in (TM_FAIL, TM_PARTFAIL) 464 465 if mode == TM_PARTFAIL: 466 ToStdout("Testing partial job failure") 467 ops = [ 468 opcodes.OpTestJqueue(notify_waitlock=True, notify_exec=True, 469 log_messages=test_messages, fail=False), 470 opcodes.OpTestJqueue(notify_waitlock=True, notify_exec=True, 471 log_messages=test_messages, fail=False), 472 opcodes.OpTestJqueue(notify_waitlock=True, notify_exec=True, 473 log_messages=test_messages, fail=True), 474 opcodes.OpTestJqueue(notify_waitlock=True, notify_exec=True, 475 log_messages=test_messages, fail=False), 476 ] 477 expect_messages = 3 * [test_messages] 478 expect_opstatus = [ 479 constants.OP_STATUS_SUCCESS, 480 constants.OP_STATUS_SUCCESS, 481 constants.OP_STATUS_ERROR, 482 constants.OP_STATUS_ERROR, 483 ] 484 expect_resultlen = 2 485 elif mode == TM_MULTISUCCESS: 486 ToStdout("Testing multiple successful opcodes") 487 ops = [ 488 opcodes.OpTestJqueue(notify_waitlock=True, notify_exec=True, 489 log_messages=test_messages, fail=False), 490 opcodes.OpTestJqueue(notify_waitlock=True, notify_exec=True, 491 log_messages=test_messages, fail=False), 492 ] 493 expect_messages = 2 * [test_messages] 494 expect_opstatus = [ 495 constants.OP_STATUS_SUCCESS, 496 constants.OP_STATUS_SUCCESS, 497 ] 498 expect_resultlen = 2 499 else: 500 if mode == TM_SUCCESS: 501 ToStdout("Testing job success") 502 expect_opstatus = [constants.OP_STATUS_SUCCESS] 503 elif mode == TM_FAIL: 504 ToStdout("Testing job failure") 505 expect_opstatus = [constants.OP_STATUS_ERROR] 506 else: 507 raise errors.ProgrammerError("Unknown test mode %s" % mode) 508 509 ops = [ 510 opcodes.OpTestJqueue(notify_waitlock=True, 511 notify_exec=True, 512 log_messages=test_messages, 513 fail=fail), 514 ] 515 expect_messages = [test_messages] 516 expect_resultlen = 1 517 518 cl = cli.GetClient() 519 cli.SetGenericOpcodeOpts(ops, opts) 520 521 # Send job to master daemon 522 job_id = cli.SendJob(ops, cl=cl) 523 524 reporter = _JobQueueTestReporter() 525 results = None 526 527 try: 528 results = cli.PollJob(job_id, cl=cl, reporter=reporter) 529 except errors.OpExecError, err: 530 if not fail: 531 raise 532 ToStdout("Ignoring error for 'job fail' test: %s", err) 533 else: 534 if fail: 535 raise errors.OpExecError("Job didn't fail when it should") 536 537 # Check length of result 538 if fail: 539 if results is not None: 540 raise errors.OpExecError("Received result from failed job") 541 elif len(results) != expect_resultlen: 542 raise errors.OpExecError("Received %s results (%s), expected %s" % 543 (len(results), results, expect_resultlen)) 544 545 # Check received log messages 546 all_messages = [i for j in expect_messages for i in j] 547 if reporter.GetTestMessages() != all_messages: 548 raise errors.OpExecError("Received test messages don't match input" 549 " (input %r, received %r)" % 550 (all_messages, reporter.GetTestMessages())) 551 552 # Check final status 553 reported_job_id = reporter.GetJobId() 554 if reported_job_id != job_id: 555 raise errors.OpExecError("Reported job ID %s doesn't match" 556 "submission job ID %s" % 557 (reported_job_id, job_id)) 558 559 jobdetails = cli.GetClient().QueryJobs([job_id], ["status", "opstatus"])[0] 560 if not jobdetails: 561 raise errors.OpExecError("Can't find job %s" % job_id) 562 563 if fail: 564 exp_status = constants.JOB_STATUS_ERROR 565 else: 566 exp_status = constants.JOB_STATUS_SUCCESS 567 568 (final_status, final_opstatus) = jobdetails 569 if final_status != exp_status: 570 raise errors.OpExecError("Final job status is %s, not %s as expected" % 571 (final_status, exp_status)) 572 if len(final_opstatus) != len(ops): 573 raise errors.OpExecError("Did not receive status for all opcodes (got %s," 574 " expected %s)" % 575 (len(final_opstatus), len(ops))) 576 if final_opstatus != expect_opstatus: 577 raise errors.OpExecError("Opcode status is %s, expected %s" % 578 (final_opstatus, expect_opstatus)) 579 580 ToStdout("Job queue test successful") 581 582 return 0
583 584
585 -def ListLocks(opts, args): # pylint: disable=W0613
586 """List all locks. 587 588 @param opts: the command line options selected by the user 589 @type args: list 590 @param args: should be an empty list 591 @rtype: int 592 @return: the desired exit code 593 594 """ 595 selected_fields = ParseFields(opts.output, _LIST_LOCKS_DEF_FIELDS) 596 597 def _DashIfNone(fn): 598 def wrapper(value): 599 if not value: 600 return "-" 601 return fn(value) 602 return wrapper 603 604 def _FormatPending(value): 605 """Format pending acquires. 606 607 """ 608 return utils.CommaJoin("%s:%s" % (mode, ",".join(map(str, threads))) 609 for mode, threads in value) 610 611 # Format raw values 612 fmtoverride = { 613 "mode": (_DashIfNone(str), False), 614 "owner": (_DashIfNone(",".join), False), 615 "pending": (_DashIfNone(_FormatPending), False), 616 } 617 618 while True: 619 ret = GenericList(constants.QR_LOCK, selected_fields, None, None, 620 opts.separator, not opts.no_headers, 621 format_override=fmtoverride, verbose=opts.verbose) 622 623 if ret != constants.EXIT_SUCCESS: 624 return ret 625 626 if not opts.interval: 627 break 628 629 ToStdout("") 630 time.sleep(opts.interval) 631 632 return 0 633 634
635 -def Wconfd(opts, args): # pylint: disable=W0613
636 """Send commands to WConfD. 637 638 @param opts: the command line options selected by the user 639 @type args: list 640 @param args: the command to send, followed by the command-specific arguments 641 @rtype: int 642 @return: the desired exit code 643 644 """ 645 if args[0] == "echo": 646 if len(args) != 2: 647 ToStderr("Command 'echo' takes only precisely argument.") 648 return 1 649 result = wconfd.Client().Echo(args[1]) 650 print "Answer: %s" % (result,) 651 elif args[0] == "cleanuplocks": 652 if len(args) != 1: 653 ToStderr("Command 'cleanuplocks' takes no arguments.") 654 return 1 655 wconfd.Client().CleanupLocks() 656 print "Stale locks cleaned up." 657 elif args[0] == "listlocks": 658 if len(args) != 2: 659 ToStderr("Command 'listlocks' takes precisely one argument.") 660 return 1 661 wconfdcontext = (int(args[1]), 662 utils.livelock.GuessLockfileFor("masterd_1")) 663 result = wconfd.Client().ListLocks(wconfdcontext) 664 print "Answer: %s" % (result,) 665 elif args[0] == "listalllocks": 666 if len(args) != 1: 667 ToStderr("Command 'listalllocks' takes no arguments.") 668 return 1 669 result = wconfd.Client().ListAllLocks() 670 print "Answer: %s" % (result,) 671 elif args[0] == "listalllocksowners": 672 if len(args) != 1: 673 ToStderr("Command 'listalllocks' takes no arguments.") 674 return 1 675 result = wconfd.Client().ListAllLocksOwners() 676 print "Answer: %s" % (result,) 677 elif args[0] == "flushconfig": 678 if len(args) != 1: 679 ToStderr("Command 'flushconfig' takes no arguments.") 680 return 1 681 wconfd.Client().FlushConfig() 682 print "Configuration flushed." 683 else: 684 ToStderr("Command '%s' not supported", args[0]) 685 return 1 686 687 return 0 688 689 690 commands = { 691 "delay": ( 692 Delay, [ArgUnknown(min=1, max=1)], 693 [cli_option("--no-master", dest="on_master", default=True, 694 action="store_false", help="Do not sleep in the master code"), 695 cli_option("-n", dest="on_nodes", default=[], 696 action="append", help="Select nodes to sleep on"), 697 cli_option("-r", "--repeat", type="int", default="0", dest="repeat", 698 help="Number of times to repeat the sleep"), 699 cli_option("-i", "--interruptible", default=False, dest="interruptible", 700 action="store_true", 701 help="Allows the opcode to be interrupted by using a domain " 702 "socket"), 703 cli_option("-l", "--no-locks", default=False, dest="no_locks", 704 action="store_true", 705 help="Don't take locks while performing the delay"), 706 DRY_RUN_OPT, PRIORITY_OPT] + SUBMIT_OPTS, 707 "[opts...] <duration>", "Executes a TestDelay OpCode"), 708 "submit-job": ( 709 GenericOpCodes, [ArgFile(min=1)], 710 [VERBOSE_OPT, 711 cli_option("--op-repeat", type="int", default="1", dest="rep_op", 712 help="Repeat the opcode sequence this number of times"), 713 cli_option("--job-repeat", type="int", default="1", dest="rep_job", 714 help="Repeat the job this number of times"), 715 cli_option("--timing-stats", default=False, 716 action="store_true", help="Show timing stats"), 717 cli_option("--each", default=False, action="store_true", 718 help="Submit each job separately"), 719 DRY_RUN_OPT, PRIORITY_OPT, 720 ], 721 "<op_list_file...>", "Submits jobs built from json files" 722 " containing a list of serialized opcodes"), 723 "iallocator": ( 724 TestAllocator, [ArgUnknown(min=1)], 725 [cli_option("--dir", dest="direction", default=constants.IALLOCATOR_DIR_IN, 726 choices=list(constants.VALID_IALLOCATOR_DIRECTIONS), 727 help="Show allocator input (in) or allocator" 728 " results (out)"), 729 IALLOCATOR_OPT, 730 cli_option("-m", "--mode", default="relocate", 731 choices=list(constants.VALID_IALLOCATOR_MODES), 732 help=("Request mode (one of %s)" % 733 utils.CommaJoin(constants.VALID_IALLOCATOR_MODES))), 734 cli_option("--memory", default=128, type="unit", 735 help="Memory size for the instance (MiB)"), 736 cli_option("--disks", default="4096,4096", 737 help="Comma separated list of disk sizes (MiB)"), 738 DISK_TEMPLATE_OPT, 739 cli_option("--nics", default="00:11:22:33:44:55", 740 help="Comma separated list of nics, each nic" 741 " definition is of form mac/ip/bridge, if" 742 " missing values are replace by None"), 743 OS_OPT, 744 cli_option("-p", "--vcpus", default=1, type="int", 745 help="Select number of VCPUs for the instance"), 746 cli_option("--tags", default=None, 747 help="Comma separated list of tags"), 748 cli_option("--evac-mode", default=constants.NODE_EVAC_ALL, 749 choices=list(constants.NODE_EVAC_MODES), 750 help=("Node evacuation mode (one of %s)" % 751 utils.CommaJoin(constants.NODE_EVAC_MODES))), 752 cli_option("--target-groups", help="Target groups for relocation", 753 default=[], action="append"), 754 cli_option("--spindle-use", help="How many spindles to use", 755 default=1, type="int"), 756 cli_option("--count", help="How many instances to allocate", 757 default=2, type="int"), 758 DRY_RUN_OPT, PRIORITY_OPT, 759 ], 760 "{opts...} <instance>", "Executes a TestAllocator OpCode"), 761 "test-jobqueue": ( 762 TestJobqueue, ARGS_NONE, [PRIORITY_OPT], 763 "", "Test a few aspects of the job queue"), 764 "locks": ( 765 ListLocks, ARGS_NONE, 766 [NOHDR_OPT, SEP_OPT, FIELDS_OPT, INTERVAL_OPT, VERBOSE_OPT], 767 "[--interval N]", "Show a list of locks in the master daemon"), 768 "wconfd": ( 769 Wconfd, [ArgUnknown(min=1)], [], 770 "<cmd> <args...>", "Directly talk to WConfD"), 771 } 772 773 #: dictionary with aliases for commands 774 aliases = { 775 "allocator": "iallocator", 776 } 777 778
779 -def Main():
780 return GenericMain(commands, aliases=aliases)
781