|
1 | 1 | from typing import Tuple, Optional
|
| 2 | +from enum import IntFlag |
2 | 3 |
|
3 | 4 | import docker # type: ignore
|
4 | 5 | from docker.models.networks import Network # type: ignore
|
|
25 | 26 | NAME_SERVER_ADDRESS = "8.8.8.8"
|
26 | 27 |
|
27 | 28 |
|
| 29 | +class ItdeContainerStatus(IntFlag): |
| 30 | + ABSENT = 0 |
| 31 | + STOPPED = 1 |
| 32 | + RUNNING = 3 |
| 33 | + VISIBLE = 5 |
| 34 | + READY = RUNNING | VISIBLE |
| 35 | + |
| 36 | + |
28 | 37 | def bring_itde_up(conf: Secrets) -> None:
|
29 | 38 | """
|
30 | 39 | Launches the ITDE environment using its API. Sets hardcoded environment name,
|
@@ -100,20 +109,21 @@ def _add_current_container_to_db_network(network_name: str) -> None:
|
100 | 109 | network.connect(container.id)
|
101 | 110 |
|
102 | 111 |
|
103 |
| -def _is_current_container_not_in_db_network(network_name: str) -> bool: |
| 112 | +def _is_current_container_visible(network_name: str) -> bool: |
104 | 113 | """
|
105 | 114 | For the Docker Edition returns True if the current (AI-Lab) container
|
106 |
| - is NOT connected to the network with the specified name. Otherwise, |
107 |
| - including the cases of other editions, returns False. |
| 115 | + is connected to the network with the specified name, otherwise False. |
| 116 | + For other editions it always returns True. |
108 | 117 | """
|
109 | 118 | with ContextDockerClient() as docker_client:
|
110 | 119 | container = _get_current_container(docker_client)
|
111 | 120 | if not container:
|
112 |
| - return False |
| 121 | + # Not the Docker Edition |
| 122 | + return True |
113 | 123 | network = _get_docker_network(docker_client, network_name)
|
114 | 124 | if not network:
|
115 |
| - return True |
116 |
| - return container not in network.containers |
| 125 | + return False |
| 126 | + return container in network.containers |
117 | 127 |
|
118 | 128 |
|
119 | 129 | def _get_docker_network(docker_client: docker.DockerClient, network_name: str) -> Optional[Network]:
|
@@ -144,61 +154,62 @@ def _get_ipv4_addresses():
|
144 | 154 | return ip_addresses
|
145 | 155 |
|
146 | 156 |
|
147 |
| -def is_itde_running(conf: Secrets) -> Tuple[bool, bool]: |
| 157 | +def get_itde_status(conf: Secrets) -> ItdeContainerStatus: |
148 | 158 | """
|
149 | 159 | Checks if the ITDE container exists and ready to be used. In the Docker Edition that
|
150 | 160 | means the ITDE is running and the AI-Lab container is connected to its network. In
|
151 | 161 | other editions it will just check that the ITDE is running.
|
152 | 162 |
|
153 |
| - Returns two boolean flags - (exists, running). |
| 163 | + Returns the container status. |
154 | 164 |
|
155 | 165 | The name of the container is taken from the provided secret store.
|
156 |
| - If the name cannot be found in the secret store the function returns False, False. |
| 166 | + If the name cannot be found there the function returns the status ABSENT. |
157 | 167 | """
|
158 | 168 |
|
159 | 169 | # Try to get the names of the Docker-DB container and its network from the secret store.
|
160 | 170 | container_name = conf.get(AILabConfig.itde_container)
|
161 | 171 | network_name = conf.get(AILabConfig.itde_network)
|
162 | 172 | if not container_name or not network_name:
|
163 |
| - return False, False |
| 173 | + return ItdeContainerStatus.ABSENT |
164 | 174 |
|
165 | 175 | # Check the existence and the status of the container using the Docker API.
|
166 | 176 | with ContextDockerClient() as docker_client:
|
167 | 177 | if docker_client.containers.list(all=True, filters={"name": container_name}):
|
168 | 178 | container = docker_client.containers.get(container_name)
|
169 |
| - is_ready = (container.status == 'running' and not |
170 |
| - _is_current_container_not_in_db_network(network_name)) |
171 |
| - return True, is_ready |
172 |
| - return False, False |
| 179 | + if container.status != 'running': |
| 180 | + return ItdeContainerStatus.STOPPED |
| 181 | + status = ItdeContainerStatus.RUNNING |
| 182 | + if _is_current_container_visible(network_name): |
| 183 | + status |= ItdeContainerStatus.VISIBLE |
| 184 | + return status |
| 185 | + return ItdeContainerStatus.ABSENT |
173 | 186 |
|
174 | 187 |
|
175 |
| -def start_itde(conf: Secrets) -> None: |
| 188 | +def restart_itde(conf: Secrets) -> None: |
176 | 189 | """
|
177 | 190 | Starts an existing ITDE container if it's not already running. In the Docker Edition
|
178 | 191 | connects the AI-Lab container to the Docker-DB network, unless it's already connected
|
179 | 192 | to it.
|
180 | 193 |
|
181 |
| - For this function to work the container must exist. If it doesn't |
182 |
| - the docker.errors.NotFound exception will be raised. Use the is_itde_running |
183 |
| - function to check if the container exists. |
184 |
| -
|
185 |
| - The name of the container is taken from the provided secret store, where it must |
186 |
| - exist. Otherwise, a RuntimeError will be raised. |
| 194 | + For this function to work the container must exist. If it doesn't a RuntimeError will |
| 195 | + be raised. Use the get_itde_status function to check if the container exists. |
187 | 196 | """
|
188 | 197 |
|
189 |
| - # The names of the Docker-DB container and its network should be in the secret store. |
190 |
| - container_name = conf.get(AILabConfig.itde_container) |
191 |
| - network_name = conf.get(AILabConfig.itde_network) |
192 |
| - if not container_name or not network_name: |
193 |
| - raise RuntimeError('Unable to find the name of the Docker container or its network.') |
| 198 | + status = get_itde_status(conf) |
194 | 199 |
|
195 |
| - # Start the container using the Docker API, unless it's already running. |
196 |
| - with ContextDockerClient() as docker_client: |
197 |
| - container = docker_client.containers.get(container_name) |
198 |
| - if container.status != 'running': |
| 200 | + if status is ItdeContainerStatus.ABSENT: |
| 201 | + raise RuntimeError("The Docker-DB container doesn't exist.") |
| 202 | + |
| 203 | + if ItdeContainerStatus.RUNNING not in status: |
| 204 | + container_name = conf.get(AILabConfig.itde_container) |
| 205 | + with ContextDockerClient() as docker_client: |
| 206 | + container = docker_client.containers.get(container_name) |
199 | 207 | container.start()
|
200 | 208 |
|
201 |
| - _add_current_container_to_db_network(network_name) |
| 209 | + if ItdeContainerStatus.VISIBLE not in status: |
| 210 | + network_name = conf.get(AILabConfig.itde_network) |
| 211 | + if network_name: |
| 212 | + _add_current_container_to_db_network(network_name) |
202 | 213 |
|
203 | 214 |
|
204 | 215 | def take_itde_down(conf: Secrets) -> None:
|
|
0 commit comments