From 616970c3a8756aad262745c56df185105704b6ad Mon Sep 17 00:00:00 2001 From: Karel van Klink <karel.vanklink@geant.org> Date: Tue, 11 Jul 2023 16:53:05 +0200 Subject: [PATCH] adjust signature of calling provisioning proxy, making it more streamlined --- gso/services/provisioning_proxy.py | 32 +++++++++---- gso/workflows/device/create_device.py | 15 ++---- gso/workflows/iptrunk/create_iptrunk.py | 51 ++++----------------- gso/workflows/iptrunk/modify_generic.py | 27 ++--------- gso/workflows/iptrunk/modify_isis_metric.py | 15 ++---- gso/workflows/iptrunk/terminate_iptrunk.py | 20 ++------ 6 files changed, 46 insertions(+), 114 deletions(-) diff --git a/gso/services/provisioning_proxy.py b/gso/services/provisioning_proxy.py index 13d90249..2fd1cce9 100644 --- a/gso/services/provisioning_proxy.py +++ b/gso/services/provisioning_proxy.py @@ -14,7 +14,7 @@ from orchestrator.forms import FormPage, ReadOnlyField from orchestrator.forms.validators import Accept, Label, LongText from orchestrator.types import FormGenerator, State, UUIDstr, strEnum from orchestrator.utils.json import json_dumps -from orchestrator.workflow import Step, StepList +from orchestrator.workflow import Step, StepList, abort from pydantic import validator from gso import settings @@ -159,6 +159,7 @@ def _await_pp_results(subscription: SubscriptionModel, label_text: str = DEFAULT boolean set to `True`. :rtype: {class}`orchestrator.types.FormGenerator` """ + class ProvisioningResultPage(FormPage): class Config: title = f"Deploying {subscription.product.name}..." @@ -179,7 +180,7 @@ def _await_pp_results(subscription: SubscriptionModel, label_text: str = DEFAULT @step("Reset Provisioning Proxy state") -def reset_pp_success_state() -> State: +def _reset_pp_success_state() -> State: """Reset the boolean that indicates a successful provisioning proxy result in the state of a running workflow. :return: A new state of the workflow, where the key `pp_did_succeed` has been (re)set to false. @@ -224,8 +225,8 @@ def _confirm_pp_results(state: State) -> FormGenerator: return {"pp_did_succeed": successful_run} -def pp_interaction(provisioning_step: Step) -> StepList: - """Wrapper function for an interaction with the provisioning proxy +def pp_interaction(provisioning_step: Step, attempts: int) -> StepList: + """Interaction with the provisioning proxy. This method returns the three steps that make up an interaction with the provisioning proxy: - The provisioning step itself, given by the user as input. @@ -236,15 +237,28 @@ def pp_interaction(provisioning_step: Step) -> StepList: already successful, these steps are skipped. This mechanism is quite a dirty hack, and it is planned to be addressed in a later release. + The parameter `attempts` indicates how many times a provisioning may be attempted. When this amount is exceeded, and + it is still not successful, the workflow will be aborted. + :param provisioning_step: The step that executes an interaction with the provisioning proxy. :type provisioning_step: {class}`orchestrator.workflow.Step` + :param attempts: The maximum amount of times that a provisioning can be retried. + :type attempts: int :return: A list of three steps that form one interaction with the provisioning proxy. :rtype: {class}`orchestrator.workflow.StepList` """ should_retry_pp_steps = conditional(lambda state: not state.get("pp_did_succeed")) - return ( - should_retry_pp_steps(provisioning_step) - >> should_retry_pp_steps(_await_pp_results) - >> should_retry_pp_steps(_confirm_pp_results) - ) + pp_steps = StepList([_reset_pp_success_state]) + + for _ in range(attempts): + pp_steps >>= ( + should_retry_pp_steps(provisioning_step) + >> should_retry_pp_steps(_await_pp_results) + >> should_retry_pp_steps(_confirm_pp_results) + ) + + # Abort a workflow if provisioning has failed too many times + pp_steps >>= should_retry_pp_steps(abort) + + return pp_steps diff --git a/gso/workflows/device/create_device.py b/gso/workflows/device/create_device.py index a06ee8cf..e0a865f7 100644 --- a/gso/workflows/device/create_device.py +++ b/gso/workflows/device/create_device.py @@ -18,7 +18,7 @@ from gso.products.product_types import device from gso.products.product_types.device import DeviceInactive, DeviceProvisioning from gso.products.product_types.site import Site from gso.services import _ipam, provisioning_proxy -from gso.services.provisioning_proxy import pp_interaction, reset_pp_success_state +from gso.services.provisioning_proxy import pp_interaction def site_selector() -> Choice: @@ -165,17 +165,8 @@ def create_device() -> StepList: >> store_process_subscription(Target.CREATE) >> initialize_subscription >> get_info_from_ipam - # - >> reset_pp_success_state - >> pp_interaction(provision_device_dry) - >> pp_interaction(provision_device_dry) - >> pp_interaction(provision_device_dry) - # - >> reset_pp_success_state - >> pp_interaction(provision_device_real) - >> pp_interaction(provision_device_real) - >> pp_interaction(provision_device_real) - # + >> pp_interaction(provision_device_dry, 3) + >> pp_interaction(provision_device_real, 3) >> set_status(SubscriptionLifecycle.ACTIVE) >> resync >> done diff --git a/gso/workflows/iptrunk/create_iptrunk.py b/gso/workflows/iptrunk/create_iptrunk.py index 3b1e4231..e52ac500 100644 --- a/gso/workflows/iptrunk/create_iptrunk.py +++ b/gso/workflows/iptrunk/create_iptrunk.py @@ -14,7 +14,7 @@ from gso.products.product_blocks.iptrunk import IptrunkType from gso.products.product_types.device import Device from gso.products.product_types.iptrunk import IptrunkInactive, IptrunkProvisioning from gso.services import _ipam, provisioning_proxy -from gso.services.provisioning_proxy import pp_interaction, reset_pp_success_state +from gso.services.provisioning_proxy import pp_interaction def initial_input_form_generator(product_name: str) -> FormGenerator: @@ -245,47 +245,14 @@ def create_iptrunk() -> StepList: >> store_process_subscription(Target.CREATE) >> initialize_subscription >> get_info_from_ipam - >> reset_pp_success_state - # - >> pp_interaction(provision_ip_trunk_iface_dry) - >> pp_interaction(provision_ip_trunk_iface_dry) - >> pp_interaction(provision_ip_trunk_iface_dry) - # - >> reset_pp_success_state - >> pp_interaction(provision_ip_trunk_iface_real) - >> pp_interaction(provision_ip_trunk_iface_real) - >> pp_interaction(provision_ip_trunk_iface_real) - # - >> reset_pp_success_state - >> pp_interaction(provision_ip_trunk_isis_iface_dry) - >> pp_interaction(provision_ip_trunk_isis_iface_dry) - >> pp_interaction(provision_ip_trunk_isis_iface_dry) - # - >> reset_pp_success_state - >> pp_interaction(provision_ip_trunk_isis_iface_real) - >> pp_interaction(provision_ip_trunk_isis_iface_real) - >> pp_interaction(provision_ip_trunk_isis_iface_real) - # - >> reset_pp_success_state - >> pp_interaction(provision_ip_trunk_ldp_iface_dry) - >> pp_interaction(provision_ip_trunk_ldp_iface_dry) - >> pp_interaction(provision_ip_trunk_ldp_iface_dry) - # - >> reset_pp_success_state - >> pp_interaction(provision_ip_trunk_ldp_iface_real) - >> pp_interaction(provision_ip_trunk_ldp_iface_real) - >> pp_interaction(provision_ip_trunk_ldp_iface_real) - # - >> reset_pp_success_state - >> pp_interaction(provision_ip_trunk_lldp_iface_dry) - >> pp_interaction(provision_ip_trunk_lldp_iface_dry) - >> pp_interaction(provision_ip_trunk_lldp_iface_dry) - # - >> reset_pp_success_state - >> pp_interaction(provision_ip_trunk_lldp_iface_real) - >> pp_interaction(provision_ip_trunk_lldp_iface_real) - >> pp_interaction(provision_ip_trunk_lldp_iface_real) - # + >> pp_interaction(provision_ip_trunk_iface_dry, 3) + >> pp_interaction(provision_ip_trunk_iface_real, 3) + >> pp_interaction(provision_ip_trunk_isis_iface_dry, 3) + >> pp_interaction(provision_ip_trunk_isis_iface_real, 3) + >> pp_interaction(provision_ip_trunk_ldp_iface_dry, 3) + >> pp_interaction(provision_ip_trunk_ldp_iface_real, 3) + >> pp_interaction(provision_ip_trunk_lldp_iface_dry, 3) + >> pp_interaction(provision_ip_trunk_lldp_iface_real, 3) >> set_status(SubscriptionLifecycle.ACTIVE) >> resync >> done diff --git a/gso/workflows/iptrunk/modify_generic.py b/gso/workflows/iptrunk/modify_generic.py index f0439a9e..68294b2e 100644 --- a/gso/workflows/iptrunk/modify_generic.py +++ b/gso/workflows/iptrunk/modify_generic.py @@ -12,7 +12,7 @@ from gso.products.product_blocks import PhyPortCapacity from gso.products.product_blocks.iptrunk import IptrunkType from gso.products.product_types.iptrunk import Iptrunk from gso.services import provisioning_proxy -from gso.services.provisioning_proxy import pp_interaction, reset_pp_success_state +from gso.services.provisioning_proxy import pp_interaction def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: @@ -153,27 +153,10 @@ def modify_generic() -> StepList: >> store_process_subscription(Target.MODIFY) >> unsync >> modify_iptrunk_subscription - # - >> reset_pp_success_state - >> pp_interaction(provision_ip_trunk_iface_dry) - >> pp_interaction(provision_ip_trunk_iface_dry) - >> pp_interaction(provision_ip_trunk_iface_dry) - # - >> reset_pp_success_state - >> pp_interaction(provision_ip_trunk_iface_real) - >> pp_interaction(provision_ip_trunk_iface_real) - >> pp_interaction(provision_ip_trunk_iface_real) - # - >> reset_pp_success_state - >> pp_interaction(provision_ip_trunk_lldp_iface_dry) - >> pp_interaction(provision_ip_trunk_lldp_iface_dry) - >> pp_interaction(provision_ip_trunk_lldp_iface_dry) - # - >> reset_pp_success_state - >> pp_interaction(provision_ip_trunk_lldp_iface_real) - >> pp_interaction(provision_ip_trunk_lldp_iface_real) - >> pp_interaction(provision_ip_trunk_lldp_iface_real) - # + >> pp_interaction(provision_ip_trunk_iface_dry, 3) + >> pp_interaction(provision_ip_trunk_iface_real, 3) + >> pp_interaction(provision_ip_trunk_lldp_iface_dry, 3) + >> pp_interaction(provision_ip_trunk_lldp_iface_real, 3) >> resync >> done ) diff --git a/gso/workflows/iptrunk/modify_isis_metric.py b/gso/workflows/iptrunk/modify_isis_metric.py index 21af4c57..d7affd6a 100644 --- a/gso/workflows/iptrunk/modify_isis_metric.py +++ b/gso/workflows/iptrunk/modify_isis_metric.py @@ -7,7 +7,7 @@ from orchestrator.workflows.utils import wrap_modify_initial_input_form from gso.products.product_types.iptrunk import Iptrunk from gso.services import provisioning_proxy -from gso.services.provisioning_proxy import pp_interaction, reset_pp_success_state +from gso.services.provisioning_proxy import pp_interaction def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: @@ -71,17 +71,8 @@ def modify_isis_metric() -> StepList: >> store_process_subscription(Target.MODIFY) >> unsync >> modify_iptrunk_subscription - # - >> reset_pp_success_state - >> pp_interaction(provision_ip_trunk_isis_iface_dry) - >> pp_interaction(provision_ip_trunk_isis_iface_dry) - >> pp_interaction(provision_ip_trunk_isis_iface_dry) - # - >> reset_pp_success_state - >> pp_interaction(provision_ip_trunk_isis_iface_real) - >> pp_interaction(provision_ip_trunk_isis_iface_real) - >> pp_interaction(provision_ip_trunk_isis_iface_real) - # + >> pp_interaction(provision_ip_trunk_isis_iface_dry, 3) + >> pp_interaction(provision_ip_trunk_isis_iface_real, 3) >> resync >> done ) diff --git a/gso/workflows/iptrunk/terminate_iptrunk.py b/gso/workflows/iptrunk/terminate_iptrunk.py index 2436c8e8..474ae707 100644 --- a/gso/workflows/iptrunk/terminate_iptrunk.py +++ b/gso/workflows/iptrunk/terminate_iptrunk.py @@ -12,7 +12,7 @@ from orchestrator.workflows.utils import wrap_modify_initial_input_form from gso.products.product_types.iptrunk import Iptrunk from gso.services import ipam, provisioning_proxy from gso.services.ipam import V4ServiceNetwork, V6ServiceNetwork -from gso.services.provisioning_proxy import pp_interaction, reset_pp_success_state +from gso.services.provisioning_proxy import pp_interaction def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: @@ -92,22 +92,8 @@ def terminate_iptrunk() -> StepList: >> store_process_subscription(Target.TERMINATE) >> unsync >> modify_iptrunk_subscription - # - >> reset_pp_success_state - >> pp_interaction(drain_traffic_from_ip_trunk) - >> pp_interaction(drain_traffic_from_ip_trunk) - >> pp_interaction(drain_traffic_from_ip_trunk) - # - >> reset_pp_success_state - >> pp_interaction(deprovision_ip_trunk_dry) - >> pp_interaction(deprovision_ip_trunk_dry) - >> pp_interaction(deprovision_ip_trunk_dry) - # - >> reset_pp_success_state - >> pp_interaction(deprovision_ip_trunk_real) - >> pp_interaction(deprovision_ip_trunk_real) - >> pp_interaction(deprovision_ip_trunk_real) - # + >> pp_interaction(drain_traffic_from_ip_trunk, 3) + >> pp_interaction(deprovision_ip_trunk_dry, 3) >> deprovision_ip_trunk_ipv4 >> deprovision_ip_trunk_ipv6 >> set_status(SubscriptionLifecycle.TERMINATED) -- GitLab