Skip to content
Snippets Groups Projects
Verified Commit 5a82e691 authored by Karel van Klink's avatar Karel van Klink :smiley_cat:
Browse files

update create IP trunk workflow

parent 5331a499
No related branches found
No related tags found
1 merge request!12Add sites, and add integration of IPtrunks and routers with LSO deployment
...@@ -12,6 +12,7 @@ from orchestrator.utils.json import json_dumps ...@@ -12,6 +12,7 @@ from orchestrator.utils.json import json_dumps
from gso import settings from gso import settings
from gso.products.product_types.device import DeviceProvisioning from gso.products.product_types.device import DeviceProvisioning
from gso.products.product_types.iptrunk import IptrunkProvisioning
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -48,12 +49,18 @@ def _provision_service( ...@@ -48,12 +49,18 @@ def _provision_service(
_send_request(endpoint, parameters, process_id) _send_request(endpoint, parameters, process_id)
def provision_device(subscription: SubscriptionModel, def provision_device(subscription: DeviceProvisioning,
process_id: UUIDstr, process_id: UUIDstr,
dry_run: bool = True): dry_run: bool = True):
_provision_service('device', subscription, process_id, dry_run) _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')) @inputstep('Await provisioning proxy results', assignee=Assignee('SYSTEM'))
def await_pp_results() -> State: def await_pp_results() -> State:
class ProvisioningResultPage(FormPage): class ProvisioningResultPage(FormPage):
......
...@@ -26,13 +26,13 @@ def site_selector() -> list: ...@@ -26,13 +26,13 @@ def site_selector() -> list:
site_subscriptions = {} site_subscriptions = {}
for site_id, site_description in ( for site_id, site_description in (
SubscriptionTable.query.join(ProductTable) SubscriptionTable.query.join(ProductTable)
.filter( .filter(
ProductTable.product_type == "Site", ProductTable.product_type == "Site",
SubscriptionTable.status == "active", SubscriptionTable.status == "active",
) )
.with_entities(SubscriptionTable.subscription_id, .with_entities(SubscriptionTable.subscription_id,
SubscriptionTable.description) SubscriptionTable.description)
.all() .all()
): ):
site_subscriptions[str(site_id)] = site_description site_subscriptions[str(site_id)] = site_description
...@@ -123,10 +123,7 @@ def initialize_subscription( ...@@ -123,10 +123,7 @@ def initialize_subscription(
@step('Provision device [DRY RUN]') @step('Provision device [DRY RUN]')
def provision_device_dry(subscription: DeviceProvisioning, def provision_device_dry(subscription: DeviceProvisioning,
process_id: UUIDstr) -> State: process_id: UUIDstr) -> State:
provisioning_proxy.provision_service( provisioning_proxy.provision_device(subscription, process_id)
subscription,
process_id
)
return {'subscription': subscription} return {'subscription': subscription}
...@@ -134,11 +131,7 @@ def provision_device_dry(subscription: DeviceProvisioning, ...@@ -134,11 +131,7 @@ def provision_device_dry(subscription: DeviceProvisioning,
@step('Provision device [FOR REAL]') @step('Provision device [FOR REAL]')
def provision_device_real(subscription: DeviceProvisioning, def provision_device_real(subscription: DeviceProvisioning,
process_id: UUIDstr) -> State: process_id: UUIDstr) -> State:
provisioning_proxy.provision_service( provisioning_proxy.provision_device(subscription, process_id, False)
subscription,
process_id,
False # No dry run this time, run it for real
)
return {'subscription': subscription} return {'subscription': subscription}
......
import ipaddress import ipaddress
from uuid import uuid4 from uuid import uuid4
from orchestrator.db.models import ProductTable, SubscriptionTable
from orchestrator.forms import FormPage from orchestrator.forms import FormPage
from orchestrator.forms.validators import Choice, choice_list
from orchestrator.targets import Target 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 FormGenerator, State
from orchestrator.types import SubscriptionLifecycle, UUIDstr from orchestrator.types import SubscriptionLifecycle, UUIDstr
from orchestrator.workflow import done, init, step, workflow from orchestrator.workflow import done, init, step, workflow
from orchestrator.workflows.steps import resync, set_status from orchestrator.workflows.steps import resync, set_status
from orchestrator.workflows.steps import store_process_subscription from orchestrator.workflows.steps import store_process_subscription
from orchestrator.workflows.utils import wrap_create_initial_input_form 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 gso.products.product_blocks.iptrunk import IptrunkType
from orchestrator.db.models import ProductTable, SubscriptionTable from gso.products.product_types.device import Device
from orchestrator.forms.validators import Choice, choice_list from gso.products.product_types.iptrunk import IptrunkInactive, \
from orchestrator.utils.json import json_dumps 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: def device_selector(choice_value: str) -> list:
device_subscriptions = {} device_subscriptions = {}
for device_id, device_description in ( for device_id, device_description in (
SubscriptionTable.query.join(ProductTable) SubscriptionTable.query.join(ProductTable)
.filter( .filter(
ProductTable.product_type == "Device", ProductTable.product_type == 'Device',
SubscriptionTable.status == "active", SubscriptionTable.status == 'active',
) )
.with_entities(SubscriptionTable.subscription_id, .with_entities(SubscriptionTable.subscription_id,
SubscriptionTable.description) SubscriptionTable.description)
.all() .all()
): ):
device_subscriptions[str(device_id)] = device_description device_subscriptions[str(device_id)] = device_description
...@@ -51,7 +50,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: ...@@ -51,7 +50,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
geant_s_sid: str geant_s_sid: str
iptrunk_description: 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_speed: str # This should be an enum: 1/10/100/400
iptrunk_minimum_links: int iptrunk_minimum_links: int
...@@ -79,44 +78,44 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: ...@@ -79,44 +78,44 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
return user_input.dict() return user_input.dict()
@step("Create subscription") @step('Create subscription')
def create_subscription(product: UUIDstr) -> State: def create_subscription(product: UUIDstr) -> State:
subscription = iptrunk.IptrunkInactive.from_product_id(product, uuid4()) subscription = IptrunkInactive.from_product_id(product, uuid4())
return { return {
"subscription": subscription, 'subscription': subscription,
"subscription_id": subscription.subscription_id, 'subscription_id': subscription.subscription_id,
} }
@step("Get information from IPAM ") @step('Get information from IPAM')
def get_info_from_ipam(subscription: iptrunk.IptrunkInactive) -> State: def get_info_from_ipam(subscription: IptrunkInactive) -> State:
# TODO: get info about how these should be generated # TODO: get info about how these should be generated
subscription.iptrunk.iptrunk_ipv4_network \ subscription.iptrunk.iptrunk_ipv4_network \
= ipaddress.ip_network('192.168.255.0/31') = ipaddress.ip_network('192.168.255.0/31')
subscription.iptrunk.iptrunk_ipv6_network \ subscription.iptrunk.iptrunk_ipv6_network \
= ipaddress.ip_network('fc00:798:255::150/126') = ipaddress.ip_network('fc00:798:255::150/126')
return {"subscription": subscription} return {'subscription': subscription}
@step("Initialize subscription") @step('Initialize subscription')
def initialize_subscription( def initialize_subscription(
subscription: iptrunk.IptrunkInactive, subscription: IptrunkInactive,
geant_s_sid: str, geant_s_sid: str,
iptrunk_type: iptrunk_pb.IptrunkType, iptrunk_type: IptrunkType,
iptrunk_description: str, iptrunk_description: str,
iptrunk_speed: str, iptrunk_speed: str,
iptrunk_minimum_links: int, iptrunk_minimum_links: int,
iptrunk_sideA_node_id: str, iptrunk_sideA_node_id: str,
iptrunk_sideA_ae_iface: str, iptrunk_sideA_ae_iface: str,
iptrunk_sideA_ae_geant_a_sid: str, iptrunk_sideA_ae_geant_a_sid: str,
iptrunk_sideA_ae_members: list[str], iptrunk_sideA_ae_members: list[str],
iptrunk_sideA_ae_members_descriptions: list[str], iptrunk_sideA_ae_members_descriptions: list[str],
iptrunk_sideB_node_id: str, iptrunk_sideB_node_id: str,
iptrunk_sideB_ae_iface: str, iptrunk_sideB_ae_iface: str,
iptrunk_sideB_ae_geant_a_sid: str, iptrunk_sideB_ae_geant_a_sid: str,
iptrunk_sideB_ae_members: list[str], iptrunk_sideB_ae_members: list[str],
iptrunk_sideB_ae_members_descriptions: list[str] iptrunk_sideB_ae_members_descriptions: list[str]
) -> State: ) -> State:
subscription.iptrunk.geant_s_sid = geant_s_sid subscription.iptrunk.geant_s_sid = geant_s_sid
subscription.iptrunk.iptrunk_description = iptrunk_description subscription.iptrunk.iptrunk_description = iptrunk_description
...@@ -125,7 +124,7 @@ def initialize_subscription( ...@@ -125,7 +124,7 @@ def initialize_subscription(
subscription.iptrunk.iptrunk_minimum_links = iptrunk_minimum_links subscription.iptrunk.iptrunk_minimum_links = iptrunk_minimum_links
subscription.iptrunk.iptrunk_sideA_node = Device.from_subscription( 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_iface = iptrunk_sideA_ae_iface
subscription.iptrunk.iptrunk_sideA_ae_geant_a_sid \ subscription.iptrunk.iptrunk_sideA_ae_geant_a_sid \
= iptrunk_sideA_ae_geant_a_sid = iptrunk_sideA_ae_geant_a_sid
...@@ -134,7 +133,7 @@ def initialize_subscription( ...@@ -134,7 +133,7 @@ def initialize_subscription(
= iptrunk_sideA_ae_members_descriptions = iptrunk_sideA_ae_members_descriptions
subscription.iptrunk.iptrunk_sideB_node = Device.from_subscription( 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 \ subscription.iptrunk.iptrunk_sideB_ae_iface \
= iptrunk_sideB_ae_iface = iptrunk_sideB_ae_iface
subscription.iptrunk.iptrunk_sideB_ae_geant_a_sid \ subscription.iptrunk.iptrunk_sideB_ae_geant_a_sid \
...@@ -143,105 +142,50 @@ def initialize_subscription( ...@@ -143,105 +142,50 @@ def initialize_subscription(
subscription.iptrunk.iptrunk_sideB_ae_members_description \ subscription.iptrunk.iptrunk_sideB_ae_members_description \
= iptrunk_sideB_ae_members_descriptions = iptrunk_sideB_ae_members_descriptions
subscription.description = f"Iptrunk {geant_s_sid}: \ subscription.description = f'IP trunk, geant_s_sid:{geant_s_sid}'
(blablabla)" subscription = IptrunkProvisioning.from_other_lifecycle(
subscription = iptrunk.IptrunkProvisioning.from_other_lifecycle(
subscription, SubscriptionLifecycle.PROVISIONING subscription, SubscriptionLifecycle.PROVISIONING
) )
return {"subscription": subscription} 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}
@inputstep("Confirm step", assignee="CHANGES") @step('Provision IP trunk [DRY RUN]')
def confirm_step() -> FormGenerator: def provision_ip_trunk_dry(subscription: IptrunkProvisioning,
class ConfirmForm(FormPage): process_id: UUIDstr) -> State:
confirm: Accept 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]") return {'subscription': subscription}
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}
@workflow( @workflow(
"Create Iptrunk", 'Create IP trunk',
initial_input_form=wrap_create_initial_input_form( initial_input_form=wrap_create_initial_input_form(
initial_input_form_generator), initial_input_form_generator),
target=Target.CREATE, target=Target.CREATE,
) )
def create_iptrunk(): def create_iptrunk():
return ( return (
init init
>> create_subscription >> create_subscription
>> store_process_subscription(Target.CREATE) >> store_process_subscription(Target.CREATE)
>> get_info_from_ipam >> get_info_from_ipam
>> initialize_subscription >> initialize_subscription
>> provision_iptrunk_dry >> provision_ip_trunk_dry
>> confirm_step >> await_pp_results
>> provision_iptrunk_real >> confirm_pp_results
>> set_status(SubscriptionLifecycle.ACTIVE) >> provision_ip_trunk_real
>> resync >> await_pp_results
>> done >> confirm_pp_results
>> set_status(SubscriptionLifecycle.ACTIVE)
>> resync
>> done
) )
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment