~ps10gel/ubuntu/xenial/trafficserver/6.2.0

« back to all changes in this revision

Viewing changes to proxy/mgmt2/cli/CliMain.cc

  • Committer: Bazaar Package Importer
  • Author(s): Arno Toell
  • Date: 2011-01-13 11:49:18 UTC
  • Revision ID: james.westby@ubuntu.com-20110113114918-vu422h8dknrgkj15
Tags: upstream-2.1.5-unstable
ImportĀ upstreamĀ versionĀ 2.1.5-unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file
 
2
 
 
3
  A brief file description
 
4
 
 
5
  @section license License
 
6
 
 
7
  Licensed to the Apache Software Foundation (ASF) under one
 
8
  or more contributor license agreements.  See the NOTICE file
 
9
  distributed with this work for additional information
 
10
  regarding copyright ownership.  The ASF licenses this file
 
11
  to you under the Apache License, Version 2.0 (the
 
12
  "License"); you may not use this file except in compliance
 
13
  with the License.  You may obtain a copy of the License at
 
14
 
 
15
      http://www.apache.org/licenses/LICENSE-2.0
 
16
 
 
17
  Unless required by applicable law or agreed to in writing, software
 
18
  distributed under the License is distributed on an "AS IS" BASIS,
 
19
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
20
  See the License for the specific language governing permissions and
 
21
  limitations under the License.
 
22
 */
 
23
 
 
24
/***************************************/
 
25
/****************************************************************************
 
26
 *
 
27
 *  CliMain.cc - A simple client to communicate to local manager
 
28
 *
 
29
 *
 
30
 ****************************************************************************/
 
31
 
 
32
#include "libts.h"
 
33
 
 
34
#include "ink_args.h"
 
35
#include "I_Layout.h"
 
36
#include "I_Version.h"
 
37
#include "Tokenizer.h"
 
38
#include "TextBuffer.h"
 
39
#include "CliUtils.h"
 
40
#include "clientCLI.h"
 
41
 
 
42
#ifdef _WIN32
 
43
 
 
44
bool
 
45
initWinSock(void)
 
46
{
 
47
  /* initialize WINSOCK 2.0 */
 
48
  WORD wVersionRequested;
 
49
  WSADATA wsaData;
 
50
  int err;
 
51
 
 
52
  wVersionRequested = MAKEWORD(2, 0);
 
53
  err = WSAStartup(wVersionRequested, &wsaData);
 
54
  if (err != 0) {
 
55
    return false;
 
56
  }
 
57
 
 
58
  if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) {
 
59
    WSACleanup();
 
60
    return false;
 
61
  }
 
62
 
 
63
  return true;
 
64
}
 
65
 
 
66
#endif // _WIN32
 
67
 
 
68
static const char *programName;
 
69
 
 
70
static int interactiveMode;
 
71
static char readVar[255];
 
72
static char setVar[255];
 
73
static char varValue[255];
 
74
static int reRead;
 
75
static int Shutdown;
 
76
static int BounceCluster;
 
77
static int BounceLocal;
 
78
static int QueryDeadhosts;
 
79
static int Startup;
 
80
static int ShutdownMgmtCluster;
 
81
static int ShutdownMgmtLocal;
 
82
static int ClearCluster;
 
83
static int ClearNode;
 
84
static int timeout_arg;
 
85
 
 
86
static void
 
87
handleArgInvocation(clientCLI * cli)
 
