Commit e139238d authored by ck's avatar ck
Browse files

Maemo: Implement remote mount functionality.

Untested & unused.
parent 3f36dbd8
......@@ -108,6 +108,7 @@ signals:
/*
* This signal is only emitted by the "List Directory" operation,
* one file at a time.
// TODO: Also emit for each file copied by uploadDir().
*/
void dataAvailable(SftpJobId job, const QString &data);
......
......@@ -190,6 +190,12 @@ MaemoDeployStep *MaemoRunConfiguration::deployStep() const
return step;
}
QString MaemoRunConfiguration::localHostAddressFromDevice() const
{
// TODO: From user
return QLatin1String("192.168.2.14");
}
QString MaemoRunConfiguration::maddeRoot() const
{
if (const MaemoToolChain *tc = toolchain())
......
......@@ -75,7 +75,10 @@ public:
Qt4BuildConfiguration *activeQt4BuildConfiguration() const;
MaemoDeployStep *deployStep() const;
MaemoRemoteMountsModel *remoteMounts() const { return m_remoteMounts; }
QString localHostAddressFromDevice() const;
const MaemoToolChain *toolchain() const;
QString maddeRoot() const;
QString localExecutableFilePath() const;
QString remoteExecutableFilePath() const;
......@@ -106,7 +109,6 @@ private slots:
private:
void init();
const MaemoToolChain *toolchain() const;
QString m_proFilePath;
mutable QString m_gdbPath;
......
......@@ -35,12 +35,17 @@
#include "maemosshrunner.h"
#include "maemodeviceconfigurations.h"
#include "maemoglobal.h"
#include "maemoremotemountsmodel.h"
#include "maemorunconfiguration.h"
#include "maemotoolchain.h"
#include <coreplugin/ssh/sftpchannel.h>
#include <coreplugin/ssh/sshconnection.h>
#include <coreplugin/ssh/sshremoteprocess.h>
#include <QtCore/QFileInfo>
#include <QtCore/QProcess>
using namespace Core;
......@@ -50,9 +55,12 @@ namespace Internal {
MaemoSshRunner::MaemoSshRunner(QObject *parent,
MaemoRunConfiguration *runConfig)
: QObject(parent), m_runConfig(runConfig),
m_devConfig(runConfig->deviceConfig())
m_devConfig(runConfig->deviceConfig()),
m_uploadJobId(SftpInvalidJob)
{
m_procsToKill << QFileInfo(m_runConfig->localExecutableFilePath()).fileName();
m_procsToKill
<< QFileInfo(m_runConfig->localExecutableFilePath()).fileName()
<< QLatin1String("utfs-client");
}
MaemoSshRunner::~MaemoSshRunner() {}
......@@ -93,10 +101,18 @@ void MaemoSshRunner::stop()
disconnect(m_connection.data(), 0, this, 0);
if (m_initialCleaner)
disconnect(m_initialCleaner.data(), 0, this, 0);
if (m_utfsClientUploader) {
disconnect(m_utfsClientUploader.data(), 0, this, 0);
m_utfsClientUploader->closeChannel();
}
if (m_mountProcess) {
disconnect(m_mountProcess.data(), 0, this, 0);
m_mountProcess->closeChannel();
}
if (m_runner) {
disconnect(m_runner.data(), 0, this, 0);
m_runner->closeChannel();
killRemoteProcs(false);
cleanup(false);
}
}
......@@ -105,7 +121,7 @@ void MaemoSshRunner::handleConnected()
if (m_stop)
return;
killRemoteProcs(true);
cleanup(true);
}
void MaemoSshRunner::handleConnectionFailure()
......@@ -114,7 +130,7 @@ void MaemoSshRunner::handleConnectionFailure()
.arg(m_connection->errorString()));
}
void MaemoSshRunner::killRemoteProcs(bool initialCleanup)
void MaemoSshRunner::cleanup(bool initialCleanup)
{
QString niceKill;
QString brutalKill;
......@@ -123,6 +139,15 @@ void MaemoSshRunner::killRemoteProcs(bool initialCleanup)
brutalKill += QString::fromLocal8Bit("pkill -x -9 %1;").arg(proc);
}
QString remoteCall = niceKill + QLatin1String("sleep 1; ") + brutalKill;
const MaemoRemoteMountsModel * const remoteMounts
= m_runConfig->remoteMounts();
for (int i = 0; i < remoteMounts->mountSpecificationCount(); ++i) {
remoteCall += QString::fromLocal8Bit("%1 umount %2;")
.arg(MaemoGlobal::remoteSudo(),
remoteMounts->mountSpecificationAt(i).remoteMountPoint);
}
remoteCall.remove(remoteCall.count() - 1, 1); // Get rid of trailing semicolon.
SshRemoteProcess::Ptr proc
= m_connection->createRemoteProcess(remoteCall.toUtf8());
......@@ -143,14 +168,142 @@ void MaemoSshRunner::handleInitialCleanupFinished(int exitStatus)
if (m_stop)
return;
foreach (QProcess *utfsServer, m_utfsServers) {
utfsServer->terminate();
utfsServer->waitForFinished(1000);
utfsServer->kill();
}
qDeleteAll(m_utfsServers);
if (exitStatus != SshRemoteProcess::ExitedNormally) {
emit error(tr("Initial cleanup failed: %1")
.arg(m_initialCleaner->errorString()));
} else if (m_runConfig->remoteMounts()->mountSpecificationCount() != 0) {
deployUtfsClient();
} else {
emit readyForExecution();
}
}
void MaemoSshRunner::deployUtfsClient()
{
m_utfsClientUploader = m_connection->createSftpChannel();
connect(m_utfsClientUploader.data(), SIGNAL(initialized()), this,
SLOT(handleUploaderInitialized()));
connect(m_utfsClientUploader.data(), SIGNAL(initializationFailed(QString)),
this, SLOT(handleUploaderInitializationFailed(QString)));
m_utfsClientUploader->initialize();
}
void MaemoSshRunner::handleUploaderInitializationFailed(const QString &reason)
{
if (m_stop)
return;
emit error(tr("Failed to establish SFTP connection: %1").arg(reason));
}
void MaemoSshRunner::handleUploaderInitialized()
{
if (m_stop)
return;
connect(m_utfsClientUploader.data(),
SIGNAL(finished(Core::SftpJobId, QString)), this,
SLOT(handleUploadFinished(Core::SftpJobId,QString)));
const MaemoToolChain * const toolChain
= dynamic_cast<const MaemoToolChain *>(m_runConfig->toolchain());
Q_ASSERT_X(toolChain, Q_FUNC_INFO,
"Impossible: Maemo run configuration has no Maemo Toolchain.");
const QString localFile
= toolChain->maddeRoot() + QLatin1String("/madlib/utfs-client");
m_uploadJobId
= m_utfsClientUploader->uploadFile(localFile, utfsClientOnDevice(),
SftpOverwriteExisting);
if (m_uploadJobId == SftpInvalidJob)
emit error(tr("Could not upload UTFS client (%1).").arg(localFile));
}
void MaemoSshRunner::handleUploadFinished(Core::SftpJobId jobId,
const QString &errorMsg)
{
if (m_stop)
return;
if (jobId != m_uploadJobId) {
qWarning("Warning: unknown upload job %d finished.", jobId);
return;
}
m_uploadJobId = SftpInvalidJob;
if (!errorMsg.isEmpty()) {
emit error(tr("Could not upload UTFS client: %1").arg(errorMsg));
return;
}
mount();
}
void MaemoSshRunner::mount()
{
const MaemoRemoteMountsModel * const remoteMounts
= m_runConfig->remoteMounts();
QString remoteCall(QLatin1String(":"));
for (int i = 0; i < remoteMounts->mountSpecificationCount(); ++i) {
const MaemoRemoteMountsModel::MountSpecification &mountSpec
= remoteMounts->mountSpecificationAt(i);
QProcess * const utfsServerProc = new QProcess(this);
const QString port = QString::number(mountSpec.port);
const QString localSecretOpt = QLatin1String("-l");
const QString remoteSecretOpt = QLatin1String("-r");
const QStringList utfsServerArgs = QStringList() << localSecretOpt
<< port << remoteSecretOpt << port << QLatin1String("-b") << port;
utfsServerProc->start(utfsServer(), utfsServerArgs);
if (!utfsServerProc->waitForStarted()) {
emit error(tr("Could not start UTFS server: %1")
.arg(utfsServerProc->errorString()));
return;
}
m_utfsServers << utfsServerProc;
const QString mkdir = QString::fromLocal8Bit("%1 mkdir -p %2")
.arg(MaemoGlobal::remoteSudo(), mountSpec.remoteMountPoint);
const QString utfsClient
= QString::fromLocal8Bit("%1 -l %2 -r %2 -c %3:%2 %4")
.arg(utfsClientOnDevice()).arg(port)
.arg(m_runConfig->localHostAddressFromDevice())
.arg(mountSpec.remoteMountPoint);
const QLatin1String andOp(" && ");
remoteCall += andOp + mkdir + andOp + utfsClient;
}
m_mountProcess = m_connection->createRemoteProcess(remoteCall.toUtf8());
connect(m_mountProcess.data(), SIGNAL(started()), this,
SLOT(handleMountProcessStarted()));
connect(m_mountProcess.data(), SIGNAL(closed(int)), this,
SLOT(handleRemoteProcessFinished(int)));
m_mountProcess->start();
}
void MaemoSshRunner::handleMountProcessStarted()
{
// TODO: Do we get "finished" from utfs-client when it goes into background?
// If so, remnove this slot; readyForExecution() should be emitted from
// handleRemoteProcessFinished() in that case.
if (!m_stop)
emit readyForExecution();
}
void MaemoSshRunner::handleMountProcessFinished(int exitStatus)
{
if (m_stop)
return;
if (exitStatus != SshRemoteProcess::ExitedNormally) {
emit error(tr("Failure running UTFS client: %1")
.arg(m_mountProcess->errorString()));
}
}
void MaemoSshRunner::startExecution(const QByteArray &remoteCall)
{
if (m_runConfig->remoteExecutableFilePath().isEmpty()) {
......@@ -187,6 +340,20 @@ void MaemoSshRunner::handleRemoteProcessFinished(int exitStatus)
}
}
QString MaemoSshRunner::utfsClientOnDevice() const
{
return MaemoGlobal::homeDirOnDevice(QLatin1String("developer"))
+ QLatin1String("/utfs-client");
}
QString MaemoSshRunner::utfsServer() const
{
const MaemoToolChain * const toolChain
= dynamic_cast<const MaemoToolChain *>(m_runConfig->toolchain());
Q_ASSERT_X(toolChain, Q_FUNC_INFO,
"Impossible: Maemo run configuration has no Maemo Toolchain.");
return toolChain->maddeRoot() + QLatin1String("/madlib/utfs-server");
}
} // namespace Internal
} // namespace Qt4ProjectManager
......
......@@ -44,6 +44,8 @@
#include <QtCore/QStringList>
QT_FORWARD_DECLARE_CLASS(QProcess)
namespace Core {
class SftpChannel;
class SshConnection;
......@@ -84,9 +86,18 @@ private slots:
void handleConnectionFailure();
void handleInitialCleanupFinished(int exitStatus);
void handleRemoteProcessFinished(int exitStatus);
void handleUploaderInitialized();
void handleUploaderInitializationFailed(const QString &reason);
void handleUploadFinished(Core::SftpJobId jobId, const QString &error);
void handleMountProcessStarted();
void handleMountProcessFinished(int exitStatus);
private:
void killRemoteProcs(bool initialCleanup);
void cleanup(bool initialCleanup);
void deployUtfsClient();
void mount();
QString utfsClientOnDevice() const;
QString utfsServer() const;
MaemoRunConfiguration * const m_runConfig; // TODO this pointer can be invalid
const MaemoDeviceConfig m_devConfig;
......@@ -94,7 +105,12 @@ private:
QSharedPointer<Core::SshConnection> m_connection;
QSharedPointer<Core::SshRemoteProcess> m_runner;
QSharedPointer<Core::SshRemoteProcess> m_initialCleaner;
QSharedPointer<Core::SshRemoteProcess> m_mountProcess;
QSharedPointer<Core::SftpChannel> m_utfsClientUploader;
QStringList m_procsToKill;
QList<QProcess *> m_utfsServers;
Core::SftpJobId m_uploadJobId;
bool m_stop;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment