2323import  org .apache .commons .cli .Option ;
2424import  org .apache .commons .cli .Options ;
2525import  org .apache .commons .cli .ParseException ;
26+ import  org .apache .commons .collections .CollectionUtils ;
27+ import  org .apache .commons .collections .MapUtils ;
2628import  org .apache .commons .lang3 .StringUtils ;
2729import  org .apache .hadoop .conf .Configuration ;
2830import  org .apache .hadoop .conf .Configured ;
6365import  java .io .PrintWriter ;
6466import  java .nio .charset .Charset ;
6567import  java .nio .charset .StandardCharsets ;
66- import  java .util .Arrays ;
67- import  java .util .ArrayList ;
68- import  java .util .List ;
69- import  java .util .Map ;
68+ import  java .util .*;
7069import  java .util .stream .Collectors ;
7170
7271import  static  org .apache .hadoop .yarn .server .api .protocolrecords .FederationQueueWeight .checkHeadRoomAlphaValid ;
@@ -77,25 +76,75 @@ public class RouterCLI extends Configured implements Tool {
7776
7877  private  static  final  Logger  LOG  = LoggerFactory .getLogger (RouterCLI .class );
7978
80-   protected  final  static  Map <String , UsageInfo > ADMIN_USAGE  =
81-       ImmutableMap .<String , UsageInfo >builder ()
82-          // Command1: deregisterSubCluster 
83-         .put ("-deregisterSubCluster" , new  UsageInfo (
84-         "[-sc|--subClusterId [subCluster Id]]" ,
85-         "Deregister SubCluster, If the interval between the heartbeat time of the subCluster "  +
86-         "and the current time exceeds the timeout period, "  +
87-         "set the state of the subCluster to SC_LOST." ))
88-          // Command2: policy 
89-         .put ("-policy" , new  UsageInfo (
90-         "[-s|--save [queue;router weight;amrm weight;headroomalpha]] "  +
91-          "[-bs|--batch-save [--format xml] [-f|--input-file fileName]]"  +
92-          "[-l|--list [--pageSize][--currentPage][--queue][--queues]]" ,
93-         "We provide a set of commands for Policy:"  +
94-         " Include list policies, save policies, batch save policies. "  +
95-         " (Note: The policy type will be directly read from the"  +
96-         " yarn.federation.policy-manager in the local yarn-site.xml.)"  +
97-         " eg. (routeradmin -policy [-s|--save] root.a;SC-1:0.7,SC-2:0.3;SC-1:0.7,SC-2:0.3;1.0)" ))
98-         .build ();
79+   protected  final  static  UsageInfo  subClusterId  = new  UsageInfo ("<-sc|--subClusterId>" ,
80+       "'-sc' option allows you to specify the sub-cluster to operate on, "  +
81+       "while the '--subClusterId' option is the long format of -sc and serves the same purpose." );
82+   protected  final  static  String  dsExample_1  = "yarn routeradmin -deregisterSubCluster -sc SC-1" ;
83+   protected  final  static  String  dsExample_2  = "yarn routeradmin -deregisterSubCluster --subClusterId SC-1" ;
84+ 
85+   protected  final  static  RouterExampleUsageInfos  dsExampleUsageInfos_1  = new  RouterExampleUsageInfos (
86+           Arrays .asList (dsExample_1 , dsExample_2 ),
87+           Arrays .asList ("At this point we can use the following command:" ));
88+   protected  final  static  RouterUsageInfos  deregisterSubCluster  =
89+       new  RouterUsageInfos (Arrays .asList (subClusterId ),
90+       Arrays .asList ("deregister subCluster, If the interval between the heartbeat time of the subCluster"  +
91+       "and the current time exceeds the timeout period, set the state of the subCluster to SC_LOST." ),
92+       ImmutableMap .<String , RouterExampleUsageInfos >builder ()
93+       .put ("<--deregisterSubCluster>" , dsExampleUsageInfos_1 )
94+       .build ());
95+ 
96+   protected  final  static  UsageInfo  policySaveUsage  = new  UsageInfo (
97+       "<-s|--save [queue;router weight;amrm weight;headroomalpha]>" ,
98+       "We will save the policy information of the queue, including queue and weight information." );
99+   protected  final  static  UsageInfo  policyBatchSaveUsage  = new  UsageInfo (
100+       "<-bs|--batch-save [--format xml] [-f|--input-file fileName]]>" ,
101+       "We will save queue policies in bulk, where users can provide XML files containing the policies." );
102+   protected  final  static  UsageInfo  policyListUsage  = new  UsageInfo ("<-l|--list [--pageSize][--currentPage][--queue][--queues]>" ,
103+       "We can display the configured queue policies." );
104+ 
105+   protected  final  static  String  pExample_1  = "yarn routeradmin -policy -s root.a;SC-1:0.7,SC-2:0.3;SC-1:0.6,SC-2:0.4;1.0" ;
106+   protected  final  static  String  pExample_2  = "yarn routeradmin -policy --save root.a;SC-1:0.7,SC-2:0.3;SC-1:0.6,SC-2:0.4;1.0" ;
107+   protected  final  static  RouterExampleUsageInfos  pExampleUsageInfos_1  = new  RouterExampleUsageInfos (
108+       Arrays .asList (pExample_1 , pExample_2 ),
109+       Arrays .asList ("We have two subClusters, SC-1 and SC-2. For queue root.a, we want the ratio to be set to SC-1:SC-2=0.7:0.3 when routing." ,
110+       "Additionally, when AM applies containers, we want the allocation ratio to be SC-1:SC-2=0.6:0.4." ,
111+       "Headroomalpha can be set to the default value of 1.0." ,
112+       "At this point we can use the following command:" ));
113+ 
114+   protected  final  static  String  pExample_3  = "yarn routeradmin -policy -bs --format xml -f queue.xml" ;
115+   protected  final  static  String  pExample_4  = "yarn routeradmin -policy --batch-save --format xml -f queue.xml" ;
116+   protected  final  static  RouterExampleUsageInfos  pExampleUsageInfos_2  = new  RouterExampleUsageInfos (
117+       Arrays .asList (pExample_3 , pExample_4 ),
118+       Arrays .asList ("We offer the capability to batch input queue policies. " ,
119+       "Currently, this is supported exclusively through XML. "  +
120+       "(We can find federationWeights.xml in the Federation.md on the website.) " ,
121+       "We can use the batch-save command to input proportion information. " ,
122+       "At this point we can use the following command:" ));
123+ 
124+   protected  final  static  String  pExample_5  = "yarn routeradmin -policy -l --pageSize 20 --currentPage 1 --queue root.a" ;
125+   protected  final  static  String  pExample_6  = "yarn routeradmin -policy -list --pageSize 20 --currentPage 1 --queues root.a,root.b" ;
126+   protected  final  static  RouterExampleUsageInfos  pExampleUsageInfos_3  = new  RouterExampleUsageInfos (
127+       Arrays .asList (pExample_5 , pExample_6 ),
128+       Arrays .asList ("We can print the Configured Queue Policies on the command line. " ,
129+       "We can specify a queue through --queue, and we can specify a queue list through --queues." ,
130+       "At this point we can use the following command:" ));
131+ 
132+   protected  final  static  RouterUsageInfos  policy  =
133+       new  RouterUsageInfos (Arrays .asList (policySaveUsage , policyBatchSaveUsage , policyListUsage ),
134+       Arrays .asList ("We provide a set of commands for Policy Include list policies, save policies, batch save policies." ),
135+       ImmutableMap .<String , RouterExampleUsageInfos >builder ()
136+           .put ("<-s|--save>" , pExampleUsageInfos_1 )
137+           .put ("<-bs|--batch-save>" , pExampleUsageInfos_2 )
138+           .put ("<-l|--list>" , pExampleUsageInfos_3 )
139+           .build ());
140+ 
141+   protected  final  static  Map <String , RouterUsageInfos > ADMIN_USAGE  =
142+       ImmutableMap .<String , RouterUsageInfos >builder ()
143+       // Command1: deregisterSubCluster 
144+       .put ("-deregisterSubCluster" , deregisterSubCluster )
145+       // Command2: policy 
146+       .put ("-policy" , policy )
147+       .build ();
99148
100149  // Common Constant 
101150  private  static  final  String  SEMICOLON  = ";" ;
@@ -135,7 +184,7 @@ public class RouterCLI extends Configured implements Tool {
135184
136185  private  static  final  String  CMD_POLICY  = "-policy" ;
137186  private  static  final  String  FORMAT_XML  = "xml" ;
138-    private   static   final   String   FORMAT_JSON  =  "json" ; 
187+ 
139188  private  static  final  String  XML_TAG_SUBCLUSTERIDINFO  = "subClusterIdInfo" ;
140189  private  static  final  String  XML_TAG_AMRMPOLICYWEIGHTS  = "amrmPolicyWeights" ;
141190  private  static  final  String  XML_TAG_ROUTERPOLICYWEIGHTS  = "routerPolicyWeights" ;
@@ -159,43 +208,59 @@ public RouterCLI(Configuration conf) {
159208  }
160209
161210  private  static  void  buildHelpMsg (String  cmd , StringBuilder  builder ) {
162-     UsageInfo  usageInfo  = ADMIN_USAGE .get (cmd );
163-     if  (usageInfo  == null ) {
211+     RouterUsageInfos  routerUsageInfo  = ADMIN_USAGE .get (cmd );
212+ 
213+     if  (routerUsageInfo  == null ) {
164214      return ;
165215    }
216+     builder .append ("["  + cmd  + "]\n " );
166217
167-     if  (usageInfo .args  != null ) {
168-       String  space  = (usageInfo .args  == "" ) ? ""  : " " ;
169-       builder .append ("   " )
170-           .append (cmd )
171-           .append (space )
172-           .append (usageInfo .args )
173-           .append (": " )
174-           .append (usageInfo .help );
175-     } else  {
176-       builder .append ("   " )
177-           .append (cmd )
178-           .append (": " )
179-           .append (usageInfo .help );
218+     if  (!routerUsageInfo .helpInfos .isEmpty ()) {
219+       builder .append ("\t  Description: \n " );
220+       for  (String  helpInfo  : routerUsageInfo .helpInfos ) {
221+         builder .append ("\t \t "  + helpInfo ).append ("\n \n " );
222+       }
180223    }
181-   }
182224
183-   private  static  void  buildIndividualUsageMsg (String  cmd , StringBuilder  builder ) {
184-     UsageInfo  usageInfo  = ADMIN_USAGE .get (cmd );
185-     if  (usageInfo  == null ) {
186-       return ;
225+     if  (!routerUsageInfo .usageInfos .isEmpty ()) {
226+       builder .append ("\t  UsageInfos: \n " );
227+       for  (UsageInfo  usageInfo  : routerUsageInfo .usageInfos ) {
228+         builder .append ("\t \t " +usageInfo .args )
229+             .append (": " )
230+             .append ("\n \t \t " )
231+             .append (usageInfo .help ).append ("\n \n " );
232+       }
187233    }
188-     if  (usageInfo .args  == null ) {
189-       builder .append ("Usage: routeradmin [" )
190-           .append (cmd )
191-           .append ("]\n " );
192-     } else  {
193-       String  space  = (usageInfo .args  == "" ) ? ""  : " " ;
194-       builder .append ("Usage: routeradmin [" )
195-           .append (cmd )
196-           .append (space )
197-           .append (usageInfo .args )
198-           .append ("]\n " );
234+ 
235+     if  (MapUtils .isNotEmpty (routerUsageInfo .examples )) {
236+       builder .append ("\t  Examples: \n " );
237+       int  count  = 1 ;
238+       for  (Map .Entry <String , RouterExampleUsageInfos > example  :
239+          routerUsageInfo .examples .entrySet ()) {
240+         String  key  = example .getKey ();
241+         builder .append ("\t \t " ).append ("Cmd:"  + count  + ". " ).append (key ).append (": \n \n " );
242+         RouterExampleUsageInfos  values  = example .getValue ();
243+         if  (values  == null ) {
244+           return ;
245+         }
246+         // Print Command Description 
247+         if  (CollectionUtils .isNotEmpty (values .desc )) {
248+           builder .append ("\t \t " ).append ("Cmd Requirement Description:\n " );
249+           for  (String  value  : values .desc ) {
250+             builder .append ("\t \t " ).append (value ).append ("\n " );
251+           }
252+         }
253+         builder .append ("\n " );
254+         // Print Command example 
255+         if  (CollectionUtils .isNotEmpty (values .examples )) {
256+           builder .append ("\t \t " ).append ("Cmd Examples:\n " );
257+           for  (String  value  : values .examples ) {
258+             builder .append ("\t \t " ).append (value ).append ("\n " );
259+           }
260+         }
261+         builder .append ("\n " );
262+         count ++;
263+       }
199264    }
200265  }
201266
@@ -204,12 +269,7 @@ private static void printHelp() {
204269    summary .append ("routeradmin is the command to execute " )
205270        .append ("YARN Federation administrative commands.\n " )
206271        .append ("The full syntax is: \n \n " )
207-         .append ("routeradmin\n " )
208-         .append ("   [-deregisterSubCluster [-sc|--subClusterId [subCluster Id]]\n " )
209-         .append ("   [-policy [-s|--save [queue;router weight;amrm weight;headroomalpha] "  +
210-         "[-bs|--batch-save [--format xml,json] [-f|--input-file fileName]]] "  +
211-         "[-l|--list [--pageSize][--currentPage][--queue][--queues]]\n " )
212-         .append ("   [-help [cmd]]" ).append ("\n " );
272+         .append ("routeradmin\n " );
213273    StringBuilder  helpBuilder  = new  StringBuilder ();
214274    System .out .println (summary );
215275
@@ -235,21 +295,17 @@ protected ResourceManagerAdministrationProtocol createAdminProtocol()
235295  private  static  void  buildUsageMsg (StringBuilder  builder ) {
236296    builder .append ("routeradmin is only used in Yarn Federation Mode.\n " );
237297    builder .append ("Usage: routeradmin\n " );
238-     for  (Map .Entry <String , UsageInfo > cmdEntry  : ADMIN_USAGE .entrySet ()) {
239-       UsageInfo  usageInfo  = cmdEntry .getValue ();
240-       builder .append ("   " )
241-           .append (cmdEntry .getKey ())
242-           .append (" " )
243-           .append (usageInfo .args )
244-           .append ("\n " );
298+     for  (String  cmdKey  : ADMIN_USAGE .keySet ()) {
299+       buildHelpMsg (cmdKey , builder );
300+       builder .append ("\n " );
245301    }
246302    builder .append ("   -help [cmd]\n " );
247303  }
248304
249305  private  static  void  printUsage (String  cmd ) {
250306    StringBuilder  usageBuilder  = new  StringBuilder ();
251307    if  (ADMIN_USAGE .containsKey (cmd )) {
252-       buildIndividualUsageMsg (cmd , usageBuilder );
308+       buildHelpMsg (cmd , usageBuilder );
253309    } else  {
254310      buildUsageMsg (usageBuilder );
255311    }
@@ -353,7 +409,7 @@ private int handlePolicy(String[] args)
353409    saveOpt .setOptionalArg (true );
354410    Option  batchSaveOpt  = new  Option (OPTION_BATCH_S , OPTION_BATCH_SAVE , false ,
355411        "We will save queue policies in bulk, "  +
356-          "where users can provide XML or JSON  files containing the policies. "  +
412+          "where users can provide XML files containing the policies. "  +
357413         "This command will parse the file contents and store the results "  +
358414         "in the FederationStateStore." );
359415    Option  formatOpt  = new  Option (null , "format" , true ,
@@ -748,6 +804,29 @@ public int run(String[] args) throws Exception {
748804    return  EXIT_SUCCESS ;
749805  }
750806
807+   private  static  class  RouterExampleUsageInfos  {
808+     public  List <String > examples ;
809+     public  List <String > desc ;
810+ 
811+     public  RouterExampleUsageInfos (List <String > examples , List <String > desc ) {
812+       this .examples  = examples ;
813+       this .desc  = desc ;
814+     }
815+   }
816+ 
817+   private  static  class  RouterUsageInfos  {
818+     public  List <UsageInfo > usageInfos ;
819+     public  List <String > helpInfos ;
820+     public  Map <String , RouterExampleUsageInfos > examples ;
821+ 
822+     public  RouterUsageInfos (List <UsageInfo > usageInfos , List <String > helpInfos ,
823+         Map <String , RouterExampleUsageInfos > examples ) {
824+       this .usageInfos  = usageInfos ;
825+       this .helpInfos  = helpInfos ;
826+       this .examples  = examples ;
827+     }
828+   }
829+ 
751830  public  static  void  main (String [] args ) throws  Exception  {
752831    int  result  = ToolRunner .run (new  RouterCLI (), args );
753832    System .exit (result );
0 commit comments