88
{
 
89
  char bufToLm[1024];           // buffer to send request to Local Manager
 
90
  textBuffer response(512);     // textBuffer object to hold response
 
91
  char *responseStr;            // actual response string
 
92
  ink_hrtime timeLeft = -1;
 
93
  bool printResponse = false;
 
94
  Tokenizer respTok(";");
 
95
  const char *status = NULL;
 
96
  const char *resp = NULL;
 
97
  int bufRemaining = sizeof(bufToLm) - 1;
 
98
 
 
99
  // Do we really need to memset this, shouldn't it be enough to just do *bufToLm=0; ? /leif
 
100
  memset(bufToLm, '\0', 1024);
 
101
 
 
102
  // Intialize request as non-interactive
 
103
  ink_strncpy(bufToLm, "b ", bufRemaining);
 
104
  --bufRemaining;
 
105
 
 
106
  // Following options must be sent over as their numeric
 
107
  // equivalents that show up in the interactive menu
 
108
  // this is ugly but makes the number of handled events smaller
 
109
  // on the manager side
 
110
  if (reRead == 1) {
 
111
    // Handle reRead
 
112
    if (*readVar != '\0' || *setVar != '\0' || *varValue != '\0') {
 
113
      fprintf(stderr, "%s: Invalid Argument Combination: Can not read or set values with re-read\n", programName);
 
114
      cli->disconnectFromLM();
 
115
      exit(1);
 
116
    } else {
 
117
      strncat(bufToLm, "3", bufRemaining);   /* reread */
 
118
      --bufRemaining;
 
119
    }
 
120
  } else if (ShutdownMgmtCluster == 1) {
 
121
    strncat(bufToLm, "9", bufRemaining);     /* restart_cluster */
 
122
    --bufRemaining;
 
123
  } else if (ShutdownMgmtLocal == 1) {
 
124
    strncat(bufToLm, "8", bufRemaining);     /* restart_local */
 
125
    --bufRemaining;
 
126
  } else if (Shutdown == 1) {
 
127
    strncat(bufToLm, "4", bufRemaining);     /* shutdown */
 
128
    --bufRemaining;
 
129
  } else if (BounceCluster == 1) {
 
130
    strncat(bufToLm, "7", bufRemaining);     /* bounce_cluster */
 
131
    --bufRemaining;
 
132
  } else if (BounceLocal == 1) {
 
133
    strncat(bufToLm, "6", bufRemaining);     /* bounce_local */
 
134
    --bufRemaining;
 
135
  } else if (Startup == 1) {
 
136
    strncat(bufToLm, "5", bufRemaining);     /* startup */
 
137
    --bufRemaining;
 
138
  } else if (ClearCluster == 1) {
 
139
    strncat(bufToLm, "10", bufRemaining);    /* clear_cluster */
 
140
    bufRemaining -= 2;
 
141
  } else if (ClearNode == 1) {
 
142
    strncat(bufToLm, "11", bufRemaining);    /* clear_node */
 
143
    bufRemaining -= 2;
 
144
  } else if (QueryDeadhosts == 1) {
 
145
    printResponse = true;
 
146
    strncat(bufToLm, "query_deadhosts", bufRemaining);
 
147
    bufRemaining -= 15;
 
148
  } else if (*readVar != '\0') {        // Handle a value read
 
149
    if (*setVar != '\0' || *varValue != '\0') {
 
150
      fprintf(stderr, "%s: Invalid Argument Combination: Can not read and set values at the same time\n", programName);
 
151
      cli->disconnectFromLM();
 
152
      exit(1);
 
153
    } else {
 
154
      printResponse = true;
 
155
      strncat(bufToLm, "get ", bufRemaining);
 
156
      bufRemaining -= 4;
 
157
      strncat(bufToLm, readVar, bufRemaining);
 
158
      bufRemaining -= strlen(readVar);
 
159
    }
 
160
  } else if (*setVar != '\0') { // Setting a variable
 
161
    if (*varValue == '\0') {
 
162
      fprintf(stderr, "%s: Set requires a -v argument\n", programName);
 
163
      cli->disconnectFromLM();
 
164
      exit(1);
 
165
    } else {
 
166
      strncat(bufToLm, "set ", bufRemaining);
 
167
      bufRemaining -= 4;
 
168
      strncat(bufToLm, setVar, bufRemaining);
 
169
      bufRemaining -= strlen(setVar);
 
170
      strncat(bufToLm, " ", bufRemaining);
 
171
      --bufRemaining;
 
172
      strncat(bufToLm, varValue, bufRemaining);
 
173
      bufRemaining -= strlen(varValue);
 
174
    }
 
175
  } else if (*varValue != '\0') {       // We have a value but no variable to set
 
176
    fprintf(stderr, "%s: Must specify variable to set with -s when using -v\n", programName);
 
177
    cli->disconnectFromLM();
 
178
    exit(1);
 
179
  } else if (timeout_arg > 0) { //INKqa10515
 
180
    timeLeft = timeout_arg * 1000;
 
181
  } else {
 
182
    fprintf(stderr, "%s: No arguments specified\n", programName);
 
183
    cli->disconnectFromLM();
 
184
    exit(1);
 
185
  }
 
186
 
 
187
  if (timeout_arg < 0) {
 
188
    timeLeft = -1;
 
189
  }
 
190
 
 
191
  cli->sendCommand(bufToLm, &response, timeLeft);
 
192
  responseStr = response.bufPtr();
 
193
 
 
194
  // parse response request from server into 3 tokens:
 
195
  // status, prompt and response
 
196
  respTok.setMaxTokens(3);      //<status>;<prompt>;<response>
 
197
  respTok.Initialize(response.bufPtr(), COPY_TOKS);
 
198
  status = respTok[0];
 
199
  resp = respTok[2];
 
200
 
 
201
  if (status && *status == '1') {       // OK
 
202
    // Only print responses for read, ignore prompt
 
203
    if (printResponse)
 
204
      printf("%s\n", resp ? resp : "NULL");
 
205
  } else if (responseStr && *responseStr == '0') {      // Error, Always print out errors
 
206
    fprintf(stderr, "%s: %s\n", programName, resp);
 
207
  } else {
 
208
    fprintf(stderr, "%s: Internal Error: Server Returned Invalid Reponse\n", programName);
 
209
    cli->disconnectFromLM();
 
210
    exit(1);
 
211
  }
 
212
 
 
213
  cli->disconnectFromLM();
 
214
}                               // end handleArgInvocation
 
