Cisco Intersight API – Trigger workflows

With Intersight there’s a tool called Intersight Cloud Orchestrator (ICO) that allows to automate complex multi-cloud workflows. While ICO provides a great frontend to automation administrators it’s not a natural fit for developers who want to use these workflows.

A good example for a complex would be the creation of a full-stack environment in the datacenter to run union and acceptance tests before releasing an application.

So the question is: How can you trigger these workflows to deploy the application without using a manual GUI?

And the answer is quite easy: Use the Intersight API to trigger these complex workflows!

Using the Intersight API allows you to abstract your development workflows from the infrastructure while being compliant in terms of datacenter deployments and security (you basically use what administrators have approved already). You just have to understand how to use the API and how to design the payload to trigger these workflows.

First of all you need an API key that can be generated for you and will handle the authentication and authorization for you. These API keys can be easily generated in the user interface:

Just save the API Key ID and the Secret Key as environment variables and you can start immediately using the credentials.py helper that is provided in the official Cisco DevNet repository.

Now that you have the basic authentication it’s time to get the workflow we want to trigger in this scenario. I will use a workflow that executes a Cisco WebEx Bot message because it is easier to understand the JSON payload objects. To find the workflow you want to trigger you have to get all of them with an easy python script (get_workflows.py):

import intersight.api.workflow_api
import credentials

wf_name = "Send Message to Webex Teams"

def get_workflows(apiClient):
    api_instance = intersight.api.workflow_api.WorkflowApi(apiClient)
    workflows = api_instance.get_workflow_workflow_info_list()
    for i in workflows.results:
        if i.name == wf_name:
            print("Name: " + i.name)
            print("Workflow Info MoId: " + i.moid)
            print("Status: " + i.status)
            print("Workflow Definition MoId: " + i.workflow_definition['moid'])
            get_workflow_inputs(apiClient,i.workflow_definition['moid'])

def get_workflow_inputs(apiClient,moId):
    api_instance = intersight.api.workflow_api.WorkflowApi(apiClient)
    workflows = api_instance.get_workflow_workflow_definition_by_moid(moId)
    for k in workflows.permission_resources:
        print("Organization MoId: " + k.moid)
    for i in workflows.input_definition:
        print("Input name: " + i.name)
        print("Input type: " + i.properties['type'])

def main():
    apiClient = credentials.config_credentials()
    try:
        get_workflows(apiClient)
    except intersight.OpenApiException as e:
        print(e)

if __name__ == "__main__":
    main()

As you can see, it uses the credentials helper and after creating an instance of the class apiClient you will be able to call api_instance.get_workflow_workflow_info_list() which gives you all the workflows runs but not the workflow definition.

With an iteration over the results it’s easy to get the name, status and MoId of the existing runs (get_workflows) as well as the MoId of the workflow definition that can give us the input values (get_workflow_inputs).

While the response looks like JSON it is a structured data type (WorkflowWorkflowInfo) which isn’t serializable via json.dumps() so you would need something like this. For the purpose of this litte demo we will just use a simple iteration.

Now that we got all the values we need to execute a workflow it’s time to create another python script (execute_workflow.py)

#!/usr/bin/env python
import intersight
import intersight.api.workflow_api
import credentials
from intersight.api.workflow_api import WorkflowApi
from intersight.model.workflow_workflow_info import WorkflowWorkflowInfo
from intersight.model.mo_base_mo_relationship import MoBaseMoRelationship
from intersight.model.workflow_initiator_context import WorkflowInitiatorContext
from intersight.model.workflow_workflow_definition_relationship import WorkflowWorkflowDefinitionRelationship
from pprint import pprint

moId = "62017e58696f6e2d338f918cc"

mo = WorkflowWorkflowInfo(
    action="Start",
    associated_object=MoBaseMoRelationship(
        class_id="mo.MoRef",
        moid="5ddea9626972652d32b67d21",
        object_type="organization.Organization"
    ),
    input={
        "EmailAddress": "cjohanns@cisco.com",
        "MessageContents": "Test from a python script... Cheers"},
    name="Send Message to Webex Teams",
    workflow_definition=WorkflowWorkflowDefinitionRelationship(
        class_id="mo.MoRef",
        moid="61b81012696f6e2d33259fba",
        object_type="workflow.WorkflowDefinition"
    )
)

def create_workflow_workflow_info(apiClient,mo):
    print("Email address: "+mo.input['EmailAddress'])
    api_instance = intersight.api.workflow_api.WorkflowApi(apiClient)
    workflow = api_instance.create_workflow_workflow_info(mo)

def main():
    apiClient = credentials.config_credentials()
    try:
        create_workflow_workflow_info(apiClient,mo)
    except intersight.OpenApiException as e:
        print(e)

if __name__ == "__main__":
    main()

Beside the MoId there’s also the payload (WorkflowWorkflowInfo object) for the POST request that we need to define. We will execute create_workflow_workflow_info() which it the update (or POST) definition in the API documentation.

The WorkflowWorkflowInfo object just needs a few mandatory attributes like action, organization MoId and input values and the WorkflowWorkflowDefinition relationship MoId. These values are the result of the get_workflows.py script we executed before.

After the payload is constructed we can confirm a test value like the email address before executing the POST.

This execution leads to a bot message in WebEx that shows the text we added as a message content.

This should give you a pretty good idea how Intersight Orchestrator workflows can be executed from other automation and orchestration systems as well as you own frontend application. While we used simple string inputs there might be other objects that need a specific data type.

Thanks to Cisco’s Vikrant Balyan for helping me with the creation of the payload and WorkflowWorkflowInfo object!

Please note that when there’s no execution of the workflow you want to trigger you will get an empty result! The GitHub repository can be found here.

Leave a Reply