|
16 | 16 | import redis |
17 | 17 | from ansible_base.rbac.api.related import check_related_permissions |
18 | 18 | from ansible_base.rbac.models import RoleDefinition |
19 | | -from django.conf import settings |
20 | 19 | from django.db import transaction |
21 | 20 | from django.forms import model_to_dict |
22 | 21 | from django_filters import rest_framework as defaultfilters |
@@ -208,17 +207,30 @@ def partial_update(self, request, pk): |
208 | 207 | None, |
209 | 208 | description="The Activation has been deleted.", |
210 | 209 | ), |
| 210 | + status.HTTP_409_CONFLICT: OpenApiResponse( |
| 211 | + None, |
| 212 | + description="Activation blocked while Workers offline.", |
| 213 | + ), |
211 | 214 | } |
212 | 215 | | RedisDependencyMixin.redis_unavailable_response(), |
| 216 | + parameters=[ |
| 217 | + OpenApiParameter( |
| 218 | + name="force", |
| 219 | + description="Force delete after worker node offline", |
| 220 | + required=False, |
| 221 | + type=bool, |
| 222 | + ) |
| 223 | + ], |
213 | 224 | ) |
214 | 225 | def destroy(self, request, *args, **kwargs): |
215 | 226 | activation = self.get_object() |
| 227 | + force_delete = str_to_bool( |
| 228 | + request.query_params.get("force", "false"), |
| 229 | + ) |
216 | 230 |
|
217 | | - if activation.status == ActivationStatus.WORKERS_OFFLINE: |
218 | | - raise api_exc.Conflict( |
219 | | - f"An Activation in state '{activation.status}' cannot be " |
220 | | - "deleted.", |
221 | | - ) |
| 231 | + self._check_workers_offline_with_force( |
| 232 | + activation, force_delete, "Deleted" |
| 233 | + ) |
222 | 234 |
|
223 | 235 | audit_log = logging_utils.generate_simple_audit_log( |
224 | 236 | "Delete", |
@@ -434,14 +446,33 @@ def _start(self, request, activation: models.Activation) -> Response: |
434 | 446 | None, |
435 | 447 | description="Activation has been disabled.", |
436 | 448 | ), |
| 449 | + status.HTTP_409_CONFLICT: OpenApiResponse( |
| 450 | + None, |
| 451 | + description="Activation blocked while Workers offline.", |
| 452 | + ), |
437 | 453 | } |
438 | 454 | | RedisDependencyMixin.redis_unavailable_response(), |
| 455 | + parameters=[ |
| 456 | + OpenApiParameter( |
| 457 | + name="force", |
| 458 | + description="Force disable after worker node offline", |
| 459 | + required=False, |
| 460 | + type=bool, |
| 461 | + ) |
| 462 | + ], |
439 | 463 | ) |
440 | 464 | @action(methods=["post"], detail=True, rbac_action=Action.DISABLE) |
441 | 465 | def disable(self, request, pk): |
442 | 466 | activation = self.get_object() |
443 | 467 |
|
444 | 468 | self._check_deleting(activation) |
| 469 | + force_disable = str_to_bool( |
| 470 | + request.query_params.get("force", "false"), |
| 471 | + ) |
| 472 | + |
| 473 | + self._check_workers_offline_with_force( |
| 474 | + activation, force_disable, "Disabled" |
| 475 | + ) |
445 | 476 |
|
446 | 477 | if activation.is_enabled: |
447 | 478 | # Redis must be available in order to perform the delete. |
@@ -509,19 +540,9 @@ def restart(self, request, pk): |
509 | 540 | request.query_params.get("force", "false"), |
510 | 541 | ) |
511 | 542 |
|
512 | | - if ( |
513 | | - settings.DEPLOYMENT_TYPE == "podman" |
514 | | - and activation.status == ActivationStatus.WORKERS_OFFLINE |
515 | | - and not force_restart |
516 | | - ): |
517 | | - # block the restart and return an error |
518 | | - raise api_exc.Conflict( |
519 | | - "An activation with an activation_status of 'Workers offline' " |
520 | | - "cannot be Restarted because this will leave an orphaned " |
521 | | - "container running on one of the 'activation-worker-node's. " |
522 | | - "If you want to force a restart, please add the " |
523 | | - "/?force=true query param." |
524 | | - ) |
| 543 | + self._check_workers_offline_with_force( |
| 544 | + activation, force_restart, "Restarted" |
| 545 | + ) |
525 | 546 | if not activation.is_enabled: |
526 | 547 | raise api_exc.Forbidden( |
527 | 548 | detail="Activation is disabled and cannot be run." |
@@ -616,6 +637,34 @@ def _check_deleting(self, activation): |
616 | 637 | detail="Object is being deleted", code=409 |
617 | 638 | ) |
618 | 639 |
|
| 640 | + def _check_workers_offline_with_force( |
| 641 | + self, activation, force_flag, operation_name |
| 642 | + ): |
| 643 | + """ |
| 644 | + Check if activation is in WORKERS_OFFLINE status and handle force flag. |
| 645 | +
|
| 646 | + Args: |
| 647 | + activation: The activation object to check |
| 648 | + force_flag: Boolean indicating if force operation is requested |
| 649 | + operation_name: String name of the operation |
| 650 | + (e.g., "Restarted", "Disabled", "Deleted") |
| 651 | +
|
| 652 | + Raises: |
| 653 | + api_exc.Conflict: If activation is WORKERS_OFFLINE and force flag |
| 654 | + is False |
| 655 | + """ |
| 656 | + if ( |
| 657 | + activation.status == ActivationStatus.WORKERS_OFFLINE |
| 658 | + and not force_flag |
| 659 | + ): |
| 660 | + raise api_exc.Conflict( |
| 661 | + f"An activation with an activation_status of " |
| 662 | + f"'Workers offline' cannot be {operation_name} because this " |
| 663 | + f"may leave an orphaned container running. " |
| 664 | + f"If you want to force a {operation_name.lower()}, please " |
| 665 | + f"add the /?force=true query param." |
| 666 | + ) |
| 667 | + |
619 | 668 |
|
620 | 669 | @extend_schema_view( |
621 | 670 | retrieve=extend_schema( |
|
0 commit comments