mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-10-22 10:52:21 +03:00
Merge pull request #2619 from yueguobin/fix/docker-container-name-conflict
fix(docker): handle container name conflict automatically
This commit is contained in:
commit
dce4a71004
@ -32,7 +32,7 @@ from gns3server.config import Config
|
|||||||
from gns3server.utils.asyncio import locking
|
from gns3server.utils.asyncio import locking
|
||||||
from gns3server.compute.base_manager import BaseManager
|
from gns3server.compute.base_manager import BaseManager
|
||||||
from gns3server.compute.docker.docker_vm import DockerVM
|
from gns3server.compute.docker.docker_vm import DockerVM
|
||||||
from gns3server.compute.docker.docker_error import DockerError, DockerHttp304Error, DockerHttp404Error
|
from gns3server.compute.docker.docker_error import DockerError, DockerHttp304Error, DockerHttp404Error, DockerHttp409Error
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -240,6 +240,8 @@ class Docker(BaseManager):
|
|||||||
raise DockerHttp304Error(f"Docker has returned an error: {response.status} {body}")
|
raise DockerHttp304Error(f"Docker has returned an error: {response.status} {body}")
|
||||||
elif response.status == 404:
|
elif response.status == 404:
|
||||||
raise DockerHttp404Error(f"Docker has returned an error: {response.status} {body}")
|
raise DockerHttp404Error(f"Docker has returned an error: {response.status} {body}")
|
||||||
|
elif response.status == 409:
|
||||||
|
raise DockerHttp409Error(f"Docker has returned an error: {response.status} {body}")
|
||||||
else:
|
else:
|
||||||
raise DockerError(f"Docker has returned an error: {response.status} {body}")
|
raise DockerError(f"Docker has returned an error: {response.status} {body}")
|
||||||
return response
|
return response
|
||||||
|
|||||||
@ -31,3 +31,7 @@ class DockerHttp304Error(DockerError):
|
|||||||
|
|
||||||
class DockerHttp404Error(DockerError):
|
class DockerHttp404Error(DockerError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DockerHttp409Error(DockerError):
|
||||||
|
pass
|
||||||
|
|||||||
@ -41,7 +41,7 @@ from ..base_node import BaseNode
|
|||||||
|
|
||||||
from ..adapters.ethernet_adapter import EthernetAdapter
|
from ..adapters.ethernet_adapter import EthernetAdapter
|
||||||
from ..nios.nio_udp import NIOUDP
|
from ..nios.nio_udp import NIOUDP
|
||||||
from .docker_error import DockerError, DockerHttp304Error, DockerHttp404Error
|
from .docker_error import DockerError, DockerHttp304Error, DockerHttp404Error, DockerHttp409Error
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -548,7 +548,28 @@ class DockerVM(BaseNode):
|
|||||||
params["Env"].append(f"GNS3_EXTRA_HOSTS={extra_hosts}")
|
params["Env"].append(f"GNS3_EXTRA_HOSTS={extra_hosts}")
|
||||||
|
|
||||||
# Support name in Doker: [a-zA-Z0-9][a-zA-Z0-9_.-]
|
# Support name in Doker: [a-zA-Z0-9][a-zA-Z0-9_.-]
|
||||||
result = await self.manager.query("POST", f"containers/create?name={self.docker_name}", data=params)
|
try:
|
||||||
|
result = await self.manager.query("POST", f"containers/create?name={self.docker_name}", data=params)
|
||||||
|
except DockerHttp409Error:
|
||||||
|
# Container name already exists. This can happen when the server crashes
|
||||||
|
# and leaves containers behind. Try to remove the conflicting container.
|
||||||
|
log.warning(f"Container name '{self.docker_name}' is already in use, attempting to clean up the stale container...")
|
||||||
|
try:
|
||||||
|
# Try to get and remove the conflicting container
|
||||||
|
try:
|
||||||
|
container_info = await self.manager.query("GET", f"containers/{self.docker_name}/json")
|
||||||
|
container_id = container_info["Id"]
|
||||||
|
# Force remove the container
|
||||||
|
await self.manager.query("DELETE", f"containers/{container_id}", params={"force": 1, "v": 1})
|
||||||
|
log.info(f"Removed stale container '{self.docker_name}' ({container_id})")
|
||||||
|
except DockerHttp404Error:
|
||||||
|
# Container doesn't exist anymore, race condition - just continue
|
||||||
|
pass
|
||||||
|
# Retry creating the container
|
||||||
|
result = await self.manager.query("POST", f"containers/create?name={self.docker_name}", data=params)
|
||||||
|
except DockerError as e:
|
||||||
|
log.error(f"Failed to clean up conflicting container '{self.docker_name}': {e}")
|
||||||
|
raise
|
||||||
self._cid = result["Id"]
|
self._cid = result["Id"]
|
||||||
log.info(f"Docker container '{self._name}' [{self._id}] created")
|
log.info(f"Docker container '{self._name}' [{self._id}] created")
|
||||||
if self._cpus > 0:
|
if self._cpus > 0:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user