Skip to content

Commit 4708a99

Browse files
committed
add gui to configure ssh
1 parent 44d77c2 commit 4708a99

13 files changed

+460
-57
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ set(hotspot_SRCS
5050
perfoutputwidgettext.cpp
5151
perfoutputwidgetkonsole.cpp
5252
costcontextmenu.cpp
53+
ssh.cpp
5354

5455
# ui files:
5556
mainwindow.ui

src/mainwindow.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ MainWindow::MainWindow(QWidget* parent)
122122
settings->setObjdump(m_settingsDialog->objdump());
123123
});
124124

125+
connect(m_settingsDialog, &QDialog::accepted, m_recordPage, &RecordPage::onRemoteDevicesChanged);
126+
125127
connect(settings, &Settings::sysrootChanged, m_resultsPage, &ResultsPage::setSysroot);
126128
connect(settings, &Settings::appPathChanged, m_resultsPage, &ResultsPage::setAppPath);
127129
connect(settings, &Settings::objdumpChanged, m_resultsPage, &ResultsPage::setObjdump);
@@ -227,6 +229,9 @@ MainWindow::MainWindow(QWidget* parent)
227229
settings->setDebuginfodUrls(m_config->group("debuginfod").readEntry("urls", QStringList()));
228230
connect(Settings::instance(), &Settings::debuginfodUrlsChanged, this,
229231
[this, settings] { m_config->group("debuginfod").writeEntry("urls", settings->debuginfodUrls()); });
232+
233+
const auto askpass = QStandardPaths::findExecutable(QLatin1String("ksshaskpass"));
234+
settings->setSshaskpassPath(m_config->group("SSH").readEntry("sshaskpass", askpass));
230235
}
231236

232237
auto* prettifySymbolsAction = ui->viewMenu->addAction(tr("Prettify Symbols"));

src/perfrecordssh.cpp

Lines changed: 23 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -36,51 +36,29 @@
3636
#include <csignal>
3737

3838
#include "hotspot-config.h"
39-
40-
QString sshOutput(const QString& hostname, const QStringList& command)
41-
{
42-
QProcess ssh;
43-
ssh.setProgram(QStandardPaths::findExecutable(QLatin1String("ssh")));
44-
const auto arguments = QStringList({hostname}) + command;
45-
ssh.setArguments(arguments);
46-
ssh.start();
47-
ssh.waitForFinished();
48-
return QString::fromUtf8(ssh.readAll());
49-
}
50-
51-
int sshExitCode(const QString& hostname, const QStringList& command)
52-
{
53-
QProcess ssh;
54-
ssh.setProgram(QStandardPaths::findExecutable(QLatin1String("ssh")));
55-
const auto arguments = QStringList({hostname}) + command;
56-
ssh.setArguments(arguments);
57-
ssh.start();
58-
ssh.waitForFinished();
59-
return ssh.exitCode();
60-
}
39+
#include "ssh.h"
6140

6241
PerfRecordSSH::PerfRecordSSH(QObject* parent)
6342
: PerfRecord(parent)
6443
{
65-
m_hostname = QStringLiteral("user@localhost");
6644
}
6745

6846
PerfRecordSSH::~PerfRecordSSH() = default;
6947