215
 
 
216
static void
 
217
runInteractive(clientCLI * cli)
 
218
{
 
219
  char buf[512];                // holds request from interactive prompt
 
220
  char sendbuf[512];            // holds request to send LM
 
221
  textBuffer response(8192);    // holds response from Local Manager
 
222
  ink_hrtime timeLeft;
 
223
  Tokenizer respTok(";");
 
224
  const char *prompt = NULL;
 
225
  const char *resp = NULL;
 
226
 
 
227
  respTok.setMaxTokens(3);      //<status>;<prompt>;<response>
 
228
 
 
229
  // process input from command line
 
230
  while (1) {
 
231
    // Display a prompt
 
232
    if (prompt) {
 
233
      printf("%s", prompt);
 
234
    } else {                    // default
 
235
      printf("cli-> ");
 
236
    }
 
237
 
 
238
    // get input from command line
 
239
    NOWARN_UNUSED_RETURN(fgets(buf, 512, stdin));
 
240
 
 
241
    // check status of 'stdin' after reading
 
242
    if (feof(stdin) != 0) {
 
243
      fprintf(stderr, "%s: Detected EOF on input %s\n", programName, strerror(errno));
 
244
      cli->disconnectFromLM();
 
245
      exit(0);
 
246
    } else if (ferror(stdin) != 0) {
 
247
      fprintf(stderr, "%s: Error on reading user command: %s\n", programName, strerror(errno));
 
248
      exit(1);
 
249
    }
 
250
    // continue on newline
 
251
    if (strcmp(buf, "\n") == 0) {
 
252
      continue;
 
253
    }
 
254
 
 
255
    if (timeout_arg > 0) {
 
256
      timeLeft = timeout_arg * 1000;
 
257
    } else {
 
258
      timeLeft = -1;
 
259
    }
 
260
 
 
261
    // set interactive mode
 
262
    ink_strncpy(sendbuf, "i ", sizeof(sendbuf));
 
263
    strncat(sendbuf, buf, strlen(buf) - 1);     // do not send newline
 
264
 
 
265
    cli->sendCommand(sendbuf, &response, timeLeft);
 
266
 
 
267
    // exiting/quitting?
 
268
    if (strcasecmp("quit\n", buf) == 0 || strcasecmp("exit\n", buf) == 0) {
 
269
      // Don't wait for response LM
 
270
      cli->disconnectFromLM();
 
271
      exit(0);
 
272
    }
 
273
    // parse response request from server into 3 tokens:
 
274
    // status, prompt and response (but status is not used)
 
275
    respTok.Initialize(response.bufPtr(), COPY_TOKS);
 
276
    prompt = respTok[1];
 
277
    resp = respTok[2];
 
278
 
 
279
    // print response
 
280
    if (resp) {
 
281
      printf("%s\n", resp);
 
282
    }
 
283
    // reuse response buffer?
 
284
    response.reUse();
 
285
 
 
286
  }                             // end while(1)
 
287
}                               // end runInteractive
 
288
 
 
289
AppVersionInfo appVersionInfo;
 
290
int version_flag = 0;
 
291
/*
 
292
 * Main entry point
 
293
 */
 
294
int
 
295
main(int argc, char **argv)
 
