Skip to content

Commit a52b519

Browse files
committed
add gui to configure ssh
1 parent ed17d32 commit a52b519

11 files changed

+339
-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
@@ -16,51 +16,29 @@
1616
#include <csignal>
1717

1818
#include "hotspot-config.h"
19-
20-
QString sshOutput(const QString& hostname, const QStringList& command)
21-
{
22-
QProcess ssh;
23-
ssh.setProgram(QStandardPaths::findExecutable(QLatin1String("ssh")));
24-
const auto arguments = QStringList({hostname}) + command;
25-
ssh.setArguments(arguments);
26-
ssh.start();
27-
ssh.waitForFinished();
28-
return QString::fromUtf8(ssh.readAll());
29-
}
30-
31-
int sshExitCode(const QString& hostname, const QStringList& command)
32-
{
33-
QProcess ssh;
34-
ssh.setProgram(QStandardPaths::findExecutable(QLatin1String("ssh")));
35-
const auto arguments = QStringList({hostname}) + command;
36-
ssh.setArguments(arguments);
37-
ssh.start();
38-
ssh.waitForFinished();
39-
return ssh.exitCode();
40-
}
19+
#include "ssh.h"
4120

4221
PerfRecordSSH::PerfRecordSSH(QObject* parent)
4322
: PerfRecord(parent)
4423
{
45-
m_hostname = QStringLiteral("user@localhost");
4624
}
4725

4826
PerfRecordSSH::~PerfRecordSSH() = default;
4927

