Docker: Handle docker daemon

Avoid calling the docker daemon again and again
if it is currently not running.

Change-Id: I17afa2eca098589bd362149d18e090252ef83f6e
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Stenger
2021-07-15 13:56:06 +02:00
parent f787afe732
commit 88310df13d
2 changed files with 70 additions and 4 deletions

View File

@@ -49,6 +49,7 @@
#include <utils/basetreeview.h> #include <utils/basetreeview.h>
#include <utils/environment.h> #include <utils/environment.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/utilsicons.h>
#include <utils/layoutbuilder.h> #include <utils/layoutbuilder.h>
#include <utils/overridecursor.h> #include <utils/overridecursor.h>
#include <utils/port.h> #include <utils/port.h>
@@ -69,6 +70,7 @@
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QPushButton> #include <QPushButton>
#include <QTextBrowser> #include <QTextBrowser>
#include <QToolButton>
#include <QThread> #include <QThread>
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
@@ -312,6 +314,14 @@ public:
QFileSystemWatcher m_mergedDirWatcher; QFileSystemWatcher m_mergedDirWatcher;
Environment m_cachedEnviroment; Environment m_cachedEnviroment;
enum LocalAccessState
{
NotEvaluated,
NoDaemon,
Accessible,
NotAccessible
} m_accessible = NotEvaluated;
}; };
class DockerDeviceWidget final : public IDeviceWidget class DockerDeviceWidget final : public IDeviceWidget
@@ -337,6 +347,17 @@ public:
m_repoLineEdit->setText(data.repo); m_repoLineEdit->setText(data.repo);
m_repoLineEdit->setEnabled(false); m_repoLineEdit->setEnabled(false);
auto daemonStateLabel = new QLabel(tr("Daemon state:"));
m_daemonReset = new QToolButton;
m_daemonReset->setIcon(Icons::INFO.icon());
m_daemonReset->setToolTip(tr("Daemon state not evaluated."));
connect(m_daemonReset, &QToolButton::clicked, this, [this, dockerDevice] {
dockerDevice->resetDaemonState();
m_daemonReset->setIcon(Icons::INFO.icon());
m_daemonReset->setToolTip(tr("Daemon state not evaluated."));
});
m_runAsOutsideUser = new QCheckBox(tr("Run as outside user")); m_runAsOutsideUser = new QCheckBox(tr("Run as outside user"));
m_runAsOutsideUser->setToolTip(tr("Use user ID and group ID of the user running Qt Creator " m_runAsOutsideUser->setToolTip(tr("Use user ID and group ID of the user running Qt Creator "
"in the Docker container.")); "in the Docker container."));
@@ -369,6 +390,16 @@ public:
logView->clear(); logView->clear();
dockerDevice->tryCreateLocalFileAccess(); dockerDevice->tryCreateLocalFileAccess();
m_kitItemDetector.autoDetect(id); m_kitItemDetector.autoDetect(id);
if (!dockerDevice->isDaemonRunning()) {
logView->append(tr("Docker daemon appears to be not running."));
m_daemonReset->setToolTip(tr("Daemon not running. Push to reset the state."));
m_daemonReset->setIcon(Icons::CRITICAL.icon());
} else {
m_daemonReset->setToolTip(tr("Docker daemon running."));
m_daemonReset->setIcon(Icons::OK.icon());
}
}); });
connect(undoAutoDetectButton, &QPushButton::clicked, this, [this, logView, id = data.id()] { connect(undoAutoDetectButton, &QPushButton::clicked, this, [this, logView, id = data.id()] {
@@ -381,6 +412,7 @@ public:
Form { Form {
idLabel, m_idLineEdit, Break(), idLabel, m_idLineEdit, Break(),
repoLabel, m_repoLineEdit, Break(), repoLabel, m_repoLineEdit, Break(),
daemonStateLabel, m_daemonReset, Break(),
m_runAsOutsideUser, Break(), m_runAsOutsideUser, Break(),
tr("Paths to mount:"), m_pathsLineEdit, Break(), tr("Paths to mount:"), m_pathsLineEdit, Break(),
Column { Column {
@@ -397,6 +429,7 @@ public:
private: private:
QLineEdit *m_idLineEdit; QLineEdit *m_idLineEdit;
QLineEdit *m_repoLineEdit; QLineEdit *m_repoLineEdit;
QToolButton *m_daemonReset;
QCheckBox *m_runAsOutsideUser; QCheckBox *m_runAsOutsideUser;
QLineEdit *m_pathsLineEdit; QLineEdit *m_pathsLineEdit;
@@ -648,7 +681,7 @@ void DockerDevice::tryCreateLocalFileAccess() const
void DockerDevicePrivate::stopCurrentContainer() void DockerDevicePrivate::stopCurrentContainer()
{ {
if (m_container.isEmpty()) if (m_container.isEmpty() || m_accessible == NoDaemon)
return; return;
QtcProcess proc; QtcProcess proc;
@@ -662,7 +695,7 @@ void DockerDevicePrivate::stopCurrentContainer()
void DockerDevicePrivate::tryCreateLocalFileAccess() void DockerDevicePrivate::tryCreateLocalFileAccess()
{ {
if (!m_container.isEmpty()) if (!m_container.isEmpty() || m_accessible == NoDaemon)
return; return;
QString tempFileName; QString tempFileName;
@@ -701,6 +734,14 @@ void DockerDevicePrivate::tryCreateLocalFileAccess()
LOG("RES: " << m_shell->result() LOG("RES: " << m_shell->result()
<< " STDOUT: " << m_shell->readAllStandardOutput() << " STDOUT: " << m_shell->readAllStandardOutput()
<< " STDERR: " << m_shell->readAllStandardError()); << " STDERR: " << m_shell->readAllStandardError());
if (m_shell->exitCode() != 0) {
m_accessible = NoDaemon;
LOG("DOCKER DAEMON NOT RUNNING?");
MessageManager::writeFlashing(tr("Docker Daemon appears to be not running. "
"Verify daemon is up and running and reset the "
"docker daemon on the docker device settings page "
"or restart Qt Creator."));
}
} }
m_container.clear(); m_container.clear();
}); });
@@ -723,10 +764,11 @@ void DockerDevicePrivate::tryCreateLocalFileAccess()
break; break;
} }
} }
if (i == 20) { if (i == 20 || m_accessible == NoDaemon) {
qWarning("Docker cid file empty."); qWarning("Docker cid file empty.");
return; // No return; // No
} }
qApp->processEvents(); // FIXME turn this for-loop into QEventLoop
QThread::msleep(100); QThread::msleep(100);
} }
@@ -753,11 +795,13 @@ void DockerDevicePrivate::tryCreateLocalFileAccess()
// of using wsl or a named pipe. // of using wsl or a named pipe.
// TODO investigate how to make it possible nevertheless. // TODO investigate how to make it possible nevertheless.
m_mergedDir.clear(); m_mergedDir.clear();
m_accessible = NotAccessible;
MessageManager::writeSilently(tr("This is expected on Windows.")); MessageManager::writeSilently(tr("This is expected on Windows."));
return; return;
} }
} }
m_accessible = Accessible;
m_mergedDirWatcher.addPath(m_mergedDir); m_mergedDirWatcher.addPath(m_mergedDir);
} }
@@ -766,6 +810,24 @@ bool DockerDevice::hasLocalFileAccess() const
return !d->m_mergedDir.isEmpty(); return !d->m_mergedDir.isEmpty();
} }
bool DockerDevice::isDaemonRunning() const
{
switch (d->m_accessible) {
case DockerDevicePrivate::NoDaemon:
return false;
case DockerDevicePrivate::NotEvaluated: // FIXME?
case DockerDevicePrivate::Accessible:
case DockerDevicePrivate::NotAccessible:
return true;
}
return false;
}
void DockerDevice::resetDaemonState()
{
d->m_accessible = DockerDevicePrivate::NotEvaluated;
}
void DockerDevice::setMounts(const QStringList &mounts) const void DockerDevice::setMounts(const QStringList &mounts) const
{ {
d->m_data.mounts = mounts; d->m_data.mounts = mounts;
@@ -1183,7 +1245,7 @@ bool DockerDevice::writeFileContents(const Utils::FilePath &filePath, const QByt
void DockerDevice::runProcess(QtcProcess &process) const void DockerDevice::runProcess(QtcProcess &process) const
{ {
tryCreateLocalFileAccess(); tryCreateLocalFileAccess();
if (d->m_container.isEmpty()) { if (d->m_container.isEmpty() || d->m_accessible == DockerDevicePrivate::NoDaemon) {
LOG("No container set to run " << process.commandLine().toUserOutput()); LOG("No container set to run " << process.commandLine().toUserOutput());
QTC_CHECK(false); QTC_CHECK(false);
process.setResult(QtcProcess::StartFailed); process.setResult(QtcProcess::StartFailed);
@@ -1237,6 +1299,8 @@ void DockerDevicePrivate::fetchSystemEnviroment()
int DockerDevicePrivate::runSynchronously(const CommandLine &cmd) const int DockerDevicePrivate::runSynchronously(const CommandLine &cmd) const
{ {
if (m_accessible == NoDaemon)
return -1;
CommandLine dcmd{"docker", {"exec", m_container}}; CommandLine dcmd{"docker", {"exec", m_container}};
dcmd.addArgs(cmd); dcmd.addArgs(cmd);

View File

@@ -107,6 +107,8 @@ public:
void tryCreateLocalFileAccess() const; void tryCreateLocalFileAccess() const;
bool hasLocalFileAccess() const; bool hasLocalFileAccess() const;
bool isDaemonRunning() const;
void resetDaemonState();
void setMounts(const QStringList &mounts) const; void setMounts(const QStringList &mounts) const;
Utils::FilePath mapToLocalAccess(const Utils::FilePath &filePath) const; Utils::FilePath mapToLocalAccess(const Utils::FilePath &filePath) const;