rsmportalexample.cc 16.6 KB
Newer Older
1
2
3
4
5
6
7
/*
 * @file:   mainwindow.cpp
 * @author: Jordan P. Lefebvre, lefebvrejp@ornl.gov
 *
 * Created on June 24, 2018, 10:52 AM
 */

8
#include <fcntl.h>
9
#include <memory>
10

11
12
#include <QApplication>
#include <QGridLayout>
13
#include <QHBoxLayout>
14
#include <QInputDialog>
15
#include <QLabel>
16
#include <QMessageBox>
17
#include <QTabWidget>
18
#include "rsmportalexample.hh"
19
20
21
22
23
24
25

#include "radixbug/bug.hh"
using namespace rsm;

ExamplePortalWidget::ExamplePortalWidget(QWidget *parent)
    : QWidget(parent)
{
26
27
  queue = &queueSGE;

28
29
30
31
32
  QGridLayout *layout    = new QGridLayout(this);
  QLabel *proxyHostLabel = new QLabel("Proxy:", this);
  QLabel *hostLabel      = new QLabel("Host:", this);
  QLabel *portLabel      = new QLabel("Port:", this);
  QLabel *userNameLabel  = new QLabel("Username:", this);
33

34
35
36
37
38
39
  mProxyEdit            = new QLineEdit(this);
  mHostEdit             = new QLineEdit("", this);
  mPortEdit             = new QLineEdit("", this);
  mUserNameEdit         = new QLineEdit("", this);
  mConnectButton        = new QPushButton("Connect", this);
  mCommandEdit          = new QLineEdit(this);
40
  mCommandSubmitButton  = new QPushButton("Submit Command", this);
41
42
43
44
45
46
47
48
  mSchedulerBox         = new QGroupBox(this);
  mPBSRadioButton       = new QRadioButton("PBS", this);
  mSGERadioButton       = new QRadioButton("SGE", this);
  mListAllQueuesButton  = new QPushButton("List All Queues", this);
  mGetQueueInfoButton   = new QPushButton("Queue Info", this);
  mGetQueueInfoTextEdit = new QLineEdit(this);
  mGetAllNodeInfoButton = new QPushButton("Node Info", this);
  mGetAllJobInfoButton  = new QPushButton("Job Info", this);
49
50
  mSubmitJobButton      = new QPushButton("Submit Job", this);
  mDeleteJobButton      = new QPushButton("Delete Job(s)", this);
51
  mDeleteJobTextEdit    = new QLineEdit(this);
52
  mSubmitJobTextEdit    = new QLineEdit("", this);
53
54
55
56
57
  mTextEdit             = new QTextEdit(this);
  mOpenFileButton       = new QPushButton("Open File", this);
  mOpenFileEdit         = new QLineEdit(this);
  mOpenDirButton        = new QPushButton("Open Directory", this);
  mOpenDirEdit          = new QLineEdit(this);
58

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  int row = 0;
  layout->addWidget(proxyHostLabel, row, 0);
  layout->addWidget(mProxyEdit, row, 1);
  layout->addWidget(hostLabel, ++row, 0);
  layout->addWidget(mHostEdit, row, 1);
  layout->addWidget(portLabel, ++row, 0);
  layout->addWidget(mPortEdit, row, 1);
  layout->addWidget(userNameLabel, ++row, 0);
  layout->addWidget(mUserNameEdit, row, 1);
  layout->addWidget(mConnectButton, ++row, 1);

  QHBoxLayout *mSGBLayout = new QHBoxLayout(mSchedulerBox);
  mSchedulerBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum);
  mSGBLayout->addWidget(mPBSRadioButton);
  mSGBLayout->addWidget(mSGERadioButton);
  layout->addWidget(mSchedulerBox, ++row, 1);
  mSchedulerButtonGroup = new QButtonGroup(this);
  mSchedulerButtonGroup->addButton(mPBSRadioButton);
  mSchedulerButtonGroup->addButton(mSGERadioButton);
  layout->addWidget(mSchedulerBox, ++row, 1);

  layout->addWidget(mCommandSubmitButton, ++row, 1);
  layout->addWidget(mCommandEdit, row, 2);
  layout->addWidget(mListAllQueuesButton, ++row, 0);
  layout->addWidget(mGetQueueInfoButton, row, 1);
  layout->addWidget(mGetQueueInfoTextEdit, row, 2);
  layout->addWidget(mGetAllNodeInfoButton, ++row, 1);
86
87
  layout->addWidget(mSubmitJobButton, ++row, 1);
  layout->addWidget(mSubmitJobTextEdit, row, 2);
88
89
90
91
  layout->addWidget(mGetAllJobInfoButton, ++row, 1);
  layout->addWidget(mDeleteJobButton, ++row, 1);
  layout->addWidget(mDeleteJobTextEdit, row, 2);
  layout->addWidget(mTextEdit, ++row, 0, 2, 3);
92
93
94
95
96
  row++;
  layout->addWidget(mOpenFileButton, ++row, 1);
  layout->addWidget(mOpenFileEdit, row, 2);
  layout->addWidget(mOpenDirButton, ++row, 1);
  layout->addWidget(mOpenDirEdit, row, 2);
97
98
99

  connect(mConnectButton, &QPushButton::pressed, this,
          &ExamplePortalWidget::connectToHost);
100
101
102

  connect(mSchedulerButtonGroup,
          QOverload<int>::of(&QButtonGroup::buttonClicked), [=](int id) {
103
            (void)sizeof(id);
104
105
106
107
108
109
110
111
            QString name = mSchedulerButtonGroup->checkedButton()->text();
            if ("PBS" == name)
              queue = &queuePBS;
            else if ("SGE" == name)
              queue = &queueSGE;
          });
  mSGERadioButton->click();

112
113
  connect(mCommandSubmitButton, &QPushButton::pressed, this,
          &ExamplePortalWidget::submitCommandToHost);
114
115
116
117
118
119
120
121
  connect(mListAllQueuesButton, &QPushButton::pressed, this,
          &ExamplePortalWidget::submitListAllQueuesToHost);
  connect(mGetQueueInfoButton, &QPushButton::pressed, this,
          &ExamplePortalWidget::submitGetQueueInfoToHost);
  connect(mGetAllNodeInfoButton, &QPushButton::pressed, this,
          &ExamplePortalWidget::submitGetAllNodeInfoToHost);
  connect(mGetAllJobInfoButton, &QPushButton::pressed, this,
          &ExamplePortalWidget::submitGetAllJobInfoToHost);
122
123
  connect(mSubmitJobButton, &QPushButton::pressed, this,
          &ExamplePortalWidget::submitSubmitJobToHost);
124
125
  connect(mDeleteJobButton, &QPushButton::pressed, this,
          &ExamplePortalWidget::submitDeleteJobToHost);
126

127
128
  mSessionCon = std::make_shared<SessionController>();
  connect(mSessionCon.get(), &SessionController::connectionFailed, this,
129
          &ExamplePortalWidget::connectionFailed);
130
  connect(mSessionCon.get(), &SessionController::connectionSuccessful, this,
131
          &ExamplePortalWidget::connectionSuccessful);
132
  connect(mSessionCon.get(), &SessionController::disconnectSuccessful, this,
133
          &ExamplePortalWidget::disconnectSuccessful);
134
  connect(mSessionCon.get(),
135
136
          &SessionController::interactiveAuthenticationRequested, this,
          &ExamplePortalWidget::interactiveAuthenticationRequested);
137
  connect(mSessionCon.get(), &SessionController::getServerPublicKeyFailed, this,
138
          &ExamplePortalWidget::getServerPublicKeyFailed);
139
  connect(mSessionCon.get(), &SessionController::hostUnknown, this,
140
          &ExamplePortalWidget::hostUnknown);
141
  connect(mSessionCon.get(), &SessionController::hostPublicKeyChanged, this,
142
          &ExamplePortalWidget::hostPublicKeyChanged);
143
144
145
  connect(mSessionCon.get(), &SessionController::verifyKnownHostSuccessful,
          this, &ExamplePortalWidget::verifyKnownHostSuccessful);
  connect(mSessionCon.get(), &SessionController::knownHostError, this,
146
          &ExamplePortalWidget::knownHostError);
147
  connect(mSessionCon.get(), &SessionController::authenticationError, this,
148
          &ExamplePortalWidget::authenticationError);
149
  connect(mSessionCon.get(), &SessionController::authenticationSucceeded, this,
150
          &ExamplePortalWidget::authenticationSucceeded);
151
  connect(mSessionCon.get(), &SessionController::passwordRequested, this,
152
          &ExamplePortalWidget::passwordRequested);
153
  connect(mSessionCon.get(), &SessionController::loginBannerIssued, this,
154
          &ExamplePortalWidget::loginBannerIssued);