5028
void PerfRecordSSH::record(const QStringList& perfOptions, const QString& outputPath, bool /*elevatePrivileges*/,
5129
const QString& exePath, const QStringList& exeOptions, const QString& workingDirectory)
5230
{
53-
int exitCode = sshExitCode(m_hostname, {QLatin1String("test"), QLatin1String("-e"), exePath});
31+
int exitCode = sshExitCode(m_deviceName, {QLatin1String("test"), QLatin1String("-e"), exePath});
5432
if (exitCode) {
5533
emit recordingFailed(tr("File '%1' does not exist.").arg(exePath));
5634
}
5735

58-
exitCode = sshExitCode(m_hostname, {QLatin1String("test"), QLatin1String("-f"), exePath});
36+
exitCode = sshExitCode(m_deviceName, {QLatin1String("test"), QLatin1String("-f"), exePath});
5937
if (exitCode) {
6038
emit recordingFailed(tr("'%1' is not a file.").arg(exePath));
6139
}
6240

63-
exitCode = sshExitCode(m_hostname, {QLatin1String("test"), QLatin1String("-x"), exePath});
41+
exitCode = sshExitCode(m_deviceName, {QLatin1String("test"), QLatin1String("-x"), exePath});
6442
if (exitCode) {
6543
emit recordingFailed(tr("File '%1' is not executable.").arg(exePath));
6644
}
@@ -110,32 +88,32 @@ void PerfRecordSSH::sendInput(const QByteArray& input)
11088

11189
QString PerfRecordSSH::currentUsername()
11290
{
113-
if (m_hostname.isEmpty())
91+
if (m_deviceName.isEmpty())
11492
return {};
115-
return sshOutput(m_hostname, {QLatin1String("echo"), QLatin1String("$USERNAME")}).simplified();
93+
return sshOutput(m_deviceName, {QLatin1String("echo"), QLatin1String("$USERNAME")}).simplified();
11694
}
11795

11896
bool PerfRecordSSH::canTrace(const QString& path)
11997
{
120-
if (m_hostname.isEmpty())
98+
if (m_deviceName.isEmpty())
12199
return false;
122100

123101
// exit code == 0 -> true
124-
bool isDir = sshExitCode(m_hostname, {QLatin1String("test"), QLatin1String("-d"), path}) == 0;
125-
bool isReadable = sshExitCode(m_hostname, {QLatin1String("test"), QLatin1String("-r"), path}) == 0;
102+
bool isDir = sshExitCode(m_deviceName, {QLatin1String("test"), QLatin1String("-d"), path}) == 0;
103+
bool isReadable = sshExitCode(m_deviceName, {QLatin1String("test"), QLatin1String("-r"), path}) == 0;
126104

127105
if (!isDir || !isReadable) {
128106
return false;
129107
}
130108

131109
QString paranoid =
132-
sshOutput(m_hostname, {QLatin1String("cat"), QLatin1String("/proc/sys/kernel/perf_event_paranoid")});
110+
sshOutput(m_deviceName, {QLatin1String("cat"), QLatin1String("/proc/sys/kernel/perf_event_paranoid")});
133111
return paranoid.trimmed() == QLatin1String("-1");
134112
}
135113

136114
bool PerfRecordSSH::canProfileOffCpu()
137115
{
138-
if (m_hostname.isEmpty())
116+
if (m_deviceName.isEmpty())
139117
return false;
140118
return canTrace(QStringLiteral("events/sched/sched_switch"));
141119
}
@@ -166,16 +144,16 @@ static QString perfBuildOptions(const QString& hostname)
166144

167145
bool PerfRecordSSH::canSampleCpu()
168146
{
169-
if (m_hostname.isEmpty())
147+
if (m_deviceName.isEmpty())
170148
return false;
171-
return perfRecordHelp(m_hostname).contains(QLatin1String("--sample-cpu"));
149+
return perfRecordHelp(m_deviceName).contains(QLatin1String("--sample-cpu"));
172150
}
173151

174152
bool PerfRecordSSH::canSwitchEvents()
175153
{
176-
if (m_hostname.isEmpty())
154+
if (m_deviceName.isEmpty())
177155
return false;
178-
return perfRecordHelp(m_hostname).contains(QLatin1String("--switch-events"));
156+
return perfRecordHelp(m_deviceName).contains(QLatin1String("--switch-events"));
179157
}
180158

181159
bool PerfRecordSSH::canUseAio()
@@ -186,16 +164,16 @@ bool PerfRecordSSH::canUseAio()
186164

187165
bool PerfRecordSSH::canCompress()
188166
{
189-
if (m_hostname.isEmpty())
167+
if (m_deviceName.isEmpty())
190168
return false;
191-
return Zstd_FOUND && perfBuildOptions(m_hostname).contains(QLatin1String("zstd: [ on ]"));
169+
return Zstd_FOUND && perfBuildOptions(m_deviceName).contains(QLatin1String("zstd: [ on ]"));
192170
}
193171

194172
bool PerfRecordSSH::isPerfInstalled()
195173
{
196-
if (m_hostname.isEmpty())
174+
if (m_deviceName.isEmpty())
197175
return false;
198-
return sshExitCode(m_hostname, {QLatin1String("perf")}) != 127;
176+
return sshExitCode(m_deviceName, {QLatin1String("perf")}) != 127;
199177
}
200178

201179
void PerfRecordSSH::startRecording(const QStringList& perfOptions, const QString& outputPath,
@@ -230,12 +208,13 @@ void PerfRecordSSH::startRecording(const QStringList& perfOptions, const QString
230208

231209
m_recordProcess = new QProcess(this);
232210
m_recordProcess->setProgram(QStandardPaths::findExecutable(QLatin1String("ssh")));
233-
m_recordProcess->setArguments({m_hostname, QLatin1String("perf ") + perfCommand.join(QLatin1Char(' '))});
211+
const auto arguments =
212+
assembleSSHArguments(m_deviceName, {QLatin1String("perf ") + perfCommand.join(QLatin1Char(' '))});
213+
m_recordProcess->setArguments(arguments);
214+
m_recordProcess->setProcessEnvironment(sshEnvironment());
234215
m_recordProcess->start();
235216
m_recordProcess->waitForStarted();
236217

237-
qDebug() << m_recordProcess->arguments().join(QLatin1Char(' '));
238-
239218
emit recordingStarted(QLatin1String("perf"), perfCommand);
240219

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

src/perfrecordssh.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ class PerfRecordSSH : public PerfRecord
1818
PerfRecordSSH(QObject* parent = nullptr);
1919
~PerfRecordSSH();
2020

21+
void setDeviceName(const QString& device)
22+
{
23+
m_deviceName = device;
24+
}
25+
2126
void record(const QStringList& perfOptions, const QString& outputPath, bool elevatePrivileges,
2227
const QString& exePath, const QStringList& exeOptions, const QString& workingDirectory) override;
2328
void record(const QStringList& perfOptions, const QString& outputPath, bool elevatePrivileges,
@@ -50,6 +55,6 @@ class PerfRecordSSH : public PerfRecord
5055

5156
QProcess* m_recordProcess = nullptr;
5257
QFile* m_outputFile;
53-
QString m_hostname;
58+
QString m_deviceName;
5459
bool m_userTerminated = false;
5560
};

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)