cuic-open-automation-dev-guide_v5.doc
DESCRIPTION
nmbmTRANSCRIPT
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
Document Number
Based on Template
Created By Cloupia Team
Cloupia UIC
Open Automation Developer GuideProduct Description
TEMECULA is the first Cisco release of the Cloupia Unified Infrastructure Controller. Cloupia Infrastructure controller (CUIC) is a datacenter infrastructure automation and management solution for FlexPOD, vSPEX and vBLOCK. CUIC provides a single pane of glass to manage compute, network, and storage and virtualization infrastructure.
ReviewersIt is the responsibility of the project team to determine the document reviewers and approvers. Once you have completed this document, it will require appropriate review and approval prior to use. Recommend reviewing EDCS -1161410 for guidance on review and approval.The departments and/or individuals listed above should be notified in advance and given a sufficient time period to review this document.
Modification HistoryModification history should be maintained for this document. EDCS maintains this history, the modification history table may be removed and the following note inserted where the table was. “For Modification History see EDCS.”
Revision Date Originator Comments0.1 3/13/2013 Parthasarathy
venkatavaradhanFirst Draft
0.2 3/19/2013 ParthasarathyVenkavaradhan
Added several sections describing the module, task, lists, tables etc.
After the requirement(s) have/has been documentent completely within the new document, the notes and coloring coding should be removed from the body of the document.
Copyright 2010 Cisco Systems 1Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
1 Overview
Cloupia UIC provides a rich set of functionality for Day1 and Day2 management of datacenter infrastructure. The abililty to create complex Infrastructure provisioning workflows with a simple drag-and-drop UI, has been the flaghship feature of CUIC since its first release. Though CUIC has tens of hundreds of built-in tasks that can be used for creating workflows, there are situations where the customer would want to extend the functionality and contribute tasks to the existing task library.
The ability to let developers contribute to Cloupia’s platform is made possible by Cloupia’s inherent modular architecture of the platform and its features. A developer can take advantage of this and provide customization and extension by adding several components to CUIC.
2 ScopeThis document covers description about how to develop a custom module using the Cloupia SDK.
3 Audience
This document is for Java developers who want to develop custom modules for extending the functionality of CUIC.
4 Setting up the Development Environment
4.1 Getting the latest CUIC SDKFor the time being, the CUIC SDK is available by request from Cloupia. It will be provided along with a code samples.
4.2 Setting up EclipseWe recommend using the Eclipse IDE for development, it can be downloaded from http://www.eclipse.org. You will also need a JRE (Java Runtime Environment) at version 1.6 or higher. Eclipse should be configured to compile against 1.6 level.
Copyright 2010 Cisco Systems 2Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
Make sure to include the CUIC SDK jars in your classpath. Ideally your project setup should mirror the setup we have provided in the CUIC SDK example.
4.3 Testing the setupThe simplest way to test your development environment is to import the sample SDK project into your workspace in Eclipse.
First, unzip the project zip somewhere in your file system. Launch Eclipse, once you are in Eclipse, go to File -> Import … Under General -> Existing Projects into Workspace, select Next. Select the option, “Select root directory” and point it to the location where you unzipped the project, then hit Finish. Everything should automatically compile without issue. You may or may not need to replace the CUIC SDKs under /open-auto-sdk/lib.
Please note that the samples provided are intended to work ONLY with the module.properties file it is bundled with. If you are using the sample project as a template for your own. Make sure to replace the module.properties file that Cloupia provides you. In addition, replace all the
Copyright 2010 Cisco Systems 3Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
sample classes as well with your own implementations. Otherwise you might run into some runtime exceptions preventing your module from being loaded.
4.4 Contact support [email protected]
5 Cloupia Dev Platform Architecture
Cloupia’s Platform architecture consists of two distinct components - the Cloupia Platform Runtime and the set of modules that gets executed on the platform. The platform itself provides necessary API’s and housekeeping functionality for the Modules so that the modules can perform the intended functions. The set of modules provide the necessary intelligence and features. The platform provides a loosely-coupled plugin architecture where modules can be developed, deployed and executed against the platform.
Copyright 2010 Cisco Systems 4Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Cloupia Platform Runtime
Object Store
Object Store AnnotationsAnnotations ListsLists TablesTables ConnectorsConnectors LogsLogs
ReportsReports WizardsWizards TasksTasks TriggersTriggers
Module 1 Module 2 Module 3 Module 4 Modul N
Cloupia UIC Logical Components
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
This document shall describe how to develop and deploy a module that can be executed on a Cloupia Platform runtime. The development of the platform itself is available only to Engineers working on the Cloupia UIC solution and not yet for others. For further questions, please contact [email protected] alias.
6 Module
A module is the top-most logical entry point into CUIC. To add or extend any functionality a module needs to be developed and deployed on the CUIC.
The following steps must be performed for developing and deploying a module :
Create a Module by implementing a Class that extends AbstractCloupiaModule
Create Tasks by implementing necessary Task interfaces
Package the module by running ANT
Deploy the package on a CUIC
These steps are explained below in detail:
6.1 Create a module
A module class extends AbstractCloupiaModule and provides implementation for the single method getTasks(). A sample implementation of the module is shown in Appendix B3. Here is a little more detail on the getTask() method. Refer to Section 9 for a more detailed walkthrough
on implementing your own tasks.
6.2 Publish the Module
In order to expose the module to the Platform Runtime, a file named module.properties is provided along with the module. This properties file defines certain properties of the module
Copyright 2010 Cisco Systems 5Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
/** * External modules extending this class shall provide implementation for
this method. * @return an array of tasks supported by this module */
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
itself. A sample properties file is available in Appendix B4. NOTE: A module.properties will be provided to you by Cloupia, which should never be altered by a developer. CUIC will validate the properties file to prevent tampering.
The contents include:
moduleID – Provides an unique readable string defining the feature
status – ‘Experimental’ or ‘Validated’. A developer version of the module is always ‘experimental’ whereas if the module is validated by Cloupia team then the status will be ‘validated’.
categoryID – A unique string to categorize the module’s tasks in.
categoryLabel – A user friendly string to accompany the categoryID.
org – Defines the name of the organization to which this module belongs to.
Sub-org – Defines the name of the sub-organization to which this module belongs to.
Feature – for future use.
Key – for future use.
6.3 Creating Tasks
Please refer to section titled ‘Understanding Module in detail’ below to know more about creating tasks.
6.4 Packaging the module
A module is packaged with all the necessary dependent jar files, classes, module.properties file alongwith a ‘.feature’ file. The ‘.feature’(pronounced as dot-feature) file is placed in the same folder as the root of the project. This file tells the JAR associated with this module and the path to the dependent JAR files. Please refer to Appendix B5 for a sample .feature file.
Copyright 2010 Cisco Systems 6Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
From the build.xml, run the ANT target ‘build’ which will generate the necessary ZIP file and save it to the base directory of your project.
If your module is dependent on jars not provided with the sample source code, you will need to make sure to include them in the build.xml so they will be included in the zip. Here is an example of how a module layout containing a third party jar would look like:
Note that the module jar and .feature are at the top level of the zip. Then you have your third party jars under /moduleID/lib/. Although not necessary it is best practice to place your third party jars under /moduleID/lib, then any other sub directories you may want to add.
The corresponding .feature file will look like this:
Note that references to the jar files always start with “features/”, this is mandatory. In your .feature file when you list out the jars, it should always start with features/, then you can include the path to the jar you want. The path of each jar should be same as it is in your zip file. It is also best practice to lead with your module jar then its dependencies, so you ensure your module gets loaded.
6.5 Deploying the module on CUIC
CUIC has the following screen to upload and manage modules. Use this to upload the ZIP file to CUIC.
The path for managing the modules in CUIC is located at
Administration System Administration Open Automation
Copyright 2010 Cisco Systems 7Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
Add Module
Select the action button to add a new module.The the following UI form opens up to upload a new module.
Provide the module name and module description and upload the module zip file and submit the form.
Note: For the newly added module to be loaded , the module need to be made active and CUIC services need to be restarted after upload.
Activate Module
To activate a module select the module in the Modules tabular report and click action button on the tabular report
The following for pops up.
Click Submit to activate the module.
Deactivate Module
To deactivate a module select the module in the Modules tabular report and click action button on the tabular report
The following for pops up.
Copyright 2010 Cisco Systems 8Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
Click Submit to activate the module. Once the module is deactivated to unload the module need to restart the CUIC services.
Modify Module
To modify a module select the module from the Modules tabular report and click action button.
The following form pops up.
We can upload new module zip file and also change the module description.
We need to stop start CUIC services to unload the already loaded module and reload the new module.
7 Creating a new moduleThe first step in creating a module is to extend AbstractCloupiaModule, refer to FooModule in the sample project. When extending AbstractCloupiaModule you must implement the getTasks method.
You will also need to provide a .feature file, this file MUST end with an extension of “.feature”, take a look at foo.feature for reference. It is best practice to name this file with your Cloupia supplied module ID. Refer to section 6.4 for more details about the .feature file.
Copyright 2010 Cisco Systems 9Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
As mentioned previously, Cloupia provides you with a properties file for validation purposes. This properties MUST be packaged at the root level of your module jar. The SDK example provides you with a build file that handles the packaging process.
So in summary, there are 3 required items that need to be in place for your custom module to work.
1. A class extending AbstractCloupiaModule.
2. A .feature file specifying your dependent jars and module class.
3. A jar containing your compiled classes with the Cloupia provided properties file.
8 Understanding a Module in detail
A module can consists of the following components:
Reports – These are reports that get shown in the UI. Reports may or may not contain action buttons.
Wizards – A wizard is a user interface component to get inputs from the user to perform certain action or actions.
Task – A task in this context is a Workflow Task that can be used while defining a Workflow.
Trigger – A trigger is a condition once satisfied can be associated with some action. Example : shutdown VM, start VM etc.
Each of the above major components shall make use of one or more of the following sub-components:
Object Store
Annotations
Lists
Tables
Connectors
Logs
8.1 Object Store
Object Store component provides simple API’s for database persistence. A module that wants to persist objects into the database shall primarily make use of the Object Store APIs to perform all
Copyright 2010 Cisco Systems 10Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
the CRUD operations. CUIC uses MySQL as its database. The platform runtime makes use of Java Data Object(JDO) library provided by DataNucleus to abstract all the SQL operations through and Object Query representation. This simplifies and speeds up the development in terms of data persistence. The section shows how CRUD operations are realized using JDO.
8.1.1 Marking a Class for Persistence
The POJO class that needs to be persisted in the database has to be defined and marked with suitable JDO annotations. The following class is marked for JDO persistence:
package com.cloupia.lib.cIaaS.netapp.model;
@PersistenceCapable(detachable = "true", table = “foo_netapp_filer”)
public class NetAppFiler
{
@Persistent
private String filerName;
@Persistent
private String accountName;
@Persistent
private String dcName;
}
The above class is annotated with two annotations – @PersistenceCapable and @Persistent. These are defined in the JDO and CUIC Platform runtime expects that all persistent classes be marked with these two annotations. CUIC uses a flat schema and hence creating of a nested schema, though possible and allowed in JDO, is not recommended in a Cloupia Module.
8.1.2 Publishing the Persistence Class
A class that is marked with suitable JDO annotation has to be published so that the Cloupia Platform Runtime can pick up the class. The following need to be done to publish a persistence class:
Copyright 2010 Cisco Systems 11Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Attached on top of the class declaration. ‘table’ attribute
specifies the name of the table to be used. ‘foo’ is the name of the module and the rest of the string
can be arbitrary.
Attached on top of the class declaration. ‘table’ attribute
specifies the name of the table to be used. ‘foo’ is the name of the module and the rest of the string
can be arbitrary.
Attached to the field that needs
persistence
Attached to the field that needs
persistence
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
Create a file with the name jdo.files in the same directory (package) as that of the persistence class and add the name of the class to the file as follows:
Linux# cat jdo.files
// Copyright (C) 2010 Cisco Inc. All rights reserved.// // Note: all blank lines and lines that start with // are ignored// // Each package that has Persistable Objects shall have a file called jdo.files// Each line here indicates one class that represents a persistable object.// // Any line that starts with a + means package name is relative to current package// If a line starts without +, then it must be complete fully qualified java class name // (for example: com.cloupia.lib.xyz.MyClass)
+NetAppFiler
Linux#
8.1.3 Performing CRUD Operations on the Persistence Class
The persistence class is now ready for CRUD operations against the Database. Following samples show how to perform different operations:
8.1.3.1 Create a new instance of the object
NetAppFiler filer = new NetAppFiler(); filer.setAccountName("netapp-account"); filer.setDcName("Default Datacenter"); filer.setfilerName("filer0"); filer.setIpAddress("192.168.0.1"); ObjStore store = (NetAppFiler) ObjStoreHelper.getStore(NetAppFiler.class); store.insert(filer);
8.1.3.2 Modify a single instance of the object
ObjStore store = (NetAppFiler) ObjStoreHelper.getStore(NetAppFiler.class);
Copyright 2010 Cisco Systems 12Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
String query = "filerName == 'filer0'"; //Use Java field names as parameter, // can use && , || operators in the query.
store.modifySingleObject(query, filer);
8.1.3.3 Querying all the instances from the DB
ObjStore store = (NetAppFiler) ObjStoreHelper.getStore(NetAppFiler.class);
List<NetAppFiler> filerList = store.queryAll();
8.1.3.4 Querying the instances with a filer query
ObjStore store = (NetAppFiler) ObjStoreHelper.getStore(NetAppFiler.class);
String query = "dcName == 'Default Datacenter'";List<NetAppFiler> filerList = store.query(query);
8.2 Annotations
Annotations are one of the most important part of Cloupia Module development. Most of the artifacts are driven by annotations. This makes the development effort all the more easy and convenient.
Annotations are used for persistence, report generation, wizard generation and tasks.
8.2.1 Persistence Annotations
Please refer to the section on ‘Marking a Class for Persistence’ that talks in detail about the annotations that are used for persistence.
Copyright 2010 Cisco Systems 13Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
8.2.2 Task Annotation
When a task is included in a Workflow, certain inputs are prompted from the user. These inputs are prompted based on which fields of the class representing the task is marked with annotations. What type of UI input field to show to the user, example : to show a text field, or a dropdown list or a checkbox is all determined through the ‘FormField’ annotation. Please refer to the section titled ‘Defining the inputs to a Task’ for more details.
8.3 Lists
Lists represent the drop-down list shown to the user to get inputs for a task. Developers can re-use an existing list or create their own list to show in the Task UI.
8.3.1 Showing an existing List
Cloupia UIC defines around 50+ pre-built List providers that can be readily used by the modules to prompt input from the user. This list is available in Appendix ‘A’ of this document.
For example on how to use one of the list providers, please refer to the section on ‘Tasks’.
8.3.2 Defining your own List provider
Developers can define their own list provider and ask the Platform runtime to register it with the system.
A list provider class shall implement the ‘LOVProviderIf’ interface and provide implementation for the single method getLOVs();
class MyListProvider implements LOVProviderIf{
/** * returns array of FormLOVPair objects. This array is what is shown in a
dropdown list. * a FormLOVPair object has a name and a label. While the lable is shown to the
user * name will be used for uniqueness . */@Override
Copyright 2010 Cisco Systems 14Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
public FormLOVPair[] getLOVs(WizardSession session) {
// Simple case showing hard-coded list values
FormLOVPair http = new FormLOVPair("http", "HTTP"); // http is the name, HTTP is the label
FormLOVPair https = new FormLOVPair("https", "HTTPs");
FormLOVPair[] pairs = new FormLOVPair[2];pairs[0] = http;pairs[1] = https;return pairs;
}}
A complex LOVProvider is also possible where the values are retrieved from the devices are from the database using the ObjStore.
8.4 Tables
Please refer to Appendix ‘A’ to use some of the already existing tabular report for user selection.
8.5 Tasks
Workflow Tasks provide the necessary artifacts to contribute to the Task library maintained by the Cloupia UIC. The task can then be used in a Workflow definition.
8.5.1 Contents of a Task
At the minimum a task should have the following classes:
A class that implements TaskConfigIf interface
A class that extends and implements methods in AbstractTask class
8.5.1.1 TaskConfigIf
A class that implements this interface will become a Task’s input. In other words, a task that wants to accept inputs for its execution shall depend on a class that implements TaskConfigIf. The class that implements this interface shall also contain all the input field definition suitable
Copyright 2010 Cisco Systems 15Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
annotated for prompting the user. The class should also have JDO annotations to enable the Platform runtime to persist this object in the database.
A sample Config class is shown in Appendix B1:
8.5.1.2 AbstractTask
A task implementation shall extend the AbstractTask abstract class and shall provide implementation for all the abstract methods. This shall be the main class where all the business logic pertaining to the task go. The most important method in this class where the business logic implementation will be scripted is executeCustomAction(). Rest of the methods provide suitable context to the Platform runtime so that the task appears in the Orchestration designer tree and that it can be dragged and dropped in a Workflow.
A sample AbstractTask implementation is shown in Appendix B2.
8.6 Reports, Wizards & Triggers
Reports, Wizards and Triggers will not be discussed in this document as these are not yet opened up for development from outside CUIC team. However, this document shall outline the details regarding development of tasks in a module.
9 Adding a new Workflow Task to the module
9.1 Defining a TaskAs mentioned in section 8.5.1, a task is composed of implementations of TaskConfigIf and AbstarctTask. The former is used to specify all the data you need, and the latter is where you execute all your logic given that data.
The following sections will be a walkthrough demonstrating where to start developing a task and important side notes.
.
9.2 Developing a TaskConfigIfThe first thing to do when developing a task is to implement TaskConfigIf. You need to figure out what data you will need to perform your task. We will take a look at the EnableSNMPConfig in detail. So in this example, the Enable SNMP task is designed to enable
Copyright 2010 Cisco Systems 16Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
snmp on a nexus device. For my purposes, I will need the IP address of the device, the login and password.
The first thing you will see at the beginning of EnableSNMPConfig is the annotation.
You must provide a PersistenceCapable annotation with a table name that is prefixed with your module ID. It is very important that you follow this convention, CUIC will prevent a task from being registered if you try to use a table name not prefixed your module ID. This is in place to prevent developers from accidentally interfering with existing CUIC tables.
Next, you’ll see a couple of fields.
The handler name is just the name of the task, it should be a unique string, you may run into issues if you use the same name throughout multiple tasks.
Every task will need to have a configEntryId and actionId, exactly as shown above. You will need corresponding getter and setters for these two fields. These two fields are absolutely mandatory, you will need to make sure you have these in your config object.
Next you’ll see the data we actually need to perform our task.
So we needed the IP address of the device, in this example, we are using a LOV to get that, refer to section 8.2 for more detail about LOVs. You may also note in this example, the user input field annotation, which we will go discuss more in later sections. We also needed the login and password, that will need to entered in by the user. So we use the form field annotations to mark these fields as data that will come in for the user. You will also need accompanying getters and
Copyright 2010 Cisco Systems 17Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
setters for each of these fields. With that we have declared all the data we need in our config object.
Once your config object is completed, you will need to mark it for JDO enhancement. This is done by including a “jdo.files” file in the same package of your config objects. Take a look at the “jdo.files” in the SDK example. In the “jdo.files” (must be named exactly like this), you specify all the classes that need to go through JDO enhancement. This will be taken care of for you if you use the SDK supplied build script assuming you have followed this step properly.
The handler object is where you actually execute your custom code. A handler object must implement CustomActionHandlerIf. The executCustomAction method is where you can retrieve the corresponding config object you developed previously for use to execute your code.
9.3 Developing a AbstractTaskOnce your config object is ready, then you will need to extend AbstractTask to actually use the config. We will take a look at EnableSNMPTask to get a better idea on what is happening in a task.
The most important method to look at is executeCustomAction.
executeCustomAction is where all your custom logic takes place. The first thing worth noting is how you retrieve your config object. When you call context.loadConfigObject() you can cast it to the config object you defined earlier. This allows you to retrieve all the details you need to perform your task. In this example, after I get the config object, I use the SSH utilities we provide to execute the enable snmp commands (Refer to sample code itself).
Something you may also note is the use of change tracker. When a workflow is rollbacked, a task must provide a way to undo the changes it has made.
In this line of code here, I’m basically informing the system that the undo task of my Enable SNMP task is this Disable SNMP task. All you really need to do is provide the undo config object and its name, (the rest of the arguments are mostly just logging data, which you may or may not want to provide). Note the DisableConfig actually takes in the EnableConfig, the reason for this is because you may want the details of the task you are undoing. In my case, the enable config contains the device details, so when the Disable SNMP task is called I will know specifically which device to disable snmp on.
You will also need to make sure to implement getTaskConfigImplementation.
Copyright 2010 Cisco Systems 18Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
As you can see here, we are just instantiating an instance of our config object in returning it. The most important thing about this method is just to make sure you are specifying the config object you intend to use with this task.
After this, all you need to do is to include this task in your module and it will be ready for use in CUIC.
9.4 Registering Custom Workflow InputsIn section 9.2, there was an additional annotation used to specify a custom workflow input.
You can develop your own input types in CUIC. However, you need to make sure they are prefixed with your module ID. So in this example, ModuleConstants.NEXUS_DEVICE_LIST actually resolves to “foo_nexus_device_list”.
The custom inputs registered will be available in the Workflow inputs table that appears in the second page of Workflow creation in the UI.
Copyright 2010 Cisco Systems 19Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
@UserInputField(type = ModuleConstants.NEXUS_DEVICE_LIST)
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
We can add as workflow input and map the input to the task having same input type as show below for the Enable SNMP Task.
The input will be taken when the workflow is executed and the same will be passed to the task as show below.
9.5 Registering Custom Task OutputsPlease refer to EmailDatacentersTask for better understanding as to how to create custom task outputs. For a task to add an output it need to do the following
1. Create a output definition
2. Need to implement the method getTaskoutputDefinitions() method int the task implementation and return the output definitions that the task is suppose to return.
Copyright 2010 Cisco Systems 20Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
3. Need to set the output from the task implementation.
The outputs associated with the task can be seen in the first screen of the task definition in the UI.
9.6 Testing the TaskAssuming your module is working properly. You should see your tasks coming in through task library like so.
Copyright 2010 Cisco Systems 21Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
10 Caveats
11 Support
12 Reference
13
Appendix A
ListProvider Name Description------------------------------------------ ----------------------- vdiMcsCatalogAllocationTypeList VDI MCS Catalog Allocation Type Selector netAppClusterPortAssIfGroupProvider NetApp Cluster Port Associated IfGroup Selector catalogList Catalog Selector DiskSizesList Disk Size Selector vdcProfileList vDC Profile Selector vmwareCloudNamesList VMware Account Selector protocolList NetApp vFiler Protocol List MemorySizesList Memory Size Selector vdiVdcList VDI VDC Selector emcRAIDTypesListProvider EMC RAID Type Selector portGroupTypeList VMware Portgroup Type ucsNetworkPolicyList UCS Network Policy iGroupTypeList NetApp Initiator Group Type vdiCatalogList VDI Catalog Selector hpServerBootActionTypes HP Boot Mode netappAllClusterAssocNonAssocIfGroupList NetApp Cluster All IfGroup Selector
Copyright 2010 Cisco Systems 22Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
dfmStorageServiceList NetApp OnCommand Storage Services NetworkDevicePortProfileModeList Networking Port Profile Mode ucsServiceProfileList UCS Service Profile Selector hostNodeList Host Node Selector vdiMcsCatalogTypeList VDI MCS Catalog Type Selector netappAllClusterVLANList NetApp Cluster vLAN Selector vdcList vDC Selector netappAllClusterAggrList NetApp Cluster Aggregate Selector NetworkDeviceBasicList Networking Device netappAllClusterPortList NetApp Cluster Port Selector MSPGroupList MSP Group sizeUnitList NetApp Size Units amazonVMList Amazon VM Selector ec2AccountList Amazon Cloud Selector ucsBladeList UCS Server emcSizeUnits EMC Size Units vdiMemorySizesList VDI Memory Size Selector VMwareDVSUplinkPortgroupList VMware DVSwitch Uplink Portgroup hpServerAutoPowerActionTypes HP Auto Power Mode hpServerBootSourceAction HP Boot Source hpServerPowerSaverActionTypes HP Power Saver Mode osTypeList NetApp OS Type vdiCPUsList VDI CPU Selector vscResizeDatastoreList NetApp VSC Resize Datastore Selector UcsAccountList UCS Account containerProvider Service Container amazonVMActions Generic VM Action Selector dfmGroupList NetApp OnCommand Groups hpServerPowerActionTypes HP Server Power Mode kvmVMActions KVM VM Action Selector netappAllClusterNodeList NetApp Cluster Node Selector vdiAccountList VDI Account Selector NetworkDevicePortProfileTypeList Networking Port Profile Type ec2VolumeSizeList EC2 Volume Size Selector vCPUsList vCPU Selector userGroupsLOV User Group vmwarePortGroupLoVProvider VMware Port Group
kvmVMList KVM VM Selector
APPENDIX B1
Class showing a sample implementation of TaskConfigIf
@PersistenceCapable(detachable = "true", table = "foo_enable_snmp_config")public class EnableSNMPConfig implements TaskConfigIf{
public static final String HANDLER_NAME = "Enable SNMP for Nexus";
//configEntryId and actionId are mandatory fields@Persistent
private long configEntryId; @Persistent private long actionId; //this is the ip address to the nexus device you want to enable snmp on
Copyright 2010 Cisco Systems 23Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
@FormField(label = "Host IP Address", help = "Host IP Address", mandatory = true, type = FormFieldDefinition.FIELD_TYPE_EMBEDDED_LOV, lovProvider = ModuleConstants.NEXUS_DEVICES_LOV_PROVIDER) @UserInputField(type = ModuleConstants.NEXUS_DEVICE_LIST) @Persistent private String ipAddress = ""; @FormField(label = "Login", help = "Login", mandatory = true) @Persistent private String login;
Update the getters and setters so that they return actionid and configEntryId for the return values @FormField(label = "Password", help = "Password", mandatory = true, type = FormFieldDefinition.FIELD_TYPE_PASSWORD) @Persistent private String password;
// Getters and setters are removed for brevity}
APPENDIX B2
A Task implementation Class example.
public class EnableSNMPTask extends AbstractTask
{
static Logger logger = Logger.getLogger(EnableSNMPTask.class);
public void executeCustomAction(CustomActionTriggerContext context, CustomActionLogger actionLogger) throws Exception
{
long configEntryId = context.getConfigEntry().getConfigEntryId();
//retrieving the corresponding config object for this handler
EnableSNMPConfig config = (EnableSNMPConfig) context.loadConfigObject();
Copyright 2010 Cisco Systems 24Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
if (config == null)
{
throw new Exception("No enable snmp configuration found for custom action " + context.getActionDef().getName()
+ " entryId " + configEntryId);
}
//create a ssh client with the provided credentials
SSHClient client = new SSHClient(config.getIpAddress(), 22, config.getLogin(), config.getPassword());
try {
logger.info("CONNECTING TO " + config.getIpAddress());
//mandatory step: connect to the device
client.connect();
//open a session
SshSession session = client.openShell(511, 25);
//cache the session's output stream, you use this to send commands to the device
OutputStream out = session.getOutputStream();
PrintWriter pw = new PrintWriter(out, true);
//WARNING: THIS IS SPECIFIC TO NEXUS DEVICES!!! DON'T USE THIS FOR ANYTHING ELSE!!
//wait until login is complete before executing commands
//this is a hacky way to determine when the terminal is ready for input,
//this loop is reading the output from the terminal and spinning until it sees the last line
//of the intro message has been printed
logger.info("---- WAITING FOR TERMINAL TO BE READY ----");
StringBuffer sb = new StringBuffer();
while (sb.indexOf("http://www.opensource.org/licenses/lgpl-2.1.php") != -1) {
byte[] buffer = new byte[4096];
int n;
InputStream in = session.getInputStream();
while ((n = in.read(buffer)) >= 0)
{
sb.append(new String(buffer, 0, n));
Thread.sleep(10L);
}
Copyright 2010 Cisco Systems 25Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
}
logger.info("... TERMINAL READY FOR INPUT ...");
//this terminal is now ready for input, but i'm gonna wait a second just to make sure ...
Thread.sleep(1000L);
//go into config mode, then add enable snmp on community string "whitney"
pw.print("conf t \nsnmp-server community whitney ro\n");
pw.flush();
logger.info("... ENABLE SNMP COMMAND EXECUTED ...");
//wait for another 2.5 seconds just to make sure everything is clean
Thread.sleep(2500L);
//make sure to disconnect from the device for proper clean up
client.disconnect();
actionLogger.addInfo("SNMP enabled on " + config.getIpAddress());
//if user decides to rollback a workflow containing this task, then using the change tracker
//we can take care of rolling back this task (i.e, disabling snmp)
context.getChangeTracker().undoableResourceAdded("assetType", "idString", "SNMP enabled",
"SNMP enabled on " + config.getIpAddress(), DisableSNMPConfig.HANDLER_NAME, new DisableSNMPConfig(config));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
actionLogger.addWarning("Action " + EnableSNMPConfig.HANDLER_NAME + ":" + e.getMessage());
}
}
Copyright 2010 Cisco Systems 26Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
@Override
public WorkFlowStep redfineWorkFlowStep(CustomActionTriggerContext context) throws Exception
{
// TODO Auto-generated method stub
return null;
}
@Override
public String getTaskName() {
return EnableSNMPConfig.HANDLER_NAME;
}
Provide more details as to how to define task output using TaskOutputDefinition
@Override
public TaskOutputDefinition[] getTaskOutputDefinitions() {
return null;
}
@Override
public TaskConfigIf getTaskConfigImplementation() {
return new EnableSNMPConfig();
}
}
APPENDIX B3
A sample implementation of Module
public class FooModule extends AbstractCloupiaModule{
@Overridepublic AbstractTask[] getTasks() {
AbstractTask task1 = new EnableSNMPHandler();AbstractTask task2 = new DisableSNMPHandler();AbstractTask[] tasks = new AbstractTask[2];tasks[0] = task1;tasks[1] = task2;return tasks;
Copyright 2010 Cisco Systems 27Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.
Date printed: 4/17/2023<Project Name> Product Requirements Document: EDCS-XXXXXX
}
}
APPENDIX B4A sample module.properties file
featureID=oabcstatus=experimentalorg=ciscosuborg=cloupiafeature=somethingkey=abcdef
APPENDIX B5
A sample .feature file. The name of the file will be <moduleID>-module.feature{
jars: [ "features/feature-chargeback.jar", "features/chargeback/activation-1.1.jar", "features/chargeback/axis2-jaxbri-1.5.6.jar", "features/chargeback/bcel-5.1.jar", "features/chargeback/jalopy-1.5rc3.jar", "features/chargeback/neethi-2.0.5.jar", "features/chargeback/antlr-2.7.7.jar", "features/chargeback/axis2-jaxws-1.5.6.jar",] features: [ "com.cloupia.feature.oabc.OABCModule" ]}
Copyright 2010 Cisco Systems 28Company Highly Confidential - Controlled Access
A printed copy of this document is considered uncontrolled. Refer to the online version for the controlled revision.