2
2
# Copyright (C) 2013-2018 Kristoffer Gronlund <kgronlund@suse.com>
3
3
# See COPYING for license information.
4
4
5
+ import re
5
6
from . import command
6
7
from . import completers as compl
7
8
from . import constants
@@ -172,7 +173,8 @@ def is_resource(obj):
172
173
return True
173
174
174
175
175
- _attrcmds = compl .choice (['delete' , 'set' , 'show' ])
176
+ ATTR_OPERATION_CMDS = ('delete' , 'set' , 'show' )
177
+ _attrcmds = compl .choice (ATTR_OPERATION_CMDS )
176
178
_raoperations = compl .choice (constants .ra_operations )
177
179
178
180
@@ -490,20 +492,23 @@ def do_failcount(self, context, rsc, cmd, node, value=None, operation=None, inte
490
492
failcount <rsc> delete <node>
491
493
failcount <rsc> show <node>"""
492
494
def sec_to_ms (s ):
493
- return s + '000'
495
+ return '0' if s == '0' else s + '000'
494
496
495
497
def ms_to_sec (m ):
496
- return m [:len (m )- 3 ]
498
+ return '0' if m == '0' else str (int (m ) // 1000 )
499
+
500
+ USAGE = "Usage: failcount <rsc> set <node> <value> [operation] [interval]"
497
501
498
502
if rsc not in compl .resources ():
499
- context .warning ("Resource {} not exists in this cluster" . format ( rsc ) )
503
+ logger .warning ("Resource %s not in this cluster" , rsc )
500
504
return
501
- valid_cmd_list = ["set" , "delete" , "show" ]
502
- if cmd not in valid_cmd_list :
503
- context .fatal_error ("{} is not valid command(should be one of {})" .format (cmd , valid_cmd_list ))
505
+ if cmd not in ATTR_OPERATION_CMDS :
506
+ context .fatal_error (f"{ cmd } is not valid command(should be one of { ', ' .join (ATTR_OPERATION_CMDS )} )" )
504
507
nodeid = utils .get_nodeid_from_name (node )
505
508
if nodeid is None :
506
- context .fatal_error ("Node {} not in this cluster" .format (node ))
509
+ context .fatal_error (f"Node { node } not in this cluster" )
510
+ if value and (not value .isdigit () and value != "INFINITY" ):
511
+ context .fatal_error ("value should be a non-negative integer or 'INFINITY'" )
507
512
508
513
if cmd == "set" :
509
514
# query the current failcount status
@@ -513,46 +518,50 @@ def ms_to_sec(m):
513
518
context .fatal_error (err )
514
519
515
520
# try to get failcount dict {operation:interval}
516
- import re
517
- failcount_res = re .findall (r'fail-count-{}#(.*)_([0-9]+)' .format (rsc ), out )
518
- if not failcount_res :
519
- return True if value and int (value ) == 0 else False
520
- failcount_dict = dict (failcount_res )
521
-
522
- # validate for operation and interval
523
- if operation and operation not in failcount_dict .keys ():
524
- context .fatal_error ("Usage: failcount <rsc> set <node> <value> [operation] [interval]\n \
525
- Should specify operation between \" {}\" " .format (' ' .join (failcount_dict .keys ())))
526
- if (operation and interval ) and (operation , sec_to_ms (interval )) not in failcount_res :
527
- context .fatal_error ("Usage: failcount <rsc> set <node> <value> [operation] [interval]\n \
528
- Should specify (operation, interval) between {}" .\
529
- format ([(op , ms_to_sec (inter )) for op , inter in failcount_res ]))
521
+ failcount_dict = dict (re .findall (rf'fail-count-{ rsc } #(.*)_([0-9]+)' , out ))
522
+ if failcount_dict :
523
+ # validate for operation and interval
524
+ if operation and operation not in failcount_dict :
525
+ context .fatal_error (f"Should specify operation between ({ ', ' .join (failcount_dict .keys ())} )\n { USAGE } " )
526
+ if (operation and interval ) and (operation , sec_to_ms (interval )) not in failcount_dict .items ():
527
+ failcount_items = [(op , ms_to_sec (inter )) for op , inter in failcount_dict .items ()]
528
+ context .fatal_error (f"Should specify (operation, interval) between { failcount_items } \n { USAGE } " )
529
+ else :
530
+ # no failcount entry for this resource and node
531
+ if operation and interval :
532
+ rsc = f'{ rsc } #{ operation } _{ sec_to_ms (interval )} '
533
+ else :
534
+ # when no failcount entry, it's no harm to give a warning and return true
535
+ # https://bugzilla.suse.com/show_bug.cgi?id=1180332#c11
536
+ logger .warning ("Should specify operation and interval\n %s" , USAGE )
537
+ return
530
538
531
539
# just one failcount entry
532
- if len (failcount_res ) == 1 :
533
- operation = failcount_res [0 ][0 ]
534
- interval = failcount_dict [operation ]
535
- rsc = '{}#{}_{}' .format (rsc , operation , interval )
540
+ if len (failcount_dict ) == 1 :
541
+ operation , interval_in_ms = failcount_dict .popitem ()
542
+ rsc = f'{ rsc } #{ operation } _{ interval_in_ms } '
536
543
537
544
# multiple failcount entries for this resource and node
538
- if len (failcount_res ) > 1 :
545
+ if len (failcount_dict ) > 1 :
539
546
if operation and interval :
540
- rsc = '{ }#{}_{}' . format ( rsc , operation , sec_to_ms (interval ))
547
+ rsc = f' { rsc } #{ operation } _{ sec_to_ms (interval )} '
541
548
elif int (value ) == 0 :
542
- # using '-P' option of 'crm_attribute' command
549
+ op_interval_list = [
550
+ f'{ op } _{ inter } '
551
+ for op , inter in failcount_dict .items ()
552
+ if not operation or op == operation
553
+ ]
554
+ op_interval_str = '|' .join (op_interval_list )
555
+ rsc = f'{ rsc } #{ op_interval_str } '
556
+ # using '-P' option of 'crm_attribute' command, to match the pattern
543
557
cmd = "set_p"
544
- if operation :
545
- op_interval_str = '|' .join (['{}_{}' .format (operation , inter ) for op , inter in failcount_res if op == operation ])
546
- else :
547
- op_interval_str = '|' .join (['{}_{}' .format (op , inter ) for op , inter in failcount_res ])
548
- rsc = '{}#({})' .format (rsc , op_interval_str )
549
558
else :
550
559
# value != 0
551
- if operation and len ([op for op , _ in failcount_res if op == operation ]) == 1 :
552
- rsc = '{ }#{}_{}' . format ( rsc , operation , failcount_dict [operation ])
560
+ if operation and len ([op for op in failcount_dict if op == operation ]) == 1 :
561
+ rsc = f' { rsc } #{ operation } _{ failcount_dict [operation ]} '
553
562
else :
554
- context . fatal_error ( "Should specify (operation, interval) between {}" .
555
- format ([( op , ms_to_sec ( inter )) for op , inter in failcount_res ]) )
563
+ failcount_items = [( op , ms_to_sec ( inter )) for op , inter in failcount_dict . items ()]
564
+ context . fatal_error ( f"Should specify (operation, interval) between { failcount_items } \n { USAGE } " )
556
565
557
566
return ui_utils .manage_attr (context .get_command_name (), self .rsc_failcount ,
558
567
rsc , cmd , node , value )
0 commit comments