added callbacks for output from a remote host
This commit is contained in:
parent
c8085a368f
commit
5075fe358e
5 changed files with 90 additions and 66 deletions
|
@ -76,7 +76,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
||||||
{
|
{
|
||||||
QString script = QString("cat %1 | grep AllowedIPs").arg(amnezia::protocols::wireguard::serverConfigPath);
|
QString script = QString("cat %1 | grep AllowedIPs").arg(amnezia::protocols::wireguard::serverConfigPath);
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
auto cbReadStdOut = [&](const QString &data) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -93,8 +93,8 @@ ErrorCode ServerController::connectToHost(const ServerCredentials &credentials,
|
||||||
|
|
||||||
|
|
||||||
ErrorCode ServerController::runScript(const ServerCredentials &credentials, QString script,
|
ErrorCode ServerController::runScript(const ServerCredentials &credentials, QString script,
|
||||||
const std::function<void(const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &cbReadStdOut,
|
const std::function<void(const QString &)> &cbReadStdOut,
|
||||||
const std::function<void(const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &cbReadStdErr) {
|
const std::function<void(const QString &)> &cbReadStdErr) {
|
||||||
|
|
||||||
std::shared_ptr<SshSession> session = m_sshClient.getSession();
|
std::shared_ptr<SshSession> session = m_sshClient.getSession();
|
||||||
if (!session) {
|
if (!session) {
|
||||||
|
@ -137,7 +137,7 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
|
||||||
qDebug().noquote() << "EXEC" << lineToExec;
|
qDebug().noquote() << "EXEC" << lineToExec;
|
||||||
Debug::appendSshLog("Run command:" + lineToExec);
|
Debug::appendSshLog("Run command:" + lineToExec);
|
||||||
|
|
||||||
error = session->writeToChannel(lineToExec);
|
error = session->writeToChannel(lineToExec, cbReadStdOut, cbReadStdErr);
|
||||||
if (error != ErrorCode::NoError) {
|
if (error != ErrorCode::NoError) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -150,8 +150,8 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
|
||||||
|
|
||||||
ErrorCode ServerController::runContainerScript(const ServerCredentials &credentials,
|
ErrorCode ServerController::runContainerScript(const ServerCredentials &credentials,
|
||||||
DockerContainer container, QString script,
|
DockerContainer container, QString script,
|
||||||
const std::function<void (const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &cbReadStdOut,
|
const std::function<void (const QString &)> &cbReadStdOut,
|
||||||
const std::function<void (const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &cbReadStdErr)
|
const std::function<void (const QString &)> &cbReadStdErr)
|
||||||
{
|
{
|
||||||
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
|
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
|
||||||
Debug::appendSshLog("Run container script for " + ContainerProps::containerToString(container) + QStringLiteral(":\n") + script);
|
Debug::appendSshLog("Run container script for " + ContainerProps::containerToString(container) + QStringLiteral(":\n") + script);
|
||||||
|
@ -183,7 +183,7 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
|
||||||
if (e) return e;
|
if (e) return e;
|
||||||
|
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStd = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> ) {
|
auto cbReadStd = [&](const QString &data) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -245,7 +245,7 @@ QByteArray ServerController::getTextFileFromContainer(DockerContainer container,
|
||||||
|
|
||||||
|
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
auto cbReadStdOut = [&](const QString &data) {
|
||||||
stdOut += data;
|
stdOut += data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -596,14 +596,14 @@ bool ServerController::isReinstallContainerRequred(DockerContainer container, co
|
||||||
ErrorCode ServerController::installDockerWorker(const ServerCredentials &credentials, DockerContainer container)
|
ErrorCode ServerController::installDockerWorker(const ServerCredentials &credentials, DockerContainer container)
|
||||||
{
|
{
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
auto cbReadStdOut = [&](const QString &data) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
|
|
||||||
// if (data.contains("Automatically restart Docker daemon?")) {
|
// if (data.contains("Automatically restart Docker daemon?")) {
|
||||||
// proc->write("yes\n");
|
// proc->write("yes\n");
|
||||||
// }
|
// }
|
||||||
};
|
};
|
||||||
auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> ) {
|
auto cbReadStdErr = [&](const QString &data) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -633,7 +633,7 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
|
||||||
if (e) return e;
|
if (e) return e;
|
||||||
|
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
auto cbReadStdOut = [&](const QString &data) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
// auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
// auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||||
|
@ -651,7 +651,7 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
|
||||||
ErrorCode ServerController::runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
|
ErrorCode ServerController::runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
|
||||||
{
|
{
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
auto cbReadStdOut = [&](const QString &data) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
// auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
// auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||||
|
@ -677,10 +677,10 @@ ErrorCode ServerController::runContainerWorker(const ServerCredentials &credenti
|
||||||
ErrorCode ServerController::configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
|
ErrorCode ServerController::configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
|
||||||
{
|
{
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
auto cbReadStdOut = [&](const QString &data) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
auto cbReadStdErr = [&](const QString &data) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -813,10 +813,10 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
|
||||||
QString ServerController::checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode)
|
QString ServerController::checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
auto cbReadStdOut = [&](const QString &data) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> ) {
|
auto cbReadStdErr = [&](const QString &data) {
|
||||||
stdOut += data + "\n";
|
stdOut += data + "\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -67,12 +67,12 @@ public:
|
||||||
QString replaceVars(const QString &script, const Vars &vars);
|
QString replaceVars(const QString &script, const Vars &vars);
|
||||||
|
|
||||||
ErrorCode runScript(const ServerCredentials &credentials, QString script,
|
ErrorCode runScript(const ServerCredentials &credentials, QString script,
|
||||||
const std::function<void(const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &cbReadStdOut = nullptr,
|
const std::function<void(const QString &)> &cbReadStdOut = nullptr,
|
||||||
const std::function<void(const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &cbReadStdErr = nullptr);
|
const std::function<void(const QString &)> &cbReadStdErr = nullptr);
|
||||||
|
|
||||||
ErrorCode runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script,
|
ErrorCode runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script,
|
||||||
const std::function<void(const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &cbReadStdOut = nullptr,
|
const std::function<void(const QString &)> &cbReadStdOut = nullptr,
|
||||||
const std::function<void(const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &cbReadStdErr = nullptr);
|
const std::function<void(const QString &)> &cbReadStdErr = nullptr);
|
||||||
|
|
||||||
Vars genVarsForScript(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None, const QJsonObject &config = QJsonObject());
|
Vars genVarsForScript(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None, const QJsonObject &config = QJsonObject());
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,7 @@ ErrorCode SshSession::initChannel(const ServerCredentials &credentials)
|
||||||
|
|
||||||
if (result == SSH_OK && ssh_channel_is_open(m_channel)) {
|
if (result == SSH_OK && ssh_channel_is_open(m_channel)) {
|
||||||
qDebug() << "SSH chanel opened";
|
qDebug() << "SSH chanel opened";
|
||||||
|
m_isChannelOpened = true;
|
||||||
} else {
|
} else {
|
||||||
qDebug() << ssh_get_error(m_session);
|
qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshAuthenticationError;
|
return ErrorCode::SshAuthenticationError;
|
||||||
|
@ -103,22 +104,80 @@ ErrorCode SshSession::initChannel(const ServerCredentials &credentials)
|
||||||
return ErrorCode::SshInternalError;
|
return ErrorCode::SshInternalError;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ssh_channel_request_shell(m_channel);
|
// result = ssh_channel_request_shell(m_channel);
|
||||||
if (result != SSH_OK) {
|
// if (result != SSH_OK) {
|
||||||
qDebug() << ssh_get_error(m_session);
|
// qDebug() << ssh_get_error(m_session);
|
||||||
return ErrorCode::SshInternalError;
|
// return ErrorCode::SshInternalError;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return ErrorCode::NoError;
|
return ErrorCode::NoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode SshSession::writeToChannel(const QString &data)
|
ErrorCode SshSession::writeToChannel(const QString &data,
|
||||||
|
const std::function<void(const QString &)> &cbReadStdOut,
|
||||||
|
const std::function<void(const QString &)> &cbReadStdErr)
|
||||||
{
|
{
|
||||||
QFutureWatcher<ErrorCode> watcher;
|
QFutureWatcher<ErrorCode> watcher;
|
||||||
connect(&watcher, &QFutureWatcher<ErrorCode>::finished, this, &SshSession::writeToChannelFinished);
|
connect(&watcher, &QFutureWatcher<ErrorCode>::finished, this, &SshSession::writeToChannelFinished);
|
||||||
|
|
||||||
QFuture<ErrorCode> future = QtConcurrent::run([this, &data]() {
|
QFuture<ErrorCode> future = QtConcurrent::run([this, &data, &cbReadStdOut, &cbReadStdErr]() {
|
||||||
return write(data);
|
const int channelReadTimeoutMs = 10;
|
||||||
|
const size_t bufferSize = 2048;
|
||||||
|
|
||||||
|
int bytesRead = 0;
|
||||||
|
int attempts = 0;
|
||||||
|
char buffer[bufferSize];
|
||||||
|
|
||||||
|
std::string output1;
|
||||||
|
if (ssh_channel_is_open(m_channel) && !ssh_channel_is_eof(m_channel)) {
|
||||||
|
bytesRead = ssh_channel_read_timeout(m_channel, buffer, sizeof(buffer), 0, channelReadTimeoutMs);
|
||||||
|
while (bytesRead > 0)
|
||||||
|
{
|
||||||
|
output1.append(buffer, bytesRead);
|
||||||
|
bytesRead = ssh_channel_read_timeout(m_channel, buffer, sizeof(buffer), 0, channelReadTimeoutMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qDebug().noquote() << "stdOut: " << QString(output1.c_str());
|
||||||
|
|
||||||
|
int bytesWritten = ssh_channel_write(m_channel, data.toUtf8(), (uint32_t)data.size());
|
||||||
|
if (bytesWritten == data.size()) {
|
||||||
|
std::string stdOut;
|
||||||
|
std::string stdErr;
|
||||||
|
|
||||||
|
auto readOutput = [&](bool isStdErr) {
|
||||||
|
std::string output;
|
||||||
|
if (ssh_channel_is_open(m_channel) && !ssh_channel_is_eof(m_channel)) {
|
||||||
|
bytesRead = ssh_channel_read_timeout(m_channel, buffer, sizeof(buffer), isStdErr, channelReadTimeoutMs);
|
||||||
|
while (bytesRead > 0)
|
||||||
|
{
|
||||||
|
output.append(buffer, bytesRead);
|
||||||
|
bytesRead = ssh_channel_read_timeout(m_channel, buffer, sizeof(buffer), isStdErr, channelReadTimeoutMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
|
stdOut = readOutput(false);
|
||||||
|
stdErr = readOutput(true);
|
||||||
|
|
||||||
|
if (cbReadStdOut){
|
||||||
|
cbReadStdOut(stdOut.c_str());
|
||||||
|
}
|
||||||
|
if (cbReadStdErr){
|
||||||
|
cbReadStdErr(stdErr.c_str());
|
||||||
|
}
|
||||||
|
if (!stdOut.empty()) {
|
||||||
|
qDebug().noquote() << "stdOut: " << QString(stdOut.c_str());
|
||||||
|
}
|
||||||
|
if (!stdErr.empty()) {
|
||||||
|
qDebug().noquote() << "stdErr: " << QString(stdOut.c_str());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qDebug() << ssh_get_error(m_session);
|
||||||
|
return ErrorCode::SshInternalError;
|
||||||
|
}
|
||||||
|
m_isNeedSendChannelEof = true;
|
||||||
|
return ErrorCode::NoError;
|
||||||
});
|
});
|
||||||
watcher.setFuture(future);
|
watcher.setFuture(future);
|
||||||
|
|
||||||
|
@ -129,39 +188,3 @@ ErrorCode SshSession::writeToChannel(const QString &data)
|
||||||
|
|
||||||
return watcher.result();
|
return watcher.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode SshSession::write(const QString &data)
|
|
||||||
{
|
|
||||||
const int channelReadTimeoutMs = 10;
|
|
||||||
const size_t bufferSize = 2048;
|
|
||||||
|
|
||||||
int bytesToRead = 0;
|
|
||||||
int attempts = 0;
|
|
||||||
char buffer[bufferSize];
|
|
||||||
|
|
||||||
int bytesWritten = ssh_channel_write(m_channel, data.toUtf8(), (uint32_t)data.size());
|
|
||||||
if (bytesWritten == data.size()) {
|
|
||||||
while (bytesToRead != 0 || attempts < 100){
|
|
||||||
if (ssh_channel_is_open(m_channel) && !ssh_channel_is_eof(m_channel)) {
|
|
||||||
bytesToRead = ssh_channel_read_timeout(m_channel, buffer, sizeof(buffer), 0, channelReadTimeoutMs);
|
|
||||||
if (bytesToRead > 0) {
|
|
||||||
attempts = 0;
|
|
||||||
std::string strbuf(buffer, bytesToRead);
|
|
||||||
// QByteArray qbuff(buffer, bytesToRead);
|
|
||||||
// QString outp(buffer);
|
|
||||||
|
|
||||||
// if (cbReadStdOut){
|
|
||||||
// cbReadStdOut(outp, nullptr);
|
|
||||||
// }
|
|
||||||
qDebug().noquote() << QString(strbuf.c_str());
|
|
||||||
} else {
|
|
||||||
attempts++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
qDebug() << ssh_get_error(m_session);
|
|
||||||
return ErrorCode::SshInternalError;
|
|
||||||
}
|
|
||||||
return ErrorCode::NoError;
|
|
||||||
}
|
|
||||||
|
|
|
@ -18,10 +18,11 @@ public:
|
||||||
~SshSession();
|
~SshSession();
|
||||||
|
|
||||||
ErrorCode initChannel(const ServerCredentials &credentials);
|
ErrorCode initChannel(const ServerCredentials &credentials);
|
||||||
ErrorCode writeToChannel(const QString &data);
|
ErrorCode writeToChannel(const QString &data,
|
||||||
|
const std::function<void(const QString &)> &cbReadStdOut,
|
||||||
|
const std::function<void(const QString &)> &cbReadStdErr);
|
||||||
private:
|
private:
|
||||||
ErrorCode connectToHost(const ServerCredentials &credentials);
|
ErrorCode connectToHost(const ServerCredentials &credentials);
|
||||||
ErrorCode write(const QString &data);
|
|
||||||
|
|
||||||
ssh_session m_session;
|
ssh_session m_session;
|
||||||
ssh_channel m_channel;
|
ssh_channel m_channel;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue