~ps10gel/ubuntu/xenial/trafficserver/6.2.0

« back to all changes in this revision

Viewing changes to test/deft/remote_start.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
   remote_start.cc
 
27
 
 
28
   Description:
 
29
 
 
30
 
 
31
 ****************************************************************************/
 
32
 
 
33
#include <unistd.h>
 
34
 
 
35
#if defined(darwin)
 
36
// Fix wierd conflict with Tcl #define for panic
 
37
#include <sys/mman.h>
 
38
#endif
 
39
 
 
40
#include "sio_loop.h"
 
41
#include "sio_buffer.h"
 
42
#include "raf_cmd.h"
 
43
#include "test_utils.h"
 
44
#include "test_exec.h"
 
45
 
 
46
#include "Tokenizer.h"
 
47
#include "Diags.h"
 
48
 
 
49
/* Constants */
 
50
static const int SIZE_32K = 32768;
 
51
 
 
52
static int
 
53
create_pipe_for_remote(const char *hostname, int *pipe_arg, int in_pipe)
 
54
{
 
55
 
 
56
  int r;
 
57
  do {
 
58
    r = pipe(pipe_arg);
 
59
  } while (r < 0 && errno == EINTR);
 
60
 
 
61
  if (r < 0) {
 
62
    TE_Error("Pipe creation for %s failed : %s", hostname, strerror(errno));
 
63
    return -1;
 
64
  }
 
65
 
 
66
  do {
 
67
    r = fcntl((in_pipe == true) ? pipe_arg[0] : pipe_arg[1], F_SETFL, O_NONBLOCK);
 
68
  } while (r < 0 && errno == EINTR);
 
69
 
 
70
  if (r < 0) {
 
71
    TE_Error("Failed to set non-block on %s pipe", hostname, strerror(errno));
 
72
    close(pipe_arg[0]);
 
73
    close(pipe_arg[1]);
 
74
    return -1;
 
75
  }
 
76
 
 
77
  return 0;
 
78
}
 
79
 
 
80
pid_t
 
81
start_remote_shell(const UserDirInfo * ud_info, const char *hostname, int *in_pipe, int *out_pipe)
 
82
{
 
83
 
 
84
  int r = create_pipe_for_remote(hostname, in_pipe, true);
 
85
  if (r < 0) {
 
86
    return r;
 
87
  }
 
88
 
 
89
  r = create_pipe_for_remote(hostname, out_pipe, false);
 
90
  if (r < 0) {
 
91
    close(in_pipe[0]);
 
92
    close(in_pipe[1]);
 
93
    return r;
 
94
  }
 
95
 
 
96
  char *sub_cmd;
 
97
  if (strcmp(hostname, "localhost") == 0) {
 
98
    //  The command we want is
 
99
    //   <shell> -c "bash -s"
 
100
    sub_cmd = strdup("bash -s");
 
101
  } else {
 
102
    //  The command we want is
 
103
    //   <shell> -c "ssh <hostname> -q -o "BatchMode yes" -o "StrictHostKeyChecking no" bash -s"
 
104
    const char *sub_cmd_format = "ssh -q -o \"BatchMode yes\" -o \"StrictHostKeyChecking no\" %s bash -s";
 
105
    sub_cmd = (char *) malloc(strlen(sub_cmd_format) + strlen(hostname) + 1);
 
106
    sprintf(sub_cmd, sub_cmd_format, hostname);
 
107
  }
 
108
 
 
109
  char **argv = build_argv_v(ud_info->shell, "-c", sub_cmd, NULL);
 
110
  free(sub_cmd);
 
111
  sub_cmd = NULL;
 
112
 
 
113
  pid_t new_pid = fork();
 
114
 
 
115
  if (new_pid < 0) {
 
116
    TE_Error("fork to contact %s failed : %s", hostname, strerror(errno));
 
117
    close(in_pipe[0]);
 
118
    close(in_pipe[1]);
 
119
    close(out_pipe[0]);
 
120
    close(out_pipe[1]);
 
121
    destroy_argv(argv);
 
122
    return -1;
 
123
  } else if (new_pid == 0) {
 
124
    // Child
 
125
    r = dup2(in_pipe[0], 0);
 
126
    if (r < 0) {
 
127
      Fatal("dup to stdin failed : %s", strerror(errno));
 
128
    }
 
129
 
 
130
    r = dup2(out_pipe[1], 1);
 
131
    if (r < 0) {
 
132
      Fatal("dup to stdout failed : %s", strerror(errno));
 
133
    }
 
134
 
 
135
    r = dup2(out_pipe[1], 2);
 
136
    if (r < 0) {
 
137
      Fatal("dup to stderr failed : %s", strerror(errno));
 
138
    }
 
139
    // FIX - use fd limit
 
140
    for (int i = 3; i < 1024; i++) {
 
141
      close(i);
 
142
    }
 
143
 
 
144
    r = execv(ud_info->shell, argv);
 
145
 
 
146
    if (r < 0) {
 
147
      Fatal("exec failed : %s", strerror(errno));
 
148
      return r;
 
149
    }
 
150
  } else {
 
151
    // Parent
 
152
    close(in_pipe[0]);
 
153
    close(out_pipe[1]);
 
154
    destroy_argv(argv);
 
155
 
 
156
    return new_pid;
 
157
  }
 
158
 
 
159
  return -1;
 
160
}
 
