Skip to content

Commit

Permalink
Revise the instance recreate and restart flow.
Browse files Browse the repository at this point in the history
  • Loading branch information
csadorf committed Feb 15, 2022
1 parent 27789a4 commit 9e689ea
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 28 deletions.
29 changes: 11 additions & 18 deletions aiidalab_launch/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,17 +398,11 @@ async def _async_start(
"Try to use '--pull' to pull the image prior to start."
)

# Check if image has changed.
assert instance.image is not None
image_changed = (
instance.container and instance.container.image.id != instance.image.id
)
mounts_changed = (
instance.container
and f"{instance.profile.container_name()}_conda"
not in (mount.get("Name") for mount in instance.container.attrs["Mounts"])
)
recreate = image_changed or mounts_changed
# Check if the container configuration has changed.
if instance.container:
configuration_changed = any(instance.configuration_changes())
else:
configuration_changed = False

try:

Expand All @@ -420,22 +414,21 @@ async def _async_start(
InstanceStatus.CREATED,
InstanceStatus.EXITED,
):
if recreate:
if configuration_changed:
with spinner("Recreating container..."):
instance.remove()
instance.create()
instance.recreate()
with spinner("Starting container..."):
instance.start()
elif status is InstanceStatus.UP and restart:
with spinner("Restarting container..."):
if any(instance.configuration_changes()):
if configuration_changed:
instance.stop()
instance.remove()
instance.recreate()
instance.start()
else:
instance.restart()
elif status is InstanceStatus.UP and not restart:
if any(instance.configuration_changes()):
if configuration_changed:
click.secho(
"Container is already running, however the configuration "
"has changed. A restart with --restart is recommended.",
Expand Down Expand Up @@ -723,7 +716,7 @@ def reset(app_state, profile, yes):
)

click.echo("Removing container and associated (data) volumes.")
instance.remove(data=True)
instance.remove(conda=True, data=True)


if __name__ == "__main__":
Expand Down
32 changes: 23 additions & 9 deletions aiidalab_launch/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,13 @@ def configuration_changes(self) -> Generator[str, None, None]:
if self.container.image.id != self.image.id:
yield "Image has changed."

try:
for mount in self._mounts():
if docker_mount_for(self.container, mount["Target"]) != mount["Source"]:
raise ValueError
except ValueError:
yield "Mount configuration has changed."

if self.profile != Profile.from_container(self.container):
yield "Profile configuration has changed."

Expand Down Expand Up @@ -308,6 +315,12 @@ def create(self) -> Container:
)
return self._container

def recreate(self) -> None:
self._requires_container()
assert self.container is not None
self.remove()
self.create()

def start(self) -> None:
self._ensure_home_mount_exists()
LOGGER.info(f"Starting container '{self.profile.container_name()}'...")
Expand Down Expand Up @@ -344,21 +357,22 @@ def stop(self, timeout: float | None = None) -> None:
except AttributeError:
raise RuntimeError("no container")

def remove(self, data: bool = False) -> None:
def remove(self, conda: bool = False, data: bool = False) -> None:
# Remove container
if self.container:
self.container.remove()
self._container = None

# Remove conda volume
try:
self.client.volumes.get(self.profile.conda_volume_name()).remove()
except docker.errors.NotFound: # already removed
logging.debug(
f"Failed to remove conda volume '{self.profile.conda_volume_name()}', likely already removed."
)
except Exception as error: # unexpected error
raise RuntimeError(f"Failed to remove conda volume: {error}")
if conda:
try:
self.client.volumes.get(self.profile.conda_volume_name()).remove()
except docker.errors.NotFound: # already removed
logging.debug(
f"Failed to remove conda volume '{self.profile.conda_volume_name()}', likely already removed."
)
except Exception as error: # unexpected error
raise RuntimeError(f"Failed to remove conda volume: {error}")

if data and self.profile.home_mount:
# Remove home volume
Expand Down
2 changes: 1 addition & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ def assert_status_down():
assert_status_down()

assert get_volume(instance.profile.home_mount)
assert not get_volume(instance.profile.conda_volume_name())
assert get_volume(instance.profile.conda_volume_name())

# Reset instance.
result: Result = runner.invoke(
Expand Down

0 comments on commit 9e689ea

Please sign in to comment.