155
  connect(mSessionCon.get(), &SessionController::execOutputReady, this,
156
          &ExamplePortalWidget::execOutputReady);
157
  connect(mSessionCon.get(), &SessionController::execFailed, this,
158
          &ExamplePortalWidget::execFailed);
159
  connect(mSessionCon.get(), &SessionController::execFinished, this,
160
          &ExamplePortalWidget::execFinished);
161
162
163
164
165

  connect(mOpenFileButton, &QPushButton::pressed, this,
          &ExamplePortalWidget::openFile);
  connect(mOpenDirButton, &QPushButton::pressed, this,
          &ExamplePortalWidget::openDir);
166
167
168
169
170
171
}

void ExamplePortalWidget::connectToHost()
{
  radix_tagged_line("Host:" << mHostEdit->text().toStdString());

172
173
  if (mConnectButton->text().compare("Disconnect") == 0)
  {
174
    mSessionCon->disconnect();
175
176
177
178
    mConnectButton->setText("Connect");
  }
  else
  {
179
180
181
182
183
    mSessionCon->setProxyCommand(mProxyEdit->text());
    mSessionCon->setHost(mHostEdit->text());
    mSessionCon->setPort(mPortEdit->text().toInt());
    mSessionCon->setUser(mUserNameEdit->text());
    mSessionCon->connect();
184
  }
185
186
}

187
188
189
190
void ExamplePortalWidget::submitCommandToHost()
{
  radix_tagged_line("submitCommandToHost()");
  QString command = mCommandEdit->text();
191
  submitCommand("custom", command);
192
}
193

194
195
196
197
void ExamplePortalWidget::submitListAllQueuesToHost()
{
  radix_tagged_line("submitListAllQueuesToHost()");
  QString command = queue->listAllQueues();
198
  submitCommand("listAllQueues", command);
199
200
201
202
203
204
}

void ExamplePortalWidget::submitGetQueueInfoToHost()
{
  radix_tagged_line("submitGetQueueInfoToHost()");
  QString command = queue->showQueueInfo(mGetQueueInfoTextEdit->text());
205
  submitCommand("showQueueInfo", command);
206
207
208
209
210
211
}

void ExamplePortalWidget::submitGetAllNodeInfoToHost()
{
  radix_tagged_line("submitGetAllNodeInfoToHost()");
  QString command = queue->listAllNodeInfo();
212
  submitCommand("listAllNodeInfo", command);
213
214
215
216
217
218
}

void ExamplePortalWidget::submitGetAllJobInfoToHost()
{
  radix_tagged_line("submitGetAllJobInfoToHost()");
  QString command = queue->checkJobs(QStringList());
219
220
221
222
223
224
225
226
227
  submitCommand("checkJobs", command);
}

void ExamplePortalWidget::submitSubmitJobToHost()
{
  radix_tagged_line("submitSubmitJobToHost()");
  QStringList jobIDs = QStringList();
  QString command    = queue->submitJob(mSubmitJobTextEdit->text());
  submitCommand("submitJob", command);
228
229
230
231
232
233
234
235
236
}

void ExamplePortalWidget::submitDeleteJobToHost()
{
  radix_tagged_line("submitDeleteJobToHost()");
  QStringList jobIDs = QStringList();
  if (mDeleteJobTextEdit->text().length() > 0)
    jobIDs = mDeleteJobTextEdit->text().split(QRegExp("[ ,]"));
  QString command = queue->deleteJobs(jobIDs);
237
  submitCommand("deleteJobs", command);
238
239
}

240
void ExamplePortalWidget::submitCommand(QString commandType, QString command)
241
{
242
243
  if ("" != execingCommandType) return;
  execingCommandType = commandType;
244
  mSessionCon->requestExec(command);
245
246
247
248
249
250
251
252
253
254
255
}

void ExamplePortalWidget::connectionFailed(QString message)
{
  mTextEdit->append("Connection failed.\n");
  mTextEdit->append(message);
}

void ExamplePortalWidget::connectionSuccessful()
{
  mTextEdit->append("Connection successful.\nVerifying host...\n");
256
  mSessionCon->verifyKnownHost();
257
258
}

259
260
261
262
263
264
void ExamplePortalWidget::disconnectSuccessful()
{
  mTextEdit->append("Disconnected.\n");
}

void ExamplePortalWidget::verifyKnownHostSuccessful()
265
{
266
  mTextEdit->append("Verification successful.\nAuthenticating...\n");
267
  mSessionCon->authenticate();
268
269
}