161
 
 
162
const char *
 
163
send_remote_cmd(sio_buffer * in_buf, int fd_in, sio_buffer * out_buf, int fd_out)
 
164
{
 
165
 
 
166
  int timeout_ms = 60 * 1000;
 
167
  const char *rmsg = write_buffer(fd_in, in_buf, &timeout_ms);
 
168
 
 
169
  if (rmsg) {
 
170
    return rmsg;
 
171
  }
 
172
 
 
173
  rmsg = read_until(fd_out, out_buf, '\n', &timeout_ms);
 
174
 
 
175
  if (rmsg) {
 
176
    return rmsg;
 
177
  }
 
178
 
 
179
  return NULL;
 
180
}
 
181
 
 
182
const char *
 
183
determine_arch(int fd_in, int fd_out, char **arch_out)
 
184
{
 
185
 
 
186
  sio_buffer in_buf;
 
187
  sio_buffer out_buf;
 
188
 
 
189
  // First get os type
 
190
  const char cmd[] = "uname -s\n";
 
191
  in_buf.fill(cmd, sizeof(cmd) - 1);
 
192
 
 
193
  const char *rmsg = send_remote_cmd(&in_buf, fd_in, &out_buf, fd_out);
 
194
  if (rmsg) {
 
195
    return rmsg;
 
196
  }
 
197
 
 
198
  char *start = out_buf.start();
 
199
  char *end = out_buf.memchr('\n');
 
200
  *end = '\0';
 
201
 
 
202
  // Since determine arch is the first command executed after the
 
203
  //  ssh, it's entirely possible that output has garbage in from
 
204
  //  error messages in the .login or .profile/.cshrc.  There error
 
205
  //  messages tend be of the form "<thing>: <msg>"   Thus we
 
206
  //  will ignore any line message that has a colon in it
 
207
  while (memchr(start, ':', end - start) != NULL) {
 
208
    out_buf.consume((end - start) + 1);
 
209
 
 
210
    // First check if we've got another complete line
 
211
    end = out_buf.memchr('\n');
 
212
    if (end == NULL) {
 
213
      // We need to read more
 
214
      int timeout_ms = 60 * 1000;
 
215
      rmsg = read_until(fd_out, &out_buf, '\n', &timeout_ms);
 
216
      if (rmsg) {
 
217
        return rmsg;
 
218
      }
 
219
      end = out_buf.memchr('\n');
 
220
    }
 
221
    // At this point we've got another line and end is pointing
 
222
    //  to the '\n' terminating the line.  So we just need
 
223
    //  to tidy up an loop around again
 
224
    start = out_buf.start();
 
225
    *end = '\0';
 
226
 
 
227
  }
 
228
 
 
229
  Debug("remote", "OS is %s", out_buf.start());
 
230
 
 
231
  if (strcmp(out_buf.start(), "SunOS") == 0) {
 
232
    // We need to get the processor type to distinguish between
 
233
    //    sparc & x86 solaris
 
234
    in_buf.reset();
 
235
    out_buf.reset();
 
236
 
 
237
    const char pcmd[] = "uname -p\n";
 
238
    in_buf.fill(pcmd, sizeof(pcmd) - 1);
 
239
 
 
240
    if ((rmsg = send_remote_cmd(&in_buf, fd_in, &out_buf, fd_out)) != NULL) {
 
241
      return rmsg;
 
242
    }
 
243
 
 
244
    end = out_buf.memchr('\n');
 
245
    *end = '\0';
 
246
 
 
247
    Debug("remote", "Proc Type is %s", out_buf.start());
 
248
 
 
249
    if (strcmp(out_buf.start(), "i386") == 0) {
 
250
      *arch_out = strdup("SunOSx86");
 
251
    } else {
 
252
      *arch_out = strdup("SunOS");
 
253
    }
 
254
  } else {
 
255
    *arch_out = strdup(out_buf.start());
 
256
  }
 
257
 
 
258
  return NULL;
 
259
}
 
