Skip to content

Commit e76012b

Browse files
committed
add gui to configure ssh
1 parent 30c7c23 commit e76012b

13 files changed

+465
-58
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
@@ -140,6 +140,8 @@ MainWindow::MainWindow(QWidget* parent)
140140
settings->setObjdump(m_settingsDialog->objdump());
141141
});
142142

143+
connect(m_settingsDialog, &QDialog::accepted, m_recordPage, &RecordPage::onRemoteDevicesChanged);
144+
143145
connect(settings, &Settings::sysrootChanged, m_resultsPage, &ResultsPage::setSysroot);
144146
connect(settings, &Settings::appPathChanged, m_resultsPage, &ResultsPage::setAppPath);
145147
connect(settings, &Settings::objdumpChanged, m_resultsPage, &ResultsPage::setObjdump);
@@ -231,6 +233,9 @@ MainWindow::MainWindow(QWidget* parent)
231233
settings->setDebuginfodUrls(m_config->group("debuginfod").readEntry("urls", QStringList()));
232234
connect(Settings::instance(), &Settings::debuginfodUrlsChanged, this,
233235
[this, settings] { m_config->group("debuginfod").writeEntry("urls", settings->debuginfodUrls()); });
236+
237+
const auto askpass = QStandardPaths::findExecutable(QLatin1String("ksshaskpass"));
238+
settings->setSshaskpassPath(m_config->group("SSH").readEntry("sshaskpass", askpass));
234239
}
235240

236241
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
@@ -426,20 +426,19 @@ RecordPage::RecordPage(QWidget* parent)
426426

427427
perfRecordChanged();
428428

429-
ui->remoteTargetComboBox->addItem(QStringLiteral("localhost"));
430-
ui->remoteTargetComboBox->addItem(QStringLiteral("remote test 1"));
429+
const auto sshPath = QStandardPaths::findExecutable(QLatin1String("ssh"));
430+
ui->remoteTargetGroup->setVisible(!sshPath.isEmpty());
431+
432+
onRemoteDevicesChanged();
431433

432434
connect(ui->remoteTargetComboBox, qOverload<int>(&QComboBox::currentIndexChanged), this,
433435
[this, perfRecordChanged](int index) {
434436
if (index == 0) {
435437
m_perfRecord = new PerfRecord(this);
436-
qDebug() << "PerfRecord";
437438
} else {
438439
auto recordSsh = new PerfRecordSSH(this);
439-
// TODO: this
440-
// recordSsh->setHostname();
440+
recordSsh->setDeviceName(ui->remoteTargetComboBox->currentText());
441441
m_perfRecord = recordSsh;
442-
qDebug() << "PerfRecordSSH";
443442
}
444443
perfRecordChanged();
445444
});
@@ -843,3 +842,17 @@ void RecordPage::updateOffCpuCheckboxState()
843842
ui->offCpuCheckBox->setChecked(config().readEntry(QStringLiteral("offCpuProfiling"), false));
844843
}
845844
}
845+
846+
void RecordPage::onRemoteDevicesChanged()
847+
{
848+
ui->remoteTargetComboBox->clear();
849+
ui->remoteTargetComboBox->addItem(QStringLiteral("localhost"));
850+
851+
const auto deviceConfig = KSharedConfig::openConfig()->group("devices");
852+
auto t = deviceConfig.groupList();
853+
for (const auto& device : deviceConfig.groupList()) {
854+
if (deviceConfig.hasGroup(device)) {
855+
ui->remoteTargetComboBox->addItem(device);
856+
}
857+
}
858+
}

src/recordpage.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ class RecordPage : public QWidget
7373
void homeButtonClicked();
7474
void openFile(QString filePath);
7575

76+
public slots:
77+
void onRemoteDevicesChanged();
78+
7679
private slots:
7780
void onApplicationNameChanged(const QString& filePath);
7881
void onStartRecordingButtonClicked(bool checked);

src/settings.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,9 @@ void Settings::setObjdump(const QString& objdump)
120120
m_objdump = objdump;
121121
emit objdumpChanged(m_objdump);
122122
}
123+
124+
void Settings::setSshaskpassPath(const QString& sshaskpath)
125+
{
126+
m_sshaskpassPath = sshaskpath;
127+
emit sshaskpassChanged(m_sshaskpassPath);
128+
}

src/settings.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ class Settings : public QObject
111111
return m_objdump;
112112
}
113113

114+
QString sshaskpassPath() const
115+
{
116+
return m_sshaskpassPath;
117+
}
118+
114119
signals:
115120
void prettifySymbolsChanged(bool);
116121
void collapseTemplatesChanged(bool);
@@ -125,6 +130,7 @@ class Settings : public QObject
125130
void appPathChanged(const QString& path);
126131
void archChanged(const QString& arch);
127132
void objdumpChanged(const QString& objdump);
133+
void sshaskpassChanged(const QString& path);
128134

129135
public slots:
130136
void setPrettifySymbols(bool prettifySymbols);
@@ -140,6 +146,7 @@ public slots:
140146
void setAppPath(const QString& path);
141147
void setArch(const QString& arch);
142148
void setObjdump(const QString& objdump);
149+
void setSshaskpassPath(const QString& sshaskpath);
143150

144151
private:
145152
Settings() = default;
@@ -160,4 +167,5 @@ public slots:
160167
QString m_appPath;
161168
QString m_arch;
162169
QString m_objdump;
170+
QString m_sshaskpassPath;
163171
};

0 commit comments

Comments
 (0)