forked from qt-creator/qt-creator
Docker: Check Image available
Docker will try to download images from the registry if an image is not available locally. This takes a while, even if the image is not available remotely. To circumvent the hangs resulting from this we first check if the image is available locally and if it is not we do not try to start it. Fixes: QTCREATORBUG-28880 Change-Id: I6b9de8601b87e3050ae9ac5f1bbe3fa9701d4cc1 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -143,7 +143,7 @@ public:
|
|||||||
|
|
||||||
RunResult runInShell(const CommandLine &cmd, const QByteArray &stdInData = {});
|
RunResult runInShell(const CommandLine &cmd, const QByteArray &stdInData = {});
|
||||||
|
|
||||||
void updateContainerAccess();
|
bool updateContainerAccess();
|
||||||
void changeMounts(QStringList newMounts);
|
void changeMounts(QStringList newMounts);
|
||||||
bool ensureReachable(const FilePath &other);
|
bool ensureReachable(const FilePath &other);
|
||||||
void shutdown();
|
void shutdown();
|
||||||
@@ -171,7 +171,7 @@ public:
|
|||||||
Tasks validateMounts() const;
|
Tasks validateMounts() const;
|
||||||
|
|
||||||
bool createContainer();
|
bool createContainer();
|
||||||
void startContainer();
|
bool startContainer();
|
||||||
void stopCurrentContainer();
|
void stopCurrentContainer();
|
||||||
void fetchSystemEnviroment();
|
void fetchSystemEnviroment();
|
||||||
|
|
||||||
@@ -186,6 +186,8 @@ public:
|
|||||||
|
|
||||||
QStringList createMountArgs() const;
|
QStringList createMountArgs() const;
|
||||||
|
|
||||||
|
bool isImageAvailable() const;
|
||||||
|
|
||||||
DockerDevice *const q;
|
DockerDevice *const q;
|
||||||
DockerDeviceData m_data;
|
DockerDeviceData m_data;
|
||||||
DockerSettings *m_settings;
|
DockerSettings *m_settings;
|
||||||
@@ -392,7 +394,9 @@ DockerDevice::DockerDevice(DockerSettings *settings, const DockerDeviceData &dat
|
|||||||
|
|
||||||
setOpenTerminal([this, settings](const Environment &env, const FilePath &workingDir) {
|
setOpenTerminal([this, settings](const Environment &env, const FilePath &workingDir) {
|
||||||
Q_UNUSED(env); // TODO: That's the runnable's environment in general. Use it via -e below.
|
Q_UNUSED(env); // TODO: That's the runnable's environment in general. Use it via -e below.
|
||||||
updateContainerAccess();
|
if (!updateContainerAccess())
|
||||||
|
return;
|
||||||
|
|
||||||
if (d->containerId().isEmpty()) {
|
if (d->containerId().isEmpty()) {
|
||||||
MessageManager::writeDisrupting(Tr::tr("Error starting remote shell. No container."));
|
MessageManager::writeDisrupting(Tr::tr("Error starting remote shell. No container."));
|
||||||
return;
|
return;
|
||||||
@@ -446,9 +450,9 @@ void DockerDevice::setData(const DockerDeviceData &data)
|
|||||||
d->setData(data);
|
d->setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockerDevice::updateContainerAccess() const
|
bool DockerDevice::updateContainerAccess() const
|
||||||
{
|
{
|
||||||
d->updateContainerAccess();
|
return d->updateContainerAccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandLine DockerDevicePrivate::withDockerExecCmd(const CommandLine &cmd,
|
CommandLine DockerDevicePrivate::withDockerExecCmd(const CommandLine &cmd,
|
||||||
@@ -461,7 +465,8 @@ CommandLine DockerDevicePrivate::withDockerExecCmd(const CommandLine &cmd,
|
|||||||
if (!m_settings)
|
if (!m_settings)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
updateContainerAccess();
|
if (!updateContainerAccess())
|
||||||
|
return {};
|
||||||
|
|
||||||
CommandLine dockerCmd{m_settings->dockerBinaryPath.filePath(), {"exec"}};
|
CommandLine dockerCmd{m_settings->dockerBinaryPath.filePath(), {"exec"}};
|
||||||
|
|
||||||
@@ -614,11 +619,30 @@ QStringList DockerDevicePrivate::createMountArgs() const
|
|||||||
return cmds;
|
return cmds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DockerDevicePrivate::isImageAvailable() const
|
||||||
|
{
|
||||||
|
QtcProcess proc;
|
||||||
|
proc.setCommand(
|
||||||
|
{m_settings->dockerBinaryPath.filePath(),
|
||||||
|
{"image", "list", m_data.repoAndTag(), "--format", "{{.Repository}}:{{.Tag}}"}});
|
||||||
|
proc.runBlocking();
|
||||||
|
if (proc.result() != ProcessResult::FinishedWithSuccess)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (proc.stdOut().trimmed() == m_data.repoAndTag())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool DockerDevicePrivate::createContainer()
|
bool DockerDevicePrivate::createContainer()
|
||||||
{
|
{
|
||||||
if (!m_settings)
|
if (!m_settings)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!isImageAvailable())
|
||||||
|
return false;
|
||||||
|
|
||||||
const QString display = HostOsInfo::isLinuxHost() ? QString(":0")
|
const QString display = HostOsInfo::isLinuxHost() ? QString(":0")
|
||||||
: QString("host.docker.internal:0");
|
: QString("host.docker.internal:0");
|
||||||
CommandLine dockerCreate{m_settings->dockerBinaryPath.filePath(),
|
CommandLine dockerCreate{m_settings->dockerBinaryPath.filePath(),
|
||||||
@@ -671,10 +695,10 @@ bool DockerDevicePrivate::createContainer()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockerDevicePrivate::startContainer()
|
bool DockerDevicePrivate::startContainer()
|
||||||
{
|
{
|
||||||
if (!createContainer())
|
if (!createContainer())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
m_shell = std::make_unique<ContainerShell>(m_settings, m_container, q->rootPath());
|
m_shell = std::make_unique<ContainerShell>(m_settings, m_container, q->rootPath());
|
||||||
|
|
||||||
@@ -693,23 +717,25 @@ void DockerDevicePrivate::startContainer()
|
|||||||
"or restart Qt Creator."));
|
"or restart Qt Creator."));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!m_shell->start()) {
|
if (m_shell->start())
|
||||||
|
return true;
|
||||||
|
|
||||||
qCWarning(dockerDeviceLog) << "Container shell failed to start";
|
qCWarning(dockerDeviceLog) << "Container shell failed to start";
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockerDevicePrivate::updateContainerAccess()
|
bool DockerDevicePrivate::updateContainerAccess()
|
||||||
{
|
{
|
||||||
if (m_isShutdown)
|
if (m_isShutdown)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
if (DockerApi::isDockerDaemonAvailable(false).value_or(false) == false)
|
if (DockerApi::isDockerDaemonAvailable(false).value_or(false) == false)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
if (m_shell)
|
if (m_shell)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
startContainer();
|
return startContainer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockerDevice::setMounts(const QStringList &mounts) const
|
void DockerDevice::setMounts(const QStringList &mounts) const
|
||||||
@@ -881,7 +907,8 @@ void DockerDevice::aboutToBeRemoved() const
|
|||||||
|
|
||||||
void DockerDevicePrivate::fetchSystemEnviroment()
|
void DockerDevicePrivate::fetchSystemEnviroment()
|
||||||
{
|
{
|
||||||
updateContainerAccess();
|
if (!updateContainerAccess())
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_shell && m_shell->state() == DeviceShell::State::Succeeded) {
|
if (m_shell && m_shell->state() == DeviceShell::State::Succeeded) {
|
||||||
const RunResult result = runInShell({"env", {}});
|
const RunResult result = runInShell({"env", {}});
|
||||||
@@ -905,7 +932,8 @@ void DockerDevicePrivate::fetchSystemEnviroment()
|
|||||||
|
|
||||||
RunResult DockerDevicePrivate::runInShell(const CommandLine &cmd, const QByteArray &stdInData)
|
RunResult DockerDevicePrivate::runInShell(const CommandLine &cmd, const QByteArray &stdInData)
|
||||||
{
|
{
|
||||||
updateContainerAccess();
|
if (!updateContainerAccess())
|
||||||
|
return {};
|
||||||
QTC_ASSERT(m_shell, return {});
|
QTC_ASSERT(m_shell, return {});
|
||||||
return m_shell->runInShell(cmd, stdInData);
|
return m_shell->runInShell(cmd, stdInData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ public:
|
|||||||
|
|
||||||
void setData(const DockerDeviceData &data);
|
void setData(const DockerDeviceData &data);
|
||||||
|
|
||||||
void updateContainerAccess() const;
|
bool updateContainerAccess() const;
|
||||||
void setMounts(const QStringList &mounts) const;
|
void setMounts(const QStringList &mounts) const;
|
||||||
|
|
||||||
bool prepareForBuild(const ProjectExplorer::Target *target) override;
|
bool prepareForBuild(const ProjectExplorer::Target *target) override;
|
||||||
|
|||||||
Reference in New Issue
Block a user