260
 
 
261
// char* find_proc_manager_binary(const char* remote_arch)
 
262
//
 
263
//   Caller frees return value
 
264
//
 
265
char *
 
266
find_proc_manager_binary(const UserDirInfo * ud, const char *remote_arch)
 
267
{
 
268
 
 
269
  char *my_arch = get_arch_str();
 
270
  FreeOnDestruct freer(my_arch);
 
271
 
 
272
  if (strcasecmp(remote_arch, my_arch) == 0) {
 
273
    int r;
 
274
    do {
 
275
      r = access("proc_manager", R_OK | X_OK);
 
276
    } while (r < 0 && errno == EINTR);
 
277
 
 
278
    if (r == 0) {
 
279
      Debug("remote", "Using local proc_manager");
 
280
      return strdup("proc_manager");
 
281
    }
 
282
  }
 
283
 
 
284
  char *pack_name = find_local_package("proc_manager", remote_arch);
 
285
 
 
286
  if (pack_name == NULL) {
 
287
    return NULL;
 
288
  }
 
289
 
 
290
  int len = strlen(ud->package_dir) + 1 + strlen(pack_name) + 1;
 
291
  char *local_pm_path = (char *) malloc(len);
 
292
  sprintf(local_pm_path, "%s/%s", ud->package_dir, pack_name);
 
293
 
 
294
  free(pack_name);
 
295
  return local_pm_path;
 
296
}
 
297
 
 
298
 
 
299
const char *
 
300
setup_remote_directories(int fd_in, int fd_out, UserDirInfo * ud)
 
301
{
 
302
 
 
303
  sio_buffer in_buf;
 
304
  sio_buffer out_buf;
 
305
 
 
306
  const char check_path_format[] = "if [ -d %s ]; then\n" "   echo ok\n" "else\n" "   echo not found\n" "fi\n";
 
307
 
 
308
  const char mkdir_format[] = "if mkdir %s\n" "then\n" "   echo ok\n" "fi\n";
 
309
 
 
310
  int len = sizeof(check_path_format) + strlen(ud->test_stuff_path) + 1;
 
311
  char *cmd = (char *) malloc(len);
 
312
  sprintf(cmd, check_path_format, ud->test_stuff_path);
 
313
 
 
314
  in_buf.fill(cmd, strlen(cmd));
 
315
  free(cmd);
 
316
  cmd = NULL;
 
317
 
 
318
  const char *rmsg = send_remote_cmd(&in_buf, fd_in, &out_buf, fd_out);
 
319
 
 
320
  if (rmsg) {
 
321
    return rmsg;
 
322
  }
 
323
 
 
324
  char *end = out_buf.memchr('\n');
 
325
  *end = '\0';
 
326
  Debug("remote", "Response to check stuff path: %s", out_buf.start());
 
327
 
 
328
  if (strcmp(out_buf.start(), "ok") != 0) {
 
329
    return "remote stuff_path dir does not exist";
 
330
  }
 
331
 
 
332
  in_buf.reset();
 
333
  out_buf.reset();
 
334
 
 
335
  len = sizeof(check_path_format) + strlen(ud->test_stuff_path_and_dir) + 1;
 
336
  cmd = (char *) malloc(len);
 
337
  sprintf(cmd, check_path_format, ud->test_stuff_path_and_dir);
 
338
 
 
339
  in_buf.fill(cmd, strlen(cmd));
 
340
  free(cmd);
 
341
  cmd = NULL;
 
342
 
 
343
  rmsg = send_remote_cmd(&in_buf, fd_in, &out_buf, fd_out);
 
344
 
 
345
  if (rmsg) {
 
346
    return rmsg;
 
347
  }
 
348
 
 
349
  end = out_buf.memchr('\n');
 
350
  *end = '\0';
 
351
  Debug("remote", "Response to check stuff dir: %s", out_buf.start());
 
352
 
 
353
  if (strcmp(out_buf.start(), "ok") != 0) {
 
354
    // Need to create the directory
 
355
    in_buf.reset();
 
356
    out_buf.reset();
 
357
 
 
358
    int len = sizeof(mkdir_format) + strlen(ud->test_stuff_path_and_dir) + 1;
 
359
    char *cmd = (char *) malloc(len);
 
360
    sprintf(cmd, mkdir_format, ud->test_stuff_path_and_dir);
 
361
 
 
362
    in_buf.fill(cmd, strlen(cmd));
 
363
    free(cmd);
 
364
    cmd = NULL;
 
365
 
 
366
    rmsg = send_remote_cmd(&in_buf, fd_in, &out_buf, fd_out);
 
367
 
 
368
    end = out_buf.memchr('\n');
 
369
    *end = '\0';
 
370
    Debug("remote", "Response to mkdir stuff dir: %s", out_buf.start());
 
371
 
 
372
    if (strcmp(out_buf.start(), "ok") != 0) {
 
373
      TE_Note("failed to create remote directory : %s", out_buf.start());
 
374
      return "remote directory creation failed";
 
375
    }
 
376
  }
 
377
 
 
378
  return NULL;
 
379
}
 
380
 
 
381
 
 
382
const char *
 
383
transfer_proc_manager_binary(int local_file_fd, int fd_in, int *timeout_ms)
 
384
{
 
385
 
 
386
  sio_buffer file_buf(SIZE_32K);
 
387
 
 
388
  bool read_done = false;
 
389
  const char *rmsg = NULL;
 
390
 
 
391
  while (read_done == false) {
 
392
 
 
393
    int eof = 0;
 
394
    rmsg = read_to_buffer(local_file_fd, &file_buf, SIZE_32K, &eof, timeout_ms);
 
395
 
 
396
    if (rmsg) {
 
397
      return rmsg;
 
398
    }
 
399
 
 
400
    if (eof == 1) {
 
401
      read_done = true;
 
402
    }
 
403
 
 
404
    rmsg = write_buffer(fd_in, &file_buf, timeout_ms);
 
405
    if (rmsg) {
 
406
      return rmsg;
 
407
    }
 
408
  }
 
409
 
 
410
  return NULL;
 
411
}
 
412
 
 
413
const char *
 
414
check_remote_proc_manager(int fd_in, int fd_out,
 
415
                          UserDirInfo * ud, const char *remote_proc_mgr_name, const char *remote_arch, int *ok)
 
416
{
 
417
  sio_buffer in_buf;
 
418
  sio_buffer out_buf;
 
419
 
 
420
  *ok = 0;
 
421
 
 
422
  const char ls_check_format[] =
 
423
    "if [ -x %s ]; then\n" "  a=`ls -l %s`\n" "  echo ${a:-error}\n" "else\n" "  echo error\n" "fi\n";
 
424
 
 
425
  int len = sizeof(ls_check_format) + (2 * strlen(remote_proc_mgr_name)) + 1;
 
426
  char *cmd = (char *) malloc(len);
 
427
  sprintf(cmd, ls_check_format, remote_proc_mgr_name, remote_proc_mgr_name);
 
428
 
 
429
  in_buf.fill(cmd, strlen(cmd));
 
430
  free(cmd);
 
431
  cmd = NULL;
 
432
 
 
433
  const char *rmsg = send_remote_cmd(&in_buf, fd_in, &out_buf, fd_out);
 
434
 
 
435
  if (rmsg) {
 
436
    return rmsg;
 
437
  }
 
438
 
 
439
  char *end = out_buf.memchr('\n');
 
440
  *end = '\0';
 
441
  Debug("remote", "Response to ls check cmd: %s", out_buf.start());
 
442
 
 
443
  if (strcmp(out_buf.start(), "error") == 0) {
 
444
    TE_Warning("error checking proc_manager; replacing : %s", out_buf.start());
 
445
    return NULL;
 
446
  }
 
447
 
 
448
  Tokenizer ws_tok(" \t\r\n");
 
449
  int num_tok = ws_tok.Initialize(out_buf.start());
 
450
 
 
451
  if (num_tok < 8) {
 
452
    TE_Warning("bad ls output on proc_manager check; replacing : %s", out_buf.start());
 
453
    return NULL;
 
454
  }
 
455
 
 
456
  int remote_size = atoi(ws_tok[4]);
 
457
 
 
458
  if (remote_size == 0) {
 
459
    return NULL;
 
460
  }
 
461
 
 
462
  char *local_pm = find_proc_manager_binary(ud, remote_arch);
 
463
 
 
464
  if (local_pm == NULL) {
 
465
    // Since we don't a replacement, the exisiting one
 
466
    //   will have be ok
 
467
    TE_Warning("no process manager for arch %s found", remote_arch);
 
468
    *ok = 1;
 
469
    return NULL;
 
470
  }
 
471
 
 
472
  int r;
 
473
  struct stat stat_info;
 
474
  do {
 
475
    r = stat(local_pm, &stat_info);
 
476
  } while (r < 0 && errno == EINTR);
 
477
 
 
478
  if (r < 0) {
 
479
    // Can not get info on local one, leave exisitng
 
480
    TE_Warning("stat on for proc_manager % : %s", local_pm, strerror(errno));
 
481
    *ok = 1;
 
482
  } else {
 
483
    // Check to see if sizes match
 
484
    //
 
485
    //  FIX: should also check to see if local package
 
486
    //    is newer than remote
 
487
    if (stat_info.st_size == remote_size) {
 
488
      *ok = 1;
 
489
    }
 
490
  }
 
491
  free(local_pm);
 
492
  local_pm = NULL;
 
493
 
 
494
  return NULL;
 
495
}
 
496
 
 
497
 
 
498
//
 
499
// const char* start_remote_proc_manager
 
500
//
 
501
//
 
502
const char *
 
503
start_remote_proc_manager(int &fd_in, int &fd_out,
 
504
                          UserDirInfo * ud, const char *remote_proc_mgr_name, int remote_proc_mgr_killtm)
 
505
{
 
506
  sio_buffer in_buf;
 
507
  sio_buffer out_buf;
 
508
 
 
509
  const char start_format[] = "./%s -r -q -d . -p %d%s%s -k %d\n";
 
510
 
 
511
  int len = sizeof(start_format) + strlen(remote_proc_mgr_name) + 1;
 
512
  if (ud->log_collator_arg) {
 
513
    len += 3 + strlen(ud->log_collator_arg);
 
514
  }
 
515
 
 
516
  char *cmd = (char *) malloc(len);
 
517
  sprintf(cmd, start_format, remote_proc_mgr_name, ud->port,
 
518
          (ud->log_collator_arg == NULL) ? "" : " -L ",
 
519
          (ud->log_collator_arg == NULL) ? "" : ud->log_collator_arg, remote_proc_mgr_killtm);
 
520
 
 
521
  in_buf.fill(cmd, strlen(cmd));
 
522
  free(cmd);
 
523
  cmd = NULL;
 
524
 
 
525
  const char *rmsg = send_remote_cmd(&in_buf, fd_in, &out_buf, fd_out);
 
526
 
 
527
  if (rmsg) {
 
528
    return rmsg;
 
529
  }
 
530
 
 
531
  char *end = out_buf.memchr('\n');
 
532
  *end = '\0';
 
533
  Debug("remote", "Response to start cmd: %s", out_buf.start());
 
534
 
 
535
  if (strcmp(out_buf.start(), "liftoff") != 0) {
 
536
    TE_Note("failed to start proc_manager : %s", out_buf.start());
 
537
    return "remote start failed";
 
538
  }
 
539
  close(fd_in);
 
540
  fd_in = -1;
 
541
 
 
542
  return NULL;
 
543
}
 
544
 
 
545
 
 
546
 
 
547
// const char* put_and_start_proc_manager()
 
548
//
 
549
//
 
550
const char *
 
551
put_and_start_proc_manager(int &fd_in, int &fd_out,
 
552
                           UserDirInfo * ud,
 
553
                           const char *remote_proc_mgr_name, const char *remote_arch, int remote_proc_mgr_killtm)
 
554
{
 
555
 
 
556
  sio_buffer in_buf;
 
557
  sio_buffer out_buf;
 
558
 
 
559
  char *local_pm = find_proc_manager_binary(ud, remote_arch);
 
560
 
 
561
  if (local_pm == NULL) {
 
562
    TE_Error("no process manager for arch %s found", remote_arch);
 
563
    return "no process manager for arch";
 
564
  }
 
565
 
 
566
  int local_file_fd = -1;
 
567
  do {
 
568
    local_file_fd = open(local_pm, O_RDONLY);
 
569
  } while (local_file_fd < 0 && errno == EINTR);
 
570
 
 
571
  if (local_file_fd < 0) {
 
572
    TE_Error("unable to open %s : %s", local_pm, strerror(errno));
 
573
    free(local_pm);
 
574
    return "open of proc_manager for transfer failed";
 
575
  }
 
576
 
 
577
  free(local_pm);
 
578
  local_pm = NULL;
 
579
 
 
580
  const char put_and_start_format[] = "cat - > %s; chmod 0755 %s; ./%s -r -q -d . -p %d%s%s -k %d\n";
 
581
 
 
582
  int len = sizeof(put_and_start_format) + (3 * strlen(remote_proc_mgr_name)) + 32 + 1;
 
583
  if (ud->log_collator_arg) {
 
584
    len += 3 + strlen(ud->log_collator_arg);
 
585
  }
 
586
 
 
587
  char *cmd = (char *) malloc(len);
 
588
  sprintf(cmd, put_and_start_format, remote_proc_mgr_name,
 
589
          remote_proc_mgr_name, remote_proc_mgr_name, ud->port,
 
590
          (ud->log_collator_arg == NULL) ? "" : " -L ",
 
591
          (ud->log_collator_arg == NULL) ? "" : ud->log_collator_arg, remote_proc_mgr_killtm);
 
592
 
 
593
  in_buf.fill(cmd, strlen(cmd));
 
594
  free(cmd);
 
595
  cmd = NULL;
 
596
 
 
597
  int timeout_ms = 60 * 1000;
 
598
  const char *rmsg = write_buffer(fd_in, &in_buf, &timeout_ms);
 
599
  char *end;
 
600
 
 
601
  if (rmsg) {
 
602
    goto CLEANUP;
 
603
  }
 
604
 
 
605
  rmsg = transfer_proc_manager_binary(local_file_fd, fd_in, &timeout_ms);
 
606
  close(fd_in);
 
607
  fd_in = -1;
 
608
 
 
609
  if (rmsg) {
 
610
    goto CLEANUP;
 
611
  }
 
612
 
 
613
  rmsg = read_until(fd_out, &out_buf, '\n', &timeout_ms);
 
614
 
 
615
  if (rmsg) {
 
616
    goto CLEANUP;
 
617
  }
 
618
 
 
619
  end = out_buf.memchr('\n');
 
620
  *end = '\0';
 
621
  Debug("remote", "Response to put and start: %s", out_buf.start());
 
622
 
 
623
  if (strcmp(out_buf.start(), "liftoff") != 0) {
 
624
    TE_Note("failed to push and start proc_manager : %s", out_buf.start());
 
625
    return "remote push_and_start failed";
 
626
  }
 
627
 
 
628
CLEANUP:
 
629
  if (local_file_fd >= 0) {
 
630
    close(local_file_fd);
 
631
  }
 
632
 
 
633
  if (rmsg) {
 
634
    TE_Error("put_and_start proc_manager failed %s", rmsg);
 
635
  }
 
636
  return rmsg;
 
637
}
 
638
 
 
639
const char *
 
640
handle_proc_manager(int &fd_in, int &fd_out, UserDirInfo * ud, const char *arch, int kw)
 