296
{
 
297
  programName = argv[0];
 
298
 
 
299
  interactiveMode = 0;
 
300
  readVar[0] = '\0';
 
301
  setVar[0] = '\0';
 
302
  varValue[0] = '\0';
 
303
  reRead = 0;
 
304
  Shutdown = 0;
 
305
  BounceCluster = 0;
 
306
  BounceLocal = 0;
 
307
  QueryDeadhosts = 0;
 
308
  Startup = 0;
 
309
  ShutdownMgmtCluster = 0;
 
310
  ShutdownMgmtLocal = 0;
 
311
  ClearCluster = 0;
 
312
  ClearNode = 0;
 
313
  timeout_arg = -1;
 
314
 
 
315
  // build the application information structure
 
316
  appVersionInfo.setup(PACKAGE_NAME,"traffic_line", PACKAGE_VERSION, __DATE__,
 
317
                       __TIME__, BUILD_MACHINE, BUILD_PERSON, "");
 
318
 
 
319
  // Before accessing file system initialize Layout engine
 
320
  Layout::create();
 
321
  clientCLI *cli = new clientCLI();
 
322
 
 
323
/* Argument description table used to describe how to parse command line args, */
 
324
/* see 'ink_args.h' for meanings of the various fields */
 
325
  ArgumentDescription argument_descriptions[] = {
 
326
    // INKqa10516
 
327
    /*{ "interactive", 'i', "Interactive Mode", "F", &interactiveMode, "CLI_INTERACTIVE", NULL}, */
 
328
#ifndef _WIN32
 
329
    {"query_deadhosts", 'q', "Query congested sites", "F", &QueryDeadhosts, NULL, NULL},
 
330
    {"socket_path", 'p', "Socket Path", "S255", &cli->sockPath, "CLI_SOCKPATH", NULL},
 
331
#else
 
332
    {"cli_port", 'p', "Port Number", "I", &cli->cliPort, "CLI_PORT", NULL},
 
333
#endif
 
334
    {"read_var", 'r', "Read Variable", "S255", &readVar, NULL, NULL},
 
335
    {"set_var", 's', "Set Variable (requires -v option)", "S255", &setVar, NULL, NULL},
 
336
    {"value", 'v', "Set Value (used with -s option)", "S255", &varValue, NULL, NULL},
 
337
    {"help", 'h', "Help", NULL, NULL, NULL, usage},
 
338
    {"reread_config", 'x', "Reread Config Files", "F", &reRead, NULL, NULL},
 
339
    {"restart_cluster", 'M', "Restart traffic_manager (cluster wide)",
 
340
     "F", &ShutdownMgmtCluster, NULL, NULL},
 
341
    {"restart_local", 'L', "Restart traffic_manager (local node)",
 
342
     "F", &ShutdownMgmtLocal, NULL, NULL},
 
343
    {"shutdown", 'S', "Shutdown traffic_server (local node)", "F", &Shutdown, NULL, NULL},
 
344
    {"startup", 'U', "Start traffic_server (local node)", "F", &Startup, NULL, NULL},
 
345
    {"bounce_cluster", 'B', "Bounce traffic_server (cluster wide)", "F", &BounceCluster, NULL, NULL},
 
346
    {"bounce_local", 'b', "Bounce local traffic_server", "F", &BounceLocal, NULL, NULL},
 
347
    {"clear_cluster", 'C', "Clear Statistics (cluster wide)", "F", &ClearCluster, NULL, NULL},
 
348
    {"clear_node", 'c', "Clear Statistics (local node)", "F", &ClearNode, NULL, NULL},
 
349
    {"version", 'V', "Print Version Id", "T", &version_flag, NULL, NULL},
 
350
    /* INKqa10624
 
351
       { "timeout", 'T', "Request timeout (seconds)", "I", &timeout_arg, NULL, NULL} */
 
352
 
 
353
  };
 
354
 
 
355
  int n_argument_descriptions = SIZE(argument_descriptions);
 
356
  NOWARN_UNUSED(argc);
 
357
 
 
358
  // Process command line arguments and dump into variables
 
359
  process_args(argument_descriptions, n_argument_descriptions, argv);
 
360
 
 
361
  // check for the version number request
 
362
  if (version_flag) {
 
363
    ink_fputln(stderr, appVersionInfo.FullVersionInfoStr);
 
364
    exit(0);
 
365
  }
 
366
 
 
367
#ifdef _WIN32
 
368
  if (initWinSock() == false) {
 
369
    fprintf(stderr, "%s: unable to initialize winsock.\n", programName);
 
370
    exit(1);
 
371
  }
 
372
#endif
 
373
 
 
374
  // Connect to Local Manager
 
375
#ifndef _WIN32
 
376
  if (cli->connectToLM() != clientCLI::err_none) {
 
377
    char sock_path[PATH_NAME_MAX + 1];
 
378
 
 
379
    Layout::relative_to(sock_path, sizeof(sock_path),
 
380
                        Layout::get()->runtimedir, clientCLI::defaultSockPath);
 
381
    cli->setSockPath(sock_path);
 
382
    if (cli->connectToLM() != clientCLI::err_none) {
 
383
      fprintf(stderr, "%s: unable to connect to traffic_manager via %s\n", programName, cli->sockPath);
 
384
      exit(1);
 
385
    }
 
386
  }
 
387
#else
 
388
  if (cli->connectToLM() != clientCLI::err_none) {
 
389
    fprintf(stderr, "%s: unable to connect to traffic_manager via %s\n", programName, cli->sockPath);
 
390
    exit(1);
 
391
  }
 
392
#endif
 
393
 
 
394
  // Interactive or batch mode
 
395
  if (interactiveMode == 1) {
 
396
    runInteractive(cli);
 
397
  } else {
 
398
    handleArgInvocation(cli);
 
399
  }
 
400
 
 
401
  delete cli;
 
402
 
 
403
  return 0;
 
404
}                               // end main()