Skip to content

Product and Workflow Generator

To create a new product configuration and wire up the python, database and workflows correctly you need to create a lot of boilerplate configuration and code. To speed up this process and make the experience as user friendly as possible, initial configuration of what a product looks like can be created with a yaml file.

At the end of these steps the developer will have all the necessary configuration and boilerplate completed to run the workflow and start developing on implementing the business logic.

Step 1 - Create the product configuration file

Open the Example Orchestrator directory and list the templates directory. It should look similar to this:

 ls -l templates
total 32
-rw-r--r--  1 boers001  staff  2687 Mar  7 11:28 core_link.yaml
-rw-r--r--  1 boers001  staff  2052 Mar  7 11:28 l2vpn.yaml
-rw-r--r--  1 boers001  staff  2575 Mar  7 11:28 node.yaml
-rw-r--r--  1 boers001  staff  2444 Mar  7 11:28 port.yaml

This directory houses all the configuration of the initial products that the example orchestrator provides. It is a starting point for developing new products.

Create a new file in the template directory called l2_p2p.yaml:

touch templates/l2_p2p.yaml

In this workshop we will generate the L2-Point-to-Point model and workflows by configuring it with this yaml file.

Step 2 - Configure the YAML

This file will contain the Initial product type configuration. Please create a yaml configuration reflecting the product model as described on the previous page. The goal is to configure the generator to reuse as many of the product blocks already existing in the orchestrator as possible.

Take a look at the l2vpn.yaml model for inspiration. As you can see, this file has been configured in a certain way to reflect the configuration of the product. For more in depth documentation about generate take a look at the reference doc.

Answer - l2_p2p.yaml

When creating the YAML you should notice that you do not have to create the SAP product blocks again. You just have reference the SAP in the Virtual Circuit configuration. In this way you start reusing existing building blocks that already exist in the orchestrator. We cannot reuse the existing Virtual Circuit with the generator due to the different limits on the amount of SAPS that can be connected to the Virtual Circuit of the L2 P2P product.

config:
  summary_forms: true
name: l2_p2p
type: L2p2p
tag: L2P2P
description: "L2 Point-to-Point"
fixed_inputs:
  - name: protection_type
    type: enum
    enum_type: str
    values:
      - protected
      - unprotected
    description: "Level of network redundancy"
product_blocks:
  - name: l2_p2p_virtual_circuit
    type: L2p2pVirtualCircuit
    tag: VC
    description: "virtual circuit product block"
    fields:
      - name: saps
        type: list
        description: "Virtual circuit service access points"
        list_type: SAP
        min_items: 2
        max_items: 2
        required: provisioning
      - name: speed
        description: "speed of the L2VPN in Mbit/s"
        type: int
        required: provisioning
        modifiable:
      - name: speed_policer
        description: "speed policer active?"
        type: bool
        required: provisioning
        modifiable:
      - name: ims_id
        description: "ID of the L2VPN in the inventory management system"
        type: int
        required: active
      - name: nrm_id
        type: int
        description: "ID of the L2VPN in the network resource manager"
        required: active

Step 3 - Run the generator functions

To help generate the correct file exec into the running container and activate the Python venv:

docker compose exec -it orchestrator bash
source .venv/bin/activate

What can I do when I encounter errors?

If you want to start over, use git restore . and git clean -id from your example-orchestrator directory to undo changes.

Product Blocks

Run the command to generate the domain models product blocks:

python main.py generate product-blocks -cf templates/l2_p2p.yaml --no-dryrun

The --no-dryrun option will immediately write the files to the products/product_blocks folder and create: l2_p2p_sap.py and l2_p2p_virtual_circuit.py. This file contains the product block configuration for the l2-p2p product and defines the strict hierarchy of virtual circuit and saps.

Product

Now create the product.

python main.py generate product -cf templates/l2_p2p.yaml --no-dryrun

This will create the file products/product_types/l2_p2p.py. When looking at this file you can see it created the domain model, fixed inputs and imported the correct product blocks to be used in this subscription.

Workflows

Now generate the workflows. This command will always create 4 sets of workflows create, modify, terminate and validate. These can be implemented as the user sees fit.

Run the command:

python main.py generate workflows -cf templates/l2_p2p.yaml --no-dryrun

As you can see this file needs to be run with the –force flag as it needs to overwrite a number of configuration files. Furthermore it will populate the files in workflows/l2_p2p/. Do that now:

python main.py generate workflows -cf templates/l2_p2p.yaml --no-dryrun --force

Warning

There is a bug in generate workflows which makes it overwrite the contents of workflows/shared.py instead of extend it with the missing elements. You can use git restore to restore it aftwards.

Take a look around to see which files have been created by now. Can you explain what each of them are for?

Database migrations

As a final step the user must generate and run the migrations to wire up the database. This is done as follows.

python main.py generate migration -cf templates/l2_p2p.yaml
python main.py db upgrade heads

Step 4 - Profit

If this has been executed without errors, you should see the option l2_p2p protected and l2_p2p unprotected appear in the New subscription menu, as well as in the Metadata pages. Select either product, and try to fill in the form. There is a small quirk with one of the fields, which has been left in as an exercise to understand the interaction between the workflow form and the UI.

Once you submit the form you’ll notice that creating the subscription does not work right away, as the “initial_input_form_generator” still needs to be extended with a field to select Port subscriptions for the SAPs, and the “construct_l2_p2p_model” step will need to be updated accordingly. This is out of scope for the workshop.

But this should give you an idea how the generator gives users a head start by setting up a product and workflows according to the best practices. They can then go into the workflow source code and start implementing steps to provision the resource that is being created by the create workflow.

Step 5 - Bonus

Add a new step in the create_l2_p2p workflow that manipulates the subscription in a certain way. An example could be to change the subscription description, or any other value you can think of that exists in the subscription.

Answer
@step("Update Subscription Description")
def update(subscription: L2p2pProvisioning) -> State:
    subscription.description = "My Awesome L2P2P"
    return state | {"subscription": subscription}