270
271
272
273
274
275
276
277
278
279
280
281
void ExamplePortalWidget::interactiveAuthenticationRequested(
    QString instruction, QString name, QStringList prompts)
{
  mTextEdit->append("Interactive authentication requested.");
  mTextEdit->append("Instruction: ");
  mTextEdit->append(instruction);
  mTextEdit->append("Name:");
  mTextEdit->append(name);
  for (int i = 0; i < prompts.size(); ++i)
  {
    mTextEdit->append(prompts.at(i));
  }
282
283
284
285
286
287
288

  if (!prompts.isEmpty())
  {
    QString text = QInputDialog::getText(this, "Authentication", prompts.at(0),
                                         QLineEdit::Password);
    if (text.isEmpty())
    {
289
      mSessionCon->disconnect();
290
291
292
293
294
    }
    else
    {
      QStringList responses;
      responses << text;
295
      mSessionCon->authenticatePrompts(responses);
296
297
298
299
300
301
    }
  }
  else
  {
    radix_tagged_line("Reponsing with empty handshake.");
    QStringList empty;
302
    mSessionCon->authenticatePrompts(empty);
303
  }
304
305
}

306
307
308
void ExamplePortalWidget::getServerPublicKeyFailed()
{
  mTextEdit->append("Retrieval of host's public key failed.\n");
309
  mSessionCon->disconnect();
310
311
312
313
}

void ExamplePortalWidget::hostUnknown(QString host_hash)
{
314
315
316
317
318
319
320
321
322
  int ret = QMessageBox::warning(
      this, tr("Host Unknown"),
      QString("The remote host is unknown.\n")
          .append("Are you sure you want to continue connecting?\n")
          .append("Remote host key:")
          .append(host_hash),
      QMessageBox::Yes | QMessageBox::Cancel);
  if (ret == QMessageBox::Yes)
  {
323
    mSessionCon->acceptHostPublicKeyUpdate();
324
325
326
  }
  else
  {
327
    mSessionCon->disconnect();
328
  }
329
330
331
332
333
334
}

void ExamplePortalWidget::hostPublicKeyChanged(QString host_hash)
{
  mTextEdit->append("Host key has changed.\nChanged key:");
  mTextEdit->append(host_hash);
335
  mTextEdit->append("This could be a man-in-the-middle attack.\n");
336
  mSessionCon->disconnect();
337
338
339
340
}

void ExamplePortalWidget::hostPublicKeyUnavailable()
{
341
  mTextEdit->append("Host key is unavailable.\n");
342
  mSessionCon->disconnect();
343
344
345
346
347
348
349
350
}

void ExamplePortalWidget::knownHostError(QString message)
{
  mTextEdit->append("Error verifying known host.\n");
  mTextEdit->append(message);
  mTextEdit->append("\n");

351
  mSessionCon->disconnect();
352
353
354
355
356
357
358
}

void ExamplePortalWidget::authenticationError(QString message)
{
  mTextEdit->append("Authentication error.\n");
  mTextEdit->append(message);
  mTextEdit->append("\n");
359
  mSessionCon->disconnect();
360
361
362
363
364
365
}

void ExamplePortalWidget::authenticationSucceeded()
{
  mTextEdit->append("Authentication succeeded.");
  mTextEdit->append("\n");
366
  mConnectButton->setText("Disconnect");
367
368
369
370
371
372
}

void ExamplePortalWidget::passwordRequested()
{
  mTextEdit->append("Password requested.");
  mTextEdit->append("\n");
373
374
375
376
  QString text = QInputDialog::getText(this, "Authentication",
                                       "Password:", QLineEdit::Password);
  if (text.isEmpty())
  {
377
    mSessionCon->disconnect();
378
379
380
  }
  else
  {
381
    mSessionCon->authenticateWithPassword(text);
382
  }
383
384
385
386
}

void ExamplePortalWidget::loginBannerIssued(QString message)
{
387
388
389
390
  int ret = QMessageBox::warning(this, tr("Host Login Banner"), message,
                                 QMessageBox::Ok | QMessageBox::Cancel);
  if (ret != QMessageBox::Ok)
  {
391
    mSessionCon->disconnect();
392
  }
393
394
395
396
397
398
  mTextEdit->append(message);
  mTextEdit->append("\n");
}

void ExamplePortalWidget::execOutputReady()
{
399
  mTextEdit->append(mSessionCon->readExecOutput());
400
401
402
403
}

void ExamplePortalWidget::execFailed(QString message)
{
404
  radix_tagged_line(message.toStdString());
405
406
  mTextEdit->append(message);
  mTextEdit->append("\n");
407
  execingCommandType = "";
408
409
410
411
412
}

void ExamplePortalWidget::execFinished()
{
  mTextEdit->append("Execution finished.\n");
413
414
  if ("submitJob" == execingCommandType)
  {
415
    int jobID = queueSGE.parseSubmitJobReturn(mSessionCon->readExecOutput());
416
417
418
419
420
    fprintf(stderr, "%d\n", jobID);
  }
  if ("checkJobs" == execingCommandType)
  {
    QSet<int> jobIDs =
421
        queueSGE.parseCheckJobsReturn(mSessionCon->readExecOutput());
422
423
424
425
426
427
428
    fprintf(stderr, "--\n");
    for (auto jobID : jobIDs) fprintf(stderr, "%d\n", jobID);
    fprintf(stderr, "--\n");
  }
  if ("deleteJobs" == execingCommandType)
  {
    QSet<int> jobIDs =
429
        queueSGE.parseDeleteJobsReturn(mSessionCon->readExecOutput());
430
431
432
433
434
    fprintf(stderr, "--\n");
    for (auto jobID : jobIDs) fprintf(stderr, "%d\n", jobID);
    fprintf(stderr, "--\n");
  }
  execingCommandType = "";
435
}
436

437
438
439
440
441
void ExamplePortalWidget::openFile()
{
  radix_tagged_line(
      "Opening remote file:" << mOpenFileEdit->text().toStdString());

442
443
444
445
446
  std::unique_ptr<SFTPSession> sftpSession(
      mSessionCon->session()->newSFTPSession());
  std::unique_ptr<SFTPFile> sftpFile(
      sftpSession->openFile(mOpenFileEdit->text(), O_RDONLY));
  if (!sftpFile->isOpen())
447
448
449
450
451
  {
    mTextEdit->append("FAILED to open file");
    return;
  }
  // read some of the file
452
453
  QString tmpStr = sftpFile->read(1000);
  if (!sftpFile->isOpen())
454
455
456
457
458
459
460
461
  {
    {
      mTextEdit->append("ERROR reading file");
      return;
    }
  }
  mTextEdit->append("File contents:");
  mTextEdit->append(tmpStr);
462
  if (!sftpFile->close())
463
464
465
466
467
468
469
470
471
472
473
  {
    mTextEdit->append("ERROR closing file");
    return;
  }
}

void ExamplePortalWidget::openDir()
{
  radix_tagged_line(
      "Opening remote directory:" << mOpenFileEdit->text().toStdString());

474
475
476
477
478
  std::unique_ptr<SFTPSession> sftpSession(
      mSessionCon->session()->newSFTPSession());
  std::unique_ptr<SFTPDir> sftpDir(sftpSession->openDir(mOpenDirEdit->text()));

  if (!sftpDir->isOpen())
479
480
481
482
483
484
  {
    mTextEdit->append("FAILED to open directory");
    return;
  }
  mTextEdit->append("Directory entries:");
  // read dir entries
485
  while (sftpDir->hasNext())
486
  {
487
    SFTPAttributes *a = sftpDir->next();
488
489
490
491
492
493
494
495
    if (nullptr == a)
    {
      mTextEdit->append("ERROR reading directory entry");
      break;
    }
    mTextEdit->append(a->longname);
    delete a;
  }
496
  if (!sftpDir->close())
497
498
499
500
501
502
  {
    mTextEdit->append("ERROR closing directory");
    return;
  }
}

503
// ----------------------------------------------------------------------------
504
505
506
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
507
  setGeometry(120, 120, 720, 720);
508

509
510
  QTabWidget *tab                 = new QTabWidget(this);
  ExamplePortalWidget *portalView = new ExamplePortalWidget(tab);
511
512
513

  tab->addTab(portalView, "connect");
  setCentralWidget(tab);
514
515
516
517
518
}

MainWindow::~MainWindow() {}

/******************************************************************************/
519
/******************************** MAIN PROGRAM ********************************/
520
521
522
523
524
525
526
527
528
529
530
/******************************************************************************/

int main(int argc, char **argv)
{
  QApplication app(argc, argv);
  MainWindow mainWindow;
  mainWindow.show();
  mainWindow.raise();

  return app.exec();
}