7048
void PerfRecordSSH::record(const QStringList& perfOptions, const QString& outputPath, bool /*elevatePrivileges*/,
7149
const QString& exePath, const QStringList& exeOptions, const QString& workingDirectory)
7250
{
73-
int exitCode = sshExitCode(m_hostname, {QLatin1String("test"), QLatin1String("-e"), exePath});
51+
int exitCode = sshExitCode(m_deviceName, {QLatin1String("test"), QLatin1String("-e"), exePath});
7452
if (exitCode) {
7553
emit recordingFailed(tr("File '%1' does not exist.").arg(exePath));
7654
}
7755

78-
exitCode = sshExitCode(m_hostname, {QLatin1String("test"), QLatin1String("-f"), exePath});
56+
exitCode = sshExitCode(m_deviceName, {QLatin1String("test"), QLatin1String("-f"), exePath});
7957
if (exitCode) {
8058
emit recordingFailed(tr("'%1' is not a file.").arg(exePath));
8159
}
8260

83-
exitCode = sshExitCode(m_hostname, {QLatin1String("test"), QLatin1String("-x"), exePath});
61+
exitCode = sshExitCode(m_deviceName, {QLatin1String("test"), QLatin1String("-x"), exePath});
8462
if (exitCode) {
8563
emit recordingFailed(tr("File '%1' is not executable.").arg(exePath));
8664
}
@@ -130,32 +108,32 @@ void PerfRecordSSH::sendInput(const QByteArray& input)
130108

131109
QString PerfRecordSSH::currentUsername()
132110
{
133-
if (m_hostname.isEmpty())
111+
if (m_deviceName.isEmpty())
134112
return {};
135-
return sshOutput(m_hostname, {QLatin1String("echo"), QLatin1String("$USERNAME")}).simplified();
113+
return sshOutput(m_deviceName, {QLatin1String("echo"), QLatin1String("$USERNAME")}).simplified();
136114
}
137115

138116
bool PerfRecordSSH::canTrace(const QString& path)
139117
{
140-
if (m_hostname.isEmpty())
118+
if (m_deviceName.isEmpty())
141119
return false;
142120

143121
// exit code == 0 -> true
144-
bool isDir = sshExitCode(m_hostname, {QLatin1String("test"), QLatin1String("-d"), path}) == 0;
145-
bool isReadable = sshExitCode(m_hostname, {QLatin1String("test"), QLatin1String("-r"), path}) == 0;
122+
bool isDir = sshExitCode(m_deviceName, {QLatin1String("test"), QLatin1String("-d"), path}) == 0;
123+
bool isReadable = sshExitCode(m_deviceName, {QLatin1String("test"), QLatin1String("-r"), path}) == 0;
146124

147125
if (!isDir || !isReadable) {
148126
return false;
149127
}
150128

151129
QString paranoid =
152-
sshOutput(m_hostname, {QLatin1String("cat"), QLatin1String("/proc/sys/kernel/perf_event_paranoid")});
130+
sshOutput(m_deviceName, {QLatin1String("cat"), QLatin1String("/proc/sys/kernel/perf_event_paranoid")});
153131
return paranoid.trimmed() == QLatin1String("-1");
154132
}
155133

156134
bool PerfRecordSSH::canProfileOffCpu()
157135
{
158-
if (m_hostname.isEmpty())
136+
if (m_deviceName.isEmpty())
159137
return false;
160138
return canTrace(QStringLiteral("events/sched/sched_switch"));
161139
}
@@ -186,16 +164,16 @@ static QString perfBuildOptions(const QString& hostname)
186164

187165
bool PerfRecordSSH::canSampleCpu()
188166
{
189-
if (m_hostname.isEmpty())
167+
if (m_deviceName.isEmpty())
190168
return false;
191-
return perfRecordHelp(m_hostname).contains(QLatin1String("--sample-cpu"));
169+
return perfRecordHelp(m_deviceName).contains(QLatin1String("--sample-cpu"));
192170
}
193171

194172
bool PerfRecordSSH::canSwitchEvents()
195173
{
196-
if (m_hostname.isEmpty())
174+
if (m_deviceName.isEmpty())
197175
return false;
198-
return perfRecordHelp(m_hostname).contains(QLatin1String("--switch-events"));
176+
return perfRecordHelp(m_deviceName).contains(QLatin1String("--switch-events"));
199177
}
200178

201179
bool PerfRecordSSH::canUseAio()
@@ -206,16 +184,16 @@ bool PerfRecordSSH::canUseAio()
206184

207185
bool PerfRecordSSH::canCompress()
208186
{
209-
if (m_hostname.isEmpty())
187+
if (m_deviceName.isEmpty())
210188
return false;
211-
return Zstd_FOUND && perfBuildOptions(m_hostname).contains(QLatin1String("zstd: [ on ]"));
189+
return Zstd_FOUND && perfBuildOptions(m_deviceName).contains(QLatin1String("zstd: [ on ]"));
212190
}
213191

214192
bool PerfRecordSSH::isPerfInstalled()
215193
{
216-
if (m_hostname.isEmpty())
194+
if (m_deviceName.isEmpty())
217195
return false;
218-
return sshExitCode(m_hostname, {QLatin1String("perf")}) != 127;
196+
return sshExitCode(m_deviceName, {QLatin1String("perf")}) != 127;
219197
}
220198

221199
void PerfRecordSSH::startRecording(const QStringList& perfOptions, const QString& outputPath,
@@ -250,12 +228,13 @@ void PerfRecordSSH::startRecording(const QStringList& perfOptions, const QString
250228

251229
m_recordProcess = new QProcess(this);
252230
m_recordProcess->setProgram(QStandardPaths::findExecutable(QLatin1String("ssh")));
253-
m_recordProcess->setArguments({m_hostname, QLatin1String("perf ") + perfCommand.join(QLatin1Char(' '))});
231+
const auto arguments =
232+
assembleSSHArguments(m_deviceName, {QLatin1String("perf ") + perfCommand.join(QLatin1Char(' '))});
233+
m_recordProcess->setArguments(arguments);
234+
m_recordProcess->setProcessEnvironment(sshEnvironment());
254235
m_recordProcess->start();
255236
m_recordProcess->waitForStarted();
256237

257-
qDebug() << m_recordProcess->arguments().join(QLatin1Char(' '));
258-
259238
emit recordingStarted(QLatin1String("perf"), perfCommand);
260239

261240
connect(m_recordProcess, &QProcess::readyReadStandardOutput, this,

src/perfrecordssh.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ class PerfRecordSSH : public PerfRecord
3838
PerfRecordSSH(QObject* parent = nullptr);
3939
~PerfRecordSSH();
4040

41+
void setDeviceName(const QString& device)
42+
{
43+
m_deviceName = device;
44+
}
45+
4146
void record(const QStringList& perfOptions, const QString& outputPath, bool elevatePrivileges,
4247
const QString& exePath, const QStringList& exeOptions, const QString& workingDirectory) override;
4348
void record(const QStringList& perfOptions, const QString& outputPath, bool elevatePrivileges,
@@ -70,6 +75,6 @@ class PerfRecordSSH : public PerfRecord
7075

7176
QProcess* m_recordProcess = nullptr;
7277
QFile* m_outputFile;
73-
QString m_hostname;
78+
QString m_deviceName;
7479
bool m_userTerminated = false;
7580
};

src/recordpage.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -407,20 +407,19 @@ RecordPage::RecordPage(QWidget* parent)
407407

408408
perfRecordChanged();
409409

410-
ui->remoteTargetComboBox->addItem(QStringLiteral("localhost"));
411-
ui->remoteTargetComboBox->addItem(QStringLiteral("remote test 1"));
410+
const auto sshPath = QStandardPaths::findExecutable(QLatin1String("ssh"));
411+
ui->remoteTargetGroup->setVisible(!sshPath.isEmpty());
412+
413+
onRemoteDevicesChanged();
412414

413415
connect(ui->remoteTargetComboBox, qOverload<int>(&QComboBox::currentIndexChanged), this,
414416
[this, perfRecordChanged](int index) {
415417
if (index == 0) {
416418
m_perfRecord = new PerfRecord(this);
417-
qDebug() << "PerfRecord";
418419
} else {
419420
auto recordSsh = new PerfRecordSSH(this);
420-
// TODO: this
421-
// recordSsh->setHostname();
421+
recordSsh->setDeviceName(ui->remoteTargetComboBox->currentText());
422422
m_perfRecord = recordSsh;
423-
qDebug() << "PerfRecordSSH";
424423
}
425424
perfRecordChanged();
426425
});
@@ -824,3 +823,17 @@ void RecordPage::updateOffCpuCheckboxState()
824823
ui->offCpuCheckBox->setChecked(config().readEntry(QStringLiteral("offCpuProfiling"), false));
825824
}
826825
}
826+
827+
void RecordPage::onRemoteDevicesChanged()
828+
{
829+
ui->remoteTargetComboBox->clear();
830+
ui->remoteTargetComboBox->addItem(QStringLiteral("localhost"));
831+
832+
const auto deviceConfig = KSharedConfig::openConfig()->group("devices");
833+
auto t = deviceConfig.groupList();
834+
for (const auto& device : deviceConfig.groupList()) {
835+
if (deviceConfig.hasGroup(device)) {
836+
ui->remoteTargetComboBox->addItem(device);
837+
}
838+
}
839+
}

src/recordpage.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ class RecordPage : public QWidget
5454
void homeButtonClicked();
5555
void openFile(QString filePath);
5656

57+
public slots:
58+
void onRemoteDevicesChanged();
59+
5760
private slots:
5861
void onApplicationNameChanged(const QString& filePath);
5962
void onStartRecordingButtonClicked(bool checked);

src/settings.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,9 @@ void Settings::setCallgraphColors(const QColor& active, const QColor& inactive)
132132
emit callgraphChanged();
133133
}
134134
}
135+
136+
void Settings::setSshaskpassPath(const QString& sshaskpath)
137+
{
138+
m_sshaskpassPath = sshaskpath;
139+
emit sshaskpassChanged(m_sshaskpassPath);
140+
}

src/settings.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,11 @@ class Settings : public QObject
119119
return m_callgraphColor;
120120
}
121121

122+
QString sshaskpassPath() const
123+
{
124+
return m_sshaskpassPath;
125+
}
126+
122127
signals:
123128
void prettifySymbolsChanged(bool);
124129
void collapseTemplatesChanged(bool);
@@ -134,6 +139,7 @@ class Settings : public QObject
134139
void archChanged(const QString& arch);
135140
void objdumpChanged(const QString& objdump);
136141
void callgraphChanged();
142+
void sshaskpassChanged(const QString& path);
137143

138144
public slots:
139145
void setPrettifySymbols(bool prettifySymbols);
@@ -152,6 +158,7 @@ public slots:
152158
void setCallgraphParentDepth(int parent);
153159
void setCallgraphChildDepth(int child);
154160
void setCallgraphColors(const QColor& active, const QColor& inactive);
161+
void setSshaskpassPath(const QString& sshaskpath);
155162

156163
private:
157164
Settings() = default;
@@ -172,6 +179,7 @@ public slots:
172179
QString m_appPath;
173180
QString m_arch;
174181
QString m_objdump;
182+
QString m_sshaskpassPath;
175183

176184
int m_callgraphParentDepth = 3;
177185
int m_callgraphChildDepth = 2;

0 commit comments

Comments
 (0)