diff --git a/gso/services/provisioning_proxy.py b/gso/services/provisioning_proxy.py index 9ec5f50eee03d94f2b18bc31512c1ac8d579dc7a..9ba2862475a544a840740d6f14b64bdcd87bdf3a 100644 --- a/gso/services/provisioning_proxy.py +++ b/gso/services/provisioning_proxy.py @@ -12,6 +12,7 @@ from orchestrator.utils.json import json_dumps from gso import settings from gso.products.product_types.device import DeviceProvisioning +from gso.products.product_types.iptrunk import IptrunkProvisioning logger = logging.getLogger(__name__) @@ -48,12 +49,18 @@ def _provision_service( _send_request(endpoint, parameters, process_id) -def provision_device(subscription: SubscriptionModel, +def provision_device(subscription: DeviceProvisioning, process_id: UUIDstr, dry_run: bool = True): _provision_service('device', subscription, process_id, dry_run) +def provision_ip_trunk(subscription: IptrunkProvisioning, + process_id: UUIDstr, + dry_run: bool = True): + _provision_service('ip_trunk', subscription, process_id, dry_run) + + @inputstep('Await provisioning proxy results', assignee=Assignee('SYSTEM')) def await_pp_results() -> State: class ProvisioningResultPage(FormPage): diff --git a/gso/workflows/device/create_device.py b/gso/workflows/device/create_device.py index 640c5297d1567d1871d385bf9905516c6982b9d6..9ee1cafb8ab1d5242755865e00f8d4d496c99d64 100644 --- a/gso/workflows/device/create_device.py +++ b/gso/workflows/device/create_device.py @@ -26,13 +26,13 @@ def site_selector() -> list: site_subscriptions = {} for site_id, site_description in ( SubscriptionTable.query.join(ProductTable) - .filter( + .filter( ProductTable.product_type == "Site", SubscriptionTable.status == "active", ) - .with_entities(SubscriptionTable.subscription_id, - SubscriptionTable.description) - .all() + .with_entities(SubscriptionTable.subscription_id, + SubscriptionTable.description) + .all() ): site_subscriptions[str(site_id)] = site_description @@ -123,10 +123,7 @@ def initialize_subscription( @step('Provision device [DRY RUN]') def provision_device_dry(subscription: DeviceProvisioning, process_id: UUIDstr) -> State: - provisioning_proxy.provision_service( - subscription, - process_id - ) + provisioning_proxy.provision_device(subscription, process_id) return {'subscription': subscription} @@ -134,11 +131,7 @@ def provision_device_dry(subscription: DeviceProvisioning, @step('Provision device [FOR REAL]') def provision_device_real(subscription: DeviceProvisioning, process_id: UUIDstr) -> State: - provisioning_proxy.provision_service( - subscription, - process_id, - False # No dry run this time, run it for real - ) + provisioning_proxy.provision_device(subscription, process_id, False) return {'subscription': subscription} diff --git a/gso/workflows/iptrunk/create_iptrunk.py b/gso/workflows/iptrunk/create_iptrunk.py index 4cfe1c39b7ab4d6cb6f1990a5684a1598434a8f5..efbc856808687bb658207b9ba4efb3b8739be204 100644 --- a/gso/workflows/iptrunk/create_iptrunk.py +++ b/gso/workflows/iptrunk/create_iptrunk.py @@ -1,38 +1,37 @@ import ipaddress from uuid import uuid4 +from orchestrator.db.models import ProductTable, SubscriptionTable from orchestrator.forms import FormPage +from orchestrator.forms.validators import Choice, choice_list from orchestrator.targets import Target -from orchestrator.workflow import inputstep -from orchestrator.forms.validators import Accept from orchestrator.types import FormGenerator, State from orchestrator.types import SubscriptionLifecycle, UUIDstr from orchestrator.workflow import done, init, step, workflow from orchestrator.workflows.steps import resync, set_status from orchestrator.workflows.steps import store_process_subscription from orchestrator.workflows.utils import wrap_create_initial_input_form -from gso.products.product_types import iptrunk -from gso.products.product_blocks import iptrunk as iptrunk_pb -from gso.products.product_types.device import Device -# from gso.services import ipam, provisioning_proxy -# from gso.products.product_types import device -from orchestrator.db.models import ProductTable, SubscriptionTable -from orchestrator.forms.validators import Choice, choice_list -from orchestrator.utils.json import json_dumps +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 provisioning_proxy +from gso.services.provisioning_proxy import confirm_pp_results, \ + await_pp_results def device_selector(choice_value: str) -> list: device_subscriptions = {} for device_id, device_description in ( - SubscriptionTable.query.join(ProductTable) - .filter( - ProductTable.product_type == "Device", - SubscriptionTable.status == "active", - ) - .with_entities(SubscriptionTable.subscription_id, - SubscriptionTable.description) - .all() + SubscriptionTable.query.join(ProductTable) + .filter( + ProductTable.product_type == 'Device', + SubscriptionTable.status == 'active', + ) + .with_entities(SubscriptionTable.subscription_id, + SubscriptionTable.description) + .all() ): device_subscriptions[str(device_id)] = device_description @@ -51,7 +50,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: geant_s_sid: str iptrunk_description: str - iptrunk_type: iptrunk_pb.IptrunkType + iptrunk_type: IptrunkType iptrunk_speed: str # This should be an enum: 1/10/100/400 iptrunk_minimum_links: int @@ -79,44 +78,44 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: return user_input.dict() -@step("Create subscription") +@step('Create subscription') def create_subscription(product: UUIDstr) -> State: - subscription = iptrunk.IptrunkInactive.from_product_id(product, uuid4()) + subscription = IptrunkInactive.from_product_id(product, uuid4()) return { - "subscription": subscription, - "subscription_id": subscription.subscription_id, + 'subscription': subscription, + 'subscription_id': subscription.subscription_id, } -@step("Get information from IPAM ") -def get_info_from_ipam(subscription: iptrunk.IptrunkInactive) -> State: +@step('Get information from IPAM') +def get_info_from_ipam(subscription: IptrunkInactive) -> State: # TODO: get info about how these should be generated subscription.iptrunk.iptrunk_ipv4_network \ = ipaddress.ip_network('192.168.255.0/31') subscription.iptrunk.iptrunk_ipv6_network \ = ipaddress.ip_network('fc00:798:255::150/126') - return {"subscription": subscription} + return {'subscription': subscription} -@step("Initialize subscription") +@step('Initialize subscription') def initialize_subscription( - subscription: iptrunk.IptrunkInactive, - geant_s_sid: str, - iptrunk_type: iptrunk_pb.IptrunkType, - iptrunk_description: str, - iptrunk_speed: str, - iptrunk_minimum_links: int, - iptrunk_sideA_node_id: str, - iptrunk_sideA_ae_iface: str, - iptrunk_sideA_ae_geant_a_sid: str, - iptrunk_sideA_ae_members: list[str], - iptrunk_sideA_ae_members_descriptions: list[str], - iptrunk_sideB_node_id: str, - iptrunk_sideB_ae_iface: str, - iptrunk_sideB_ae_geant_a_sid: str, - iptrunk_sideB_ae_members: list[str], - iptrunk_sideB_ae_members_descriptions: list[str] + subscription: IptrunkInactive, + geant_s_sid: str, + iptrunk_type: IptrunkType, + iptrunk_description: str, + iptrunk_speed: str, + iptrunk_minimum_links: int, + iptrunk_sideA_node_id: str, + iptrunk_sideA_ae_iface: str, + iptrunk_sideA_ae_geant_a_sid: str, + iptrunk_sideA_ae_members: list[str], + iptrunk_sideA_ae_members_descriptions: list[str], + iptrunk_sideB_node_id: str, + iptrunk_sideB_ae_iface: str, + iptrunk_sideB_ae_geant_a_sid: str, + iptrunk_sideB_ae_members: list[str], + iptrunk_sideB_ae_members_descriptions: list[str] ) -> State: subscription.iptrunk.geant_s_sid = geant_s_sid subscription.iptrunk.iptrunk_description = iptrunk_description @@ -125,7 +124,7 @@ def initialize_subscription( subscription.iptrunk.iptrunk_minimum_links = iptrunk_minimum_links subscription.iptrunk.iptrunk_sideA_node = Device.from_subscription( - iptrunk_sideA_node_id[0]).device + iptrunk_sideA_node_id[0]).device subscription.iptrunk.iptrunk_sideA_ae_iface = iptrunk_sideA_ae_iface subscription.iptrunk.iptrunk_sideA_ae_geant_a_sid \ = iptrunk_sideA_ae_geant_a_sid @@ -134,7 +133,7 @@ def initialize_subscription( = iptrunk_sideA_ae_members_descriptions subscription.iptrunk.iptrunk_sideB_node = Device.from_subscription( - iptrunk_sideB_node_id[0]).device + iptrunk_sideB_node_id[0]).device subscription.iptrunk.iptrunk_sideB_ae_iface \ = iptrunk_sideB_ae_iface subscription.iptrunk.iptrunk_sideB_ae_geant_a_sid \ @@ -143,105 +142,50 @@ def initialize_subscription( subscription.iptrunk.iptrunk_sideB_ae_members_description \ = iptrunk_sideB_ae_members_descriptions - subscription.description = f"Iptrunk {geant_s_sid}: \ - (blablabla)" - subscription = iptrunk.IptrunkProvisioning.from_other_lifecycle( + subscription.description = f'IP trunk, geant_s_sid:{geant_s_sid}' + subscription = IptrunkProvisioning.from_other_lifecycle( subscription, SubscriptionLifecycle.PROVISIONING ) - return {"subscription": subscription} - - -@step("Provision iptrunk [DRY RUN]") -def provision_iptrunk_dry( - subscription: iptrunk.IptrunkProvisioning, -) -> State: - import ansible_runner - - r = ansible_runner.run( - private_data_dir="/opt/geant-gap-ansible", - playbook = "iptrunks.yaml", - inventory = str(subscription.iptrunk.iptrunk_sideA_node.device_fqdn +"\n"+ - subscription.iptrunk.iptrunk_sideB_node.device_fqdn+"\n"), - extravars = { - "verb": "deploy", - "wfo_trunk_json":json_dumps(subscription), - "config_object":"trunk_interface", - }, - ) - out = r.stdout.read() - out_splitted = out.splitlines() - # # if r.rc != 0: - # # raise ValueError("Ansible has failed") - return {"dry_run_output": out_splitted, "return_code": r.rc} - # provisioning_proxy.provision_node( - # node_subscription_params=subscription, - # dry_run=True) - # TODO: figure out what to return when we are suspending & waiting - # for the provisioning-proxy to call back - #return {"return_code": 0} + return {'subscription': subscription} -@inputstep("Confirm step", assignee="CHANGES") -def confirm_step() -> FormGenerator: - class ConfirmForm(FormPage): - confirm: Accept +@step('Provision IP trunk [DRY RUN]') +def provision_ip_trunk_dry(subscription: IptrunkProvisioning, + process_id: UUIDstr) -> State: + provisioning_proxy.provision_ip_trunk(subscription, process_id) - user_input = yield ConfirmForm + return {'subscription': subscription} - return {"confirm": user_input.confirm} +@step('Provision IP trunk [FOR REAL]') +def provision_ip_trunk_real(subscription: IptrunkProvisioning, + process_id: UUIDstr) -> State: + provisioning_proxy.provision_ip_trunk(subscription, process_id, False) -@step("Provision iptrunk [FOR REAL]") -def provision_iptrunk_real( - subscription: iptrunk.IptrunkProvisioning, -) -> State: - # import ansible_runner - # - # r = ansible_runner.run( - # private_data_dir="/opt/geant-gap-ansible", - # playbook="base_config.yaml", - # inventory=subscription.iptrunk.fqdn, - # extravars={ - # "lo_ipv4_address": str(subscription.iptrunk.lo_ipv4_address), - # "lo_ipv6_address": str(subscription.iptrunk.lo_ipv6_address), - # "lo_iso_address": subscription.iptrunk.lo_iso_address, - # "snmp_location": subscription.iptrunk.snmp_location, - # "si_ipv4_network": str(subscription.iptrunk.si_ipv4_network), - # "lt_ipv4_network": str(subscription.iptrunk.ias_lt_ipv4_network), - # "lt_ipv6_network": str(subscription.iptrunk.ias_lt_ipv6_network), - # "site_country_code": subscription.iptrunk.site_country_code, - # "verb": "deploy", - # }, - # ) - # out = r.stdout.read() - # out_splitted = out.splitlines() - # - # # return {"real_run_output": out_splitted, "return_code": r.rc} - # provisioning_proxy.provision_node( - # node_subscription_params=subscription) - # TODO: figure out what to return when we are suspending & waiting - # for the provisioning-proxy to call back - return {"return_code": 0} + return {'subscription': subscription} @workflow( - "Create Iptrunk", + 'Create IP trunk', initial_input_form=wrap_create_initial_input_form( - initial_input_form_generator), + initial_input_form_generator), target=Target.CREATE, ) def create_iptrunk(): return ( - init - >> create_subscription - >> store_process_subscription(Target.CREATE) - >> get_info_from_ipam - >> initialize_subscription - >> provision_iptrunk_dry - >> confirm_step - >> provision_iptrunk_real - >> set_status(SubscriptionLifecycle.ACTIVE) - >> resync - >> done + init + >> create_subscription + >> store_process_subscription(Target.CREATE) + >> get_info_from_ipam + >> initialize_subscription + >> provision_ip_trunk_dry + >> await_pp_results + >> confirm_pp_results + >> provision_ip_trunk_real + >> await_pp_results + >> confirm_pp_results + >> set_status(SubscriptionLifecycle.ACTIVE) + >> resync + >> done )