|
3 | 3 | from kubernetes.client.models import V1ContainerState, V1Container, V1ContainerStatus
|
4 | 4 | from kubernetes.client.rest import ApiException
|
5 | 5 | from kubernetes.config.config_exception import ConfigException
|
| 6 | +import yaml |
6 | 7 | from calrissian.executor import IncompleteStatusException
|
7 | 8 | from calrissian.retry import retry_exponential_if_exception_type
|
8 | 9 | import threading
|
@@ -156,70 +157,6 @@ def follow_logs(self):
|
156 | 157 |
|
157 | 158 | log.info('[{}] follow_logs end'.format(pod_name))
|
158 | 159 |
|
159 |
| - @retry_exponential_if_exception_type((ApiException, HTTPError,), log) |
160 |
| - def follow_container_logs(self, status): |
161 |
| - pod_name = self.pod.metadata.name |
162 |
| - |
163 |
| - log.info('[{}] follow_logs start'.format(pod_name)) |
164 |
| - for line in self.core_api_instance.read_namespaced_pod_log(self.pod.metadata.name, self.namespace, follow=True, |
165 |
| - _preload_content=False, container=status.name).stream(): |
166 |
| - # .stream() is only available if _preload_content=False |
167 |
| - # .stream() returns a generator, each iteration yields bytes. |
168 |
| - # kubernetes-client decodes them as utf-8 when _preload_content is True |
169 |
| - # https://github.com/kubernetes-client/python/blob/fcda6fe96beb21cd05522c17f7f08c5a7c0e3dc3/kubernetes/client/rest.py#L215-L216 |
170 |
| - # So we do the same here |
171 |
| - if not status.state.running: |
172 |
| - break |
173 |
| - line = line.decode('utf-8', errors="ignore").rstrip() |
174 |
| - log.debug('[{}] {}'.format(pod_name, line)) |
175 |
| - self.tool_log.append(self.format_log_entry(pod_name, line)) |
176 |
| - |
177 |
| - log.info('[{}] follow_logs end'.format(pod_name)) |
178 |
| - |
179 |
| - @retry_exponential_if_exception_type((ApiException, HTTPError, IncompleteStatusException), log) |
180 |
| - def wait_for_dask_completion(self) -> CompletionResult: |
181 |
| - w = watch.Watch() |
182 |
| - for event in w.stream(self.core_api_instance.list_namespaced_pod, self.namespace, field_selector=self._get_pod_field_selector()): |
183 |
| - pod = event['object'] |
184 |
| - # status = self.get_first_or_none(pod.status.container_statuses) |
185 |
| - last_status = self.get_last_or_none(pod.status.container_statuses) |
186 |
| - if last_status == None or not self.state_is_terminated(last_status.state): |
187 |
| - statuses = self.get_list_or_none(pod.status.container_statuses) |
188 |
| - if statuses == None: |
189 |
| - continue |
190 |
| - for status in statuses: |
191 |
| - log.info('pod name {} with id {} has status {}'.format(pod.metadata.name, pod.metadata.uid, status)) |
192 |
| - if status is None: |
193 |
| - continue |
194 |
| - if self.state_is_waiting(status.state): |
195 |
| - continue |
196 |
| - elif self.state_is_running(status.state): |
197 |
| - # Can only get logs once container is running |
198 |
| - self.follow_container_logs(status) # This will not return until container completes |
199 |
| - elif self.state_is_terminated(status.state): |
200 |
| - continue |
201 |
| - else: |
202 |
| - raise CalrissianJobException('Unexpected pod container status', status) |
203 |
| - elif self.state_is_terminated(last_status.state): |
204 |
| - log.info('Handling terminated pod name {} with id {}'.format(pod.metadata.name, pod.metadata.uid)) |
205 |
| - container = self.get_last_or_none(pod.spec.containers) |
206 |
| - self._handle_completion(last_status.state, container) |
207 |
| - if self.should_delete_pod(): |
208 |
| - with PodMonitor() as monitor: |
209 |
| - self.delete_pod_name(pod.metadata.name) |
210 |
| - monitor.remove(pod) |
211 |
| - self._clear_pod() |
212 |
| - # stop watching for events, our pod is done. Causes wait loop to exit |
213 |
| - w.stop() |
214 |
| - else: |
215 |
| - raise CalrissianJobException('Unexpected pod container status', last_status) |
216 |
| - |
217 |
| - # When the pod is done we should have a completion result |
218 |
| - # Otherwise it will lead to further exceptions |
219 |
| - if self.completion_result is None: |
220 |
| - raise IncompleteStatusException |
221 |
| - |
222 |
| - return self.completion_result |
223 | 160 |
|
224 | 161 | @retry_exponential_if_exception_type((ApiException, HTTPError, IncompleteStatusException), log)
|
225 | 162 | def wait_for_completion(self) -> CompletionResult:
|
@@ -280,20 +217,6 @@ def state_is_waiting(state):
|
280 | 217 | def state_is_terminated(state):
|
281 | 218 | return state.terminated
|
282 | 219 |
|
283 |
| - @staticmethod |
284 |
| - def get_list_or_none(container_list: List[Union[V1ContainerStatus, V1Container]]) -> Union[V1ContainerStatus, V1Container]: |
285 |
| - if not container_list: # None or empty list |
286 |
| - return None |
287 |
| - else: |
288 |
| - return list(container_list) |
289 |
| - |
290 |
| - @staticmethod |
291 |
| - def get_last_or_none(container_list: List[Union[V1ContainerStatus, V1Container]]) -> Union[V1ContainerStatus, V1Container]: |
292 |
| - if not container_list: # None or empty list |
293 |
| - return None |
294 |
| - else: |
295 |
| - return container_list[-1] |
296 |
| - |
297 | 220 | @staticmethod
|
298 | 221 | def get_first_or_none(container_list: List[Union[V1ContainerStatus, V1Container]]) -> Union[V1ContainerStatus, V1Container]:
|
299 | 222 | """
|
@@ -350,16 +273,6 @@ def get_current_pod(self):
|
350 | 273 | raise CalrissianJobException("Missing required environment variable ${}".format(POD_NAME_ENV_VARIABLE))
|
351 | 274 | return self.get_pod_for_name(pod_name)
|
352 | 275 |
|
353 |
| - @retry_exponential_if_exception_type((ApiException, HTTPError,), log) |
354 |
| - def create_dask_gateway_cofig_map(self, gateway_url: str): |
355 |
| - configmap = client.V1ConfigMap( |
356 |
| - metadata=client.V1ObjectMeta(name="dask-gateway-cm"), |
357 |
| - data={ |
358 |
| - "gateway.yaml": f"|\ngateway:\n\taddress:{gateway_url}" |
359 |
| - } |
360 |
| - ) |
361 |
| - |
362 |
| - self.core_api_instance.create_namespaced_config_map(namespace=self.namespace, body=configmap) |
363 | 276 |
|
364 | 277 | class PodMonitor(object):
|
365 | 278 | """
|
|
0 commit comments