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/environment.h>
#include <utils/hostosinfo.h>
#include <utils/utilsicons.h>
#include <utils/layoutbuilder.h>
#include <utils/overridecursor.h>
#include <utils/port.h>
@@ -69,6 +70,7 @@
#include <QLoggingCategory>
#include <QPushButton>
#include <QTextBrowser>
#include <QToolButton>
#include <QThread>
#ifdef Q_OS_UNIX
@@ -312,6 +314,14 @@ public:
QFileSystemWatcher m_mergedDirWatcher;
Environment m_cachedEnviroment;
enum LocalAccessState
{
NotEvaluated,
NoDaemon,
Accessible,
NotAccessible
} m_accessible = NotEvaluated;
};
class DockerDeviceWidget final : public IDeviceWidget
@@ -337,6 +347,17 @@ public:
m_repoLineEdit->setText(data.repo);
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->setToolTip(tr("Use user ID and group ID of the user running Qt Creator "
"in the Docker container."));
@@ -369,6 +390,16 @@ public:
logView->clear();
dockerDevice->tryCreateLocalFileAccess();
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()] {
@@ -381,6 +412,7 @@ public:
Form {
idLabel, m_idLineEdit, Break(),
repoLabel, m_repoLineEdit, Break(),
daemonStateLabel, m_daemonReset, Break(),
m_runAsOutsideUser, Break(),
tr("Paths to mount:"), m_pathsLineEdit, Break(),
Column {
@@ -397,6 +429,7 @@ public:
private:
QLineEdit *m_idLineEdit;
QLineEdit *m_repoLineEdit;
QToolButton *m_daemonReset;
QCheckBox *m_runAsOutsideUser;
QLineEdit *m_pathsLineEdit;
@@ -648,7 +681,7 @@ void DockerDevice::tryCreateLocalFileAccess() const
void DockerDevicePrivate::stopCurrentContainer()
{
if (m_container.isEmpty())
if (m_container.isEmpty() || m_accessible == NoDaemon)
return;
QtcProcess proc;
@@ -662,7 +695,7 @@ void DockerDevicePrivate::stopCurrentContainer()
void DockerDevicePrivate::tryCreateLocalFileAccess()
{
if (!m_container.isEmpty())
if (!m_container.isEmpty() || m_accessible == NoDaemon)
return;
QString tempFileName;
@@ -701,6 +734,14 @@ void DockerDevicePrivate::tryCreateLocalFileAccess()
LOG("RES: " << m_shell->result()
<< " STDOUT: " << m_shell->readAllStandardOutput()
<< " 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();
});
@@ -723,10 +764,11 @@ void DockerDevicePrivate::tryCreateLocalFileAccess()
break;
}
}
if (i == 20) {
if (i == 20 || m_accessible == NoDaemon) {
qWarning("Docker cid file empty.");
return; // No
}
qApp->processEvents(); // FIXME turn this for-loop into QEventLoop
QThread::msleep(100);
}
@@ -753,11 +795,13 @@ void DockerDevicePrivate::tryCreateLocalFileAccess()
// of using wsl or a named pipe.
// TODO investigate how to make it possible nevertheless.
m_mergedDir.clear();
m_accessible = NotAccessible;
MessageManager::writeSilently(tr("This is expected on Windows."));
return;
}
}
m_accessible = Accessible;
m_mergedDirWatcher.addPath(m_mergedDir);
}
@@ -766,6 +810,24 @@ bool DockerDevice::hasLocalFileAccess() const
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
{
d->m_data.mounts = mounts;
@@ -1183,7 +1245,7 @@ bool DockerDevice::writeFileContents(const Utils::FilePath &filePath, const QByt
void DockerDevice::runProcess(QtcProcess &process) const
{
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());
QTC_CHECK(false);
process.setResult(QtcProcess::StartFailed);
@@ -1237,6 +1299,8 @@ void DockerDevicePrivate::fetchSystemEnviroment()
int DockerDevicePrivate::runSynchronously(const CommandLine &cmd) const
{
if (m_accessible == NoDaemon)
return -1;
CommandLine dcmd{"docker", {"exec", m_container}};
dcmd.addArgs(cmd);

View File

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