641
{
 
642
 
 
643
  sio_buffer in_buf;
 
644
  sio_buffer out_buf;
 
645
 
 
646
  const char proc_mgr_base[] = "proc_manager";
 
647
  int len = strlen(proc_mgr_base) + 1 + strlen(arch);
 
648
 
 
649
  char *proc_manager_name = (char *) malloc(len + 1);
 
650
  sprintf(proc_manager_name, "%s-%s", proc_mgr_base, arch);
 
651
  FreeOnDestruct pm_name_freer(proc_manager_name);
 
652
 
 
653
  const char chdir_format[] = "if cd %s\n" "then\n" "   echo ok\n" "fi\n";
 
654
 
 
655
  const char check_file_format[] = "if [ -e %s ]; then\n" "   echo ok\n" "else\n" "   echo not found\n" "fi\n";
 
656
 
 
657
  len = sizeof(chdir_format) + strlen(ud->test_stuff_path_and_dir) + 1;
 
658
  char *cmd = (char *) malloc(len);
 
659
 
 
660
  sprintf(cmd, chdir_format, ud->test_stuff_path_and_dir);
 
661
 
 
662
  in_buf.fill(cmd, strlen(cmd));
 
663
  free(cmd);
 
664
  cmd = NULL;
 
665
 
 
666
  const char *rmsg = send_remote_cmd(&in_buf, fd_in, &out_buf, fd_out);
 
667
 
 
668
  if (rmsg) {
 
669
    return rmsg;
 
670
  }
 
671
 
 
672
  char *end = out_buf.memchr('\n');
 
673
  *end = '\0';
 
674
  Debug("remote", "Response to cd: %s", out_buf.start());
 
675
 
 
676
  if (strcmp(out_buf.start(), "ok") != 0) {
 
677
    TE_Note("failed to change to remote directory : %s", out_buf.start());
 
678
    return "chdir to remote stuff_path failed";
 
679
  }
 
680
 
 
681
  in_buf.reset();
 
682
  out_buf.reset();
 
683
 
 
684
  len = sizeof(check_file_format) + strlen(proc_manager_name) + 1;
 
685
  cmd = (char *) malloc(len);
 
686
 
 
687
  sprintf(cmd, check_file_format, proc_manager_name);
 
688
 
 
689
  in_buf.fill(cmd, strlen(cmd));
 
690
  free(cmd);
 
691
  cmd = NULL;
 
692
 
 
693
  rmsg = send_remote_cmd(&in_buf, fd_in, &out_buf, fd_out);
 
694
 
 
695
  if (rmsg) {
 
696
    return rmsg;
 
697
  }
 
698
 
 
699
  end = out_buf.memchr('\n');
 
700
  *end = '\0';
 
701
  Debug("remote", "Response to check for %s : %s", proc_manager_name, out_buf.start());
 
702
 
 
703
  if (strcmp(out_buf.start(), "ok") == 0) {
 
704
    int ok = 0;
 
705
    rmsg = check_remote_proc_manager(fd_in, fd_out, ud, proc_manager_name, arch, &ok);
 
706
 
 
707
    if (rmsg) {
 
708
      return rmsg;
 
709
    }
 
710
 
 
711
    if (ok) {
 
712
      Debug("remote", "proc_manager is up to date on remote");
 
713
      rmsg = start_remote_proc_manager(fd_in, fd_out, ud, proc_manager_name, kw);
 
714
    } else {
 
715
      Debug("remote", "proc_manager is out of date on remote");
 
716
      rmsg = put_and_start_proc_manager(fd_in, fd_out, ud, proc_manager_name, arch, kw);
 
717
    }
 
718
 
 
719
  } else {
 
720
    Debug("remote", "no proc_manager on remote");
 
721
    rmsg = put_and_start_proc_manager(fd_in, fd_out, ud, proc_manager_name, arch, kw);
 
722
  }
 
723
 
 
724
  return rmsg;
 
725
}
 
726
 
 
727
const char *
 
728
check_remote_isalive(unsigned int ip, int port, int retries = 20)
 
729
{
 
730
 
 
731
  RafCmd request;
 
732
  RafCmd response;
 
733
  sio_buffer read_buffer;
 
734
 
 
735
  request(0) = strdup("0");
 
736
  request(1) = strdup("isalive");
 
737
 
 
738
  const char *rmsg = "Unknown Error";
 
739
  for (int i = 0; i < retries; i++) {
 
740
    int timeout_ms = 10 * 1000;
 
741
    int fd = SIO::make_client(ip, port);
 
742
    bool success = false;
 
743
 
 
744
    if (fd >= 0) {
 
745
      rmsg = send_raf_cmd(fd, &request, &timeout_ms);
 
746
      if (rmsg == NULL) {
 
747
        rmsg = read_raf_resp(fd, &read_buffer, &response, &timeout_ms);
 
748
        if (rmsg == NULL) {
 
749
          if (response.length() >= 2 && *(response[1]) == '0') {
 
750
            success = true;
 
751
          } else {
 
752
            rmsg = "bad raf reply";
 
753
          }
 
754
        }
 
755
      }
 
756
    } else {
 
757
      rmsg = "connect failed";
 
758
    }
 
759
 
 
760
    close(fd);
 
761
 
 
762
    if (success) {
 
763
      Debug("remote", "remote passed 'isalive' check");
 
764
      ink_debug_assert(rmsg == NULL);
 
765
      break;
 
766
    } else {
 
767
      Debug("remote", "remote failed 'isalive' check : %s", rmsg);
 
768
      response.clear();
 
769
      read_buffer.reset();
 
770
      usleep(500 * 1000);
 
771
    }
 
772
  }
 
773
 
 
774
  return rmsg;
 
775
}
 
776
 
 
777
int
 
778
remote_start(const char *hostname, unsigned int ip, UserDirInfo * ud, int kw)
 
779
{
 
780
  int in_pipe[2];
 
781
  int out_pipe[2];
 
782
 
 
783
  pid_t child_pid = start_remote_shell(ud, hostname, in_pipe, out_pipe);
 
784
 
 
785
  if (child_pid < 0) {
 
786
    return -1;
 
787
  }
 
788
 
 
789
  int in_fd = in_pipe[1];
 
790
  int out_fd = out_pipe[0];
 
791
  int return_value = -1;
 
792
 
 
793
  char *arch = NULL;
 
794
  const char *rmsg = determine_arch(in_fd, out_fd, &arch);
 
795
 
 
796
  if (rmsg) {
 
797
    free(arch);
 
798
    TE_Error("remote start on %s failed : %s", hostname, rmsg);
 
799
    goto CLEANUP;
 
800
  } else {
 
801
    Debug("remote", "Remote architecture for %s is %s", hostname, arch);
 
802
  }
 
803
 
 
804
  rmsg = setup_remote_directories(in_fd, out_fd, ud);
 
805
 
 
806
  if (rmsg) {
 
807
    TE_Error("remote directory setup on %s failed : %s", hostname, rmsg);
 
808
    goto CLEANUP;
 
809
  }
 
810
 
 
811
  rmsg = handle_proc_manager(in_fd, out_fd, ud, arch, kw);
 
812
 
 
813
  if (rmsg) {
 
814
    TE_Error("proc_manager startup on %s failed %s", hostname, rmsg);
 
815
    goto CLEANUP;
 
816
  }
 
817
 
 
818
  rmsg = check_remote_isalive(ip, ud->port);
 
819
  if (rmsg) {
 
820
    TE_Error("proc_manager on %s failed isalive check : %s", hostname, rmsg);
 
821
  } else {
 
822
    return_value = 0;
 
823
  }
 
824
 
 
825
CLEANUP:
 
826
 
 
827
  if (in_fd >= 0) {
 
828
    int timeout_ms = 10000;
 
829
    sio_buffer close_buf;
 
830
    close_buf.fill("exit\n", 5);
 
831
    write_buffer(in_fd, &close_buf, &timeout_ms);
 
832
    close(in_fd);
 
833
  }
 
834
 
 
835
  if (out_fd >= 0) {
 
836
    close(out_fd);
 
837
  }
 
838
 
 
839
  if (child_pid > 0) {
 
840
    int exit_status;
 
841
    reap_and_kill_child(child_pid, &exit_status);
 
842
    child_pid = -1;
 
843
  }
 
844
 
 
845
  if (arch) {
 
846
    free(arch);
 
847
  }
 
848
 
 
849
  return return_value;
 
850
}