Latest Headlines
0

Secret(?) #vCO Tips for #VMworld 2012

VMworld 2012 is coming (in fact, I’m writing this post on the plane to San Francisco  8-) ).

This year there will be a lot of great content about the Orchestrator, see this article on the official VMware Orchestrator Blog:
http://blogs.vmware.com/orchestrator/tag/vmworld-vco-vcenter-orchestrator-orchestration-breakout-sessions-plug-ins-vmware-f5-networks-infoblox-radware-vce-emc

About and in addition to these promising sessions, I have some “secret” special tips for you:

The #vBrownBag TechTalks

In the Communites/Blogger Lounge a bunch of lightning talks will be hosted, including some sessions about vCO:

See the complete agenda and the scheduling here:
http://www.virtualnetworkdesign.com/2012/08/20/techtalks-powered-by-vbrownbags-the-topics/
OPS-CIM1274 – Building Cloud Services using VMware vCenter Orchestrator

I want to highlight this session, because: It is a Panel Session, Thomas Corfmat and Igor Stoyanov from VMware discuss and demonstrate Orchestrator use-cases with Sean Harrison (Nothrop Grumman), Vivienne Cleveland (FedEx Services) and James Bowling (iland Cloud Infrastructure).
This high-class cast promises great real-world stories about vCO!

Solution Exchange

More and more vendors present plugins for vCO… Ask them all about their integration with Orchestrator!
(In the past this was hard business, but if you keep asking, you will get to the proper person for a demo….)

Party (and everywhere else)

To qoute from the official Orchestrator Blog:

And as you roam the convention floors, be on the lookout for orchestration gurus like Burke Azbill, James Bowling, Cody Bunch, Bill Call, Christophe Decanini, Chris Knowles, Thomas Kraus, Savina Ilieva, William Lam, Joerg Lew and Igor Stoyanov.

Let’s see who can snap the most pictures with these workflow jedis… ;-)

3

LittleCMDB (An Orchestrator and WaveMaker project) – Part 7

Table of Content

In Part1 we start with the SQL DB Plugin and create the required database for our need.

In Part2 we start with the development of our Workflow. We will start with a few elements.

In Part3 we  finish the  collection of the VM information.

In Part4 we insert our data into the database and test our created workflow

In Part5 we create our webview to get a look on our Data in the SQL Database

In Part6 we will make our Workflow smarter to update the DB with actual VM information

In Part7 problems with vAPP located virtual machines are fixed

Part7

Today we will make some more error corrections for our LittleCMDB. Has anyone build the LittleCMDB yet? Do you use vAPPS in your environment? Than you have a problem with the LittleCMDB. The Workflow will stop on the “Extract virtual machine information” workflow.

”"

Why that?  To answer this Question we must take a look at the Workflow and the API. Let’s start with the Workflow. The Workflow exist out of different elements. The first element “Get Folder” grabs the Folder for the virtual machine.

”"

For a “normal” virtual machine this works perfectly. The element uses the VM name and the “parent” object in the API to get the needed information.

”"

Now let’s have a look on a virtual machine which is located under a vAPP.

”"

Did you see the difference? For a virtual machine the parameter “parent” is used and the parameter “parentVApp” is Unset. For a virtual machine under a vApp that’s changed. So, when the Workflow hits a virtual machine located under a vApp the Workflow will fail.

How can we fix this problem? Don’t worry, that easy ;-)

First, we have  to copy the Workflow “Extract virtual machine information”. We do so by going to:

Library –> vCenter –> Virtual Machine management –> Others There we can find our Workflow.

Just “right click”  on the Workflow and choose in the menu “Duplicate Workflow”.

”"

Give the Workflow a name, I take the name “Extract virtual machine information_WithChanges” and choose a location for the Workflow. I would recommend  to keep all your customized workflows together. I will insert the Workflow into my vcoportal.de folder and there in a subfolder “Helper” (for me that is better to export my project ;-) ). Copy the version history.

”"

After we have duplicated the Workflow, we go to the chosen Folder and edit it.

First I change the Version history and insert a comment.

”"

Then we go to the Schema Tab and there to the “Get Folder” Element. Here we change the Scripting to:


if (vm.parent != null){
folder = vm.parent;} else
{
folder = vm.parentVApp;}

folderName = folder.name;
folderId = folder.sdkId;

The scripting here is simple. We just look if the parent value is unset, then we use parentVApp. After we are finished validate and save the workflow.

At last, we go to our “GetVMConfig” Workflow. There we delte the “Extract virtual machine information” Workflow and insert our “Extract virtual machine information_WithChanges” workflow.

”"

After that, insert the connections and the vm parameter (VMtoGet). Normally it should be insert automatically. Validate our Workflow and enjoy.

That’s all for Part7.

1

Adventures with the vCO AMQP Plugin

*** This is a Guest Article, written by Mathew Quinn – Thanks, Mat! ***

Having had some experience with a variety of plugins for vCO that range in quality, I was wondering what to expect from the AMQP plugin. I approached the plugin with a good deal of skepticism – which did turn out to be completely unfair!

Having had no prior experience with message queues, my first task was to learn about all things queue.

Selecting RabbitMQ to experiment with was the obvious choice. I believe VMware now own this product which can be used in a free edition or as part of the larger vFabric suite. The Plugin also comes with a little rabbit icon, so I’m guessing this is what they’re suggesting. The plugin can however work with any AMQP-based message broker.

Now there were some AMQP concepts to learn, which turned out to be very simple and well presented. I would recommend a read through the following documentation if you are new to AMQP or RabbitMQ: http://www.rabbitmq.com/tutorials/amqp-concepts.html

Next I provisioned a CentOS 6 VM and installed RabbitMQ which was ridiculously easy. In order to get moving faster, I also installed the RabbitMQ management plugin that presents a convenient web interface where you can define exchanges, queues and bindings, and also publish and retrieve messages.

Get Started with AMQP in vCenter Orchestrator

Installation of the AMQP plugin for vCO was easy so I’ll skip that part. It installs the same as any other Plugin for vCO.

Upon installation, some new workflows are now present in the vCO Client

Right, very straightforward. There appeared everything I needed to get started.

A good place to start is running the ‘Add a Broker’ workflow which adds a broker (AMQP server) to the vCO inventory. This is the root object from the point of view of the plugin’s inventory. Once you have a broker in your inventory you’re free to begin receiving and publishing messages, which works quite nicely.

On the AMQP Broker I added a queue called ‘Inbox’ and a queue called ‘Outbox’, the intention being to both receive a message in vCO, and publish a message back.

And published a message to the inbox, ready to receive.

Now the moment of anticipation. Will this work first go? I run the ‘Receive a text message’ workflow in vCO client.

Presto! Success! My message has been received in the vCO client perfectly. I’m starting to like this.

Now let’s send a message back to the outbox.

The workflow runs successfully, and looking at the broker, there is indeed a message sitting in the queue to be fetched.

Nice! The reply was received successfully too. Already things are starting to look very nice indeed.
Now to step things up a notch. What I’m really interested in with the AMQP plugin are the event-driven possibilities. I want to be able to trigger a workflow from an inbox message, do some processing, and respond to the outbox.

Event-driven Message Handling

Rather than reinvent the wheel, I decided to check online for examples of just this operation and stumbled across some workflows published on the subject:
http://communities.vmware.com/docs/DOC-18002
The example was focused around handling vCloud Director message notifications. I imported the package and took a look.

The author achieves this by utilising a policy connected to an AMQP subscription that triggers a scripting event. When a message arrives in the queue that is subscribed to, the event fires and the script runs. Neat.

The script that runs operates by firing up a workflow – but this is where things start to get messy.

Oh no – is that a hard coded workflow ID in the script? It sure is. If beings greater than myself have found that this is the best way to do things, we’re in trouble. I just can’t do things like this when coding and enterprise-grade solution.

Investigating policies a bit further, it turns out that it is possible to directly trigger a workflow from an event rather than run a script. I decide to give this a try.

Firstly I must create a subscription to my inbox queue, and workflow that I intend to run. Subscriptions are for the sole intent of receiving messages from a queue and they live in the vCO inventory. You can create one by running the ‘Subscribe to queues’ workflow.

I also create an empty workflow to trigger on receiving a message. Now I have all the components I need to build my policy.

This is all well and good, but I need some input to my workflow. I want the workflow to be able to inspect the message received. I create a new parameter to the workflow of type ‘Any’.

Now to hook this up to the policy. I will gloss over the details a bit here but, suffice to say, I found passing in the ‘self’ object of type AMQP:Subscription the most reliable way to get all the details of the message received and, additionally, the subscription that received the message, into the workflow using only one input. The other possible inputs, event key headers, properties, and body, achieve this only in part, and with varying degrees of success.

In the workflow itself, I add a scripting object to log the message, and nest a ‘Send text message’ workflow to reply to the outbox.

Now I am all ready for the big test. I should be able to send a message to the inbox queue, Orchestrator will log this, and send a reply to the outbox. With the policy started, I send a message to the inbox.

Fantastic, I can see the message body logged in the workflow run.

And the reply is present in the outbox queue!


In Summary, the vCO AMQP plugin offers an exciting range of possibilities. It interfaces simply and reliably with AMQP Brokers and could be used for a variety of purposes.

References

5

LittleCMDB (An Orchestrator and WaveMaker project) – Part 6

Table of Content

In Part1 we start with the SQL DB Plugin and create the required database for our need.

In Part2 we start with the development of our Workflow. We will start with a few elements.

In Part3 we  finish the  collection of the VM information.

In Part4 we insert our data into the database and test our created workflow

In Part5 we create our webview to get a look on our Data in the SQL Database

In Part6 we will make our Workflow smarter to update the DB with actual VM information

In Part7 problems with vAPP located virtual machines are fixed

Part6

Let’s have a look on our LittleCMDB. We can capture virtual machines, we insert the captured data into a SQL DB and we have a Website to get a look on our data. Till now, that okay but we have some “problems” with our CMDB. What’s with virtual Machines were the configuration is changed after the first capture? At the moment will we not get this configuration changes. Why we don’t get the changes? In our decision “VM in DB” we have the condition “when the VM is in our DB we go back to NumberofVMs”. We don’t look for configuration changes.

That’s not smart :-) ……… This means our DB could be outdated with one week if enough configuration changes were made…

So let’s start and make our LittleCMDB more “production” ready.

First we remove the red dotted line from “VM in DB” to “NumberofVMs”.

First we insert from Bottom to top a Scriptable Task and a Decision. We do this four times. When we are finished your schema should look like mine.

”"

Then we will insert the next Workflows. Here we are on a decision we must made…… We can choose the SQL “Update” workflows or generate Scriptable Task with our own code. I will use scriptable task for the update of the datasets. Why that? When you use the “Update” Workflows, error correction and data search is sometimes a problem. You can only insert “one” value (the value to update the dataset). In the data search, this leads to problems. So I will use scriptable task in which I can insert all needed parameter and my required error correction.

So insert four scriptable workflows on the left of the other workflows.

At the End your schema must look like this:

”"

Don’t worry about the sum of Workflow……it will be very easy ;-)

Know we start with the Scriptable Task at the bottom. First we give a name and description. I will call it “GetVMfromVM_Info”. As description you can insert “We read the information from the VM_Info Table split it and comparing it with the actual data.”

Here are the required Variables for the Element:

Local Parameter Variable Name Module Direction Type
VMName VMName GetVMInfofromVM_Info in String
VMInfo_Table VMInfo_Table GetVMInfofromVM_Info in SQL:Table
VMUUID VMUUID GetVMInfofromVM_Info in String
VMInfofromDB VMInfofromDB GetVMInfofromVM_Info in SQL:ActiveRecord
datastoreName datastoreName GetVMInfofromVM_Info in Array/string
cpuCount cpuCount GetVMInfofromVM_Info in number
memoryMB memoryMB GetVMInfofromVM_Info in number
CPUNumberfromDB CPUNumberfromDB GetVMInfofromVM_Info out number
MemNumberfromDB MemNumberfromDB GetVMInfofromVM_Info out number
VM_Info_Change VM_info_Change GetVMInfofromVM_Info out Boolean
V_ID V_ID GetVMInfofromVM_Info Out String

Don’t forget to map the VMInfo_table variable to the VM_Info table.

”"

Here is the required Script for the Task:

// ————————————————————-
// we search for the Data of the virtual Machine with the Name and the UUID. First we define the search columns
var columns = {
 VMUUID : VMUUID,
 VMName : VMName,

};

// Get the Data from the Table and put them in a SQL Active Record
VMInfofromDB = VMInfo_table.readRecords(columns);
// The data from the SQL Record is a "String" with is separated with ",". We have to Split the String in Single Files…..
// First, we put the String into a temporally Variable.
var SplitConfigArraytoStringMem = VMInfofromDB.toString();
// In the Array, we search for the Keyword "MemConfig" under which our Memory configuration is stored
var MemSearch = SplitConfigArraytoStringMem.search("MemConfig");
// The above defined search give us the Starting Position of our Keyword. We want the blank value, so we have to split
// on Position 10 after the Start Position (MemConfig + = is about 10 positions)
var MemStart = MemSearch + 10;
// Here we split at the beginning of the Value with the rest of the string
var MemStringTemp = SplitConfigArraytoStringMem.slice(MemStart);
// We split on the first "," found. That’s our value End
var MemStringEnd = MemStringTemp.search(",");
// Here we take the start and the end we figured out before and save the value into the Variable
MemNumberfromDB = MemStringTemp.slice(0, MemStringEnd);

// The data from the SQL Record is a "String" with is sepearted with ",". We have to Split the String in Single Files…..
// First, we put the String into a temporally Variable.
var SplitConfigArraytoStringCPU = VMInfofromDB.toString();
// In the Array, we search for the Keyword "CPUConfig" under which our Memory configuration is stored
var CPUSearch = SplitConfigArraytoStringCPU.search("CPUConfig");
// The above defined search give us the Starting Position of our Keyword. We want the blank value, so we have to split
// on Position 10 after the Start Position (CPUConfig + = is about 10 positions)
var CPUStart = CPUSearch + 10;
// Here we split at the beginning of the Value with the rest of the string
var CPUStringTemp = SplitConfigArraytoStringCPU.slice(CPUStart);
// We split on the first "}" found. That’s our value End
var CPUStringEnd = CPUStringTemp.search("}");
// Here we take the start and the end we figured out before and save the value into the Variable
CPUNumberfromDB = CPUStringTemp.slice(0, CPUStringEnd);
// The data from the SQL Record is a "String" with is sepearted with ",". We have to Split the String in Single Files…..
// First, we put the String into a temporally Variable.
// The V_ID Field is required to update the SQL DB when there is a change
var SplitConfigArraytoStringVID = VMInfofromDB.toString();
// In the Array, we search for the Keyword "V_ID" under which our V_ID is stored
var VIDSearch = SplitConfigArraytoStringVID.search("VMID");
// The above defined search give us the Starting Position of our Keyword. We want the blank value, so we have to split
// on Position 5 after the Start Position (VMID + = is about 5 positions)
var VIDStart = VIDSearch + 5;
// Here we split at the beginning of the Value with the rest of the string
var VIDStringTemp = SplitConfigArraytoStringVID.slice(VIDStart);
// We split on the first "," found. That’s our value End
var VIDStringEnd = VIDStringTemp.search(",");
// Here we take the start and the end we figured out before and save the value into the Variable
V_ID = VIDStringTemp.slice(0, VIDStringEnd);

//—————————————————————————————————————–
// After we have our "configuration" Values, we have to check if there is a difference between the VM Data and
// the data stored in the DB.

if ((CPUNumberfromDB != cpuCount) || (MemNumberfromDB != memoryMB)){
// When there is a difference, we set the Variable to true
VM_Info_Change = true;}
else {
// When there is no difference, we set the Variable to false
VM_Info_Change = false;}

I made a lot comments in the scripting element so I hope everybody understand the Idea to split the array and get on the DB data.

Next we go to our decision up to the scripting element. We give it a name. I chose “VM_Info_change”. As variable for this decision we need the following:

Local Parameter Variable Name Module Direction Type
VM_Info_Change VM_Info_Change VM_Info_Change in boolean

In the Decision field we set the Value to “is true”

”"

At least, we are going to work with the “Scriptable task” to the left. I call it  “Update active record for ‘VM_Info’” Element.  For that, we need the following In- and Outputs

Local Parameter Variable Name Module Direction Type
VMName VMName Update Active Record for ‘VM_Info’ in String
V_ID V_ID Update Active Record for ‘VM_Info’ in String
VMUUID VMUUID Update Active Record for ‘VM_Info’ in String
cpuCount cpuCount Update Active Record for ‘VM_Info’ in Number
memoryMB memoryMB Update Active Record for ‘VM_Info’ in Number
MemNumberfromDB MemNumberfromDB Update Active Record for ‘VM_Info’ in Number
CPUNumberfromDB CPUNumberfromDB Update Active Record for ‘VM_Info’ in Number
VMInfo_table VMInfo_table Update Active Record for ‘VM_Info’ in SQL:Table
VMInfoRead_result VMInfoRead_result Update Active Record for ‘VM_Info’ in SQL:ActiveRecord
UpdateResult_VM_Info UpdateResult_VM_Info Update Active Record for ‘VM_Info’ out Number

Here is the script we insert into the Scripting field:

// we need the original values to load the record from the DB
var NewArray = new Array(V_ID,VMUUID,VMName,CPUNumberfromDB,MemNumberfromDB)

// we search for the record in the DB with the data from there
VMInfoRead_result = System.getModule("com.vmware.library.sql").findUniqueRecord(VMInfo_table,NewArray);

var columns = {
 VMID : V_ID,
 VMUUID : VMUUID,
 VMName : VMName,
 CPUConfig : cpuCount,
 MemConfig : memoryMB
};
UpdateResult_VM_Info = VMInfo_table.updateRecord(VMInfoRead_result, columns);
System.log("Update DB with new virtual machine information")

Now we are going to connect the first Elements. We start with the “VM_in_DB” Element and connect it with the “red” line to the “GetVMfromVM_Info” Element. The “GetVMfromVM_Info” will be connected to the “VM_Info_Change” element. From this element we connect the “true” (the green line) to “Update active record for ‘VM_Info” and the “false” (the red line) to the “Scriptable Task above. As last connection we draw the line from “Update active record for ‘VM_Info” to the Scriptable Task above. When you are ready your connections must look like my.

”"

After we have finished our connections, we go further with the “Scriptable  Task” Element we have already connected. First we insert a name and description. I use as name “GetVMfromHost_info” and as description “Get the Information from the database regarding the Host information”. Then we have to define our needed variables:

Local Parameter Variable Name Module Direction Type
VMHost_Table VMHost_Table GetVMfromHost_info in SQL:Table
VMUUID VMUUID GetVMfromHost_info in String
V_ID V_ID GetVMfromHost_info in string
VMInfofromDB VMInfofromDB GetVMfromHost_info in SQL:ActiveRecord
runningHostName runningHostName GetVMfromHost_info in String
clusterName clusterName GetVMfromHost_info in String
resourcePoolName resourcePoolName GetVMfromHost_info in String
folderName folderName GetVMfromHost_info in String
HostfromDB HostfromDB GetVMfromHost_info out String
ClusterfromDB ClusterfromDB GetVMfromHost_info out String
RPfromDB RPfromDB GetVMfromHost_info out String
FolderfromDB FolderfromDB GetVMfromHost_info out String
VM_Host_Change VM_Host_Change GetVMfromHost_info out boolean

Also here is it required, to point the Variable “VMHost_table” to the “VM_Host” Table

”"

Then we can start our scripting. In the basic, the following scripting is the same as we already did for the “GetVMInfofromVM_Info” table. Here is the Script:

// ————————————————————-
// we search for the Data of the virtual Machine with the Name and the UUID. First we define the search columns
var columns = {
 VMID : V_ID,
 VMUUID : VMUUID,
};

// Get the Data from the Table and put them in a SQL Active Record
VMInfofromDB = VMHost_table.readRecords(columns);

// The data from the SQL Record is a "String" with is sepearted with ",". We have to Split the String in Single Files…..
// First, we put the String into a temporally Variable.
var SplitConfigArraytoStringHost = VMInfofromDB.toString();
// In the Array, we search for the Keyword
var HostSearch = SplitConfigArraytoStringHost.search("Host");
// The above defined search give us the Starting Position of our Keyword. We want the blank value, so we have to split
// on Position 5 after the Start Position
var HostStart = HostSearch + 5;
// Here we split at the beginning of the Value with the rest of the string
var HostStringTemp = SplitConfigArraytoStringHost.slice(HostStart);
// We split on the first "," found. That’s our value End
var HostStringEnd = HostStringTemp.search(",");
// Here we take the start and the end we figured out before and save the value into the Variable
HostfromDB = HostStringTemp.slice(0, HostStringEnd);

// The data from the SQL Record is a "String" with is sepearted with ",". We have to Split the String in Single Files…..
// First, we put the String into a temporally Variable.
var SplitConfigArraytoStringCluster = VMInfofromDB.toString();
// In the Array, we search for the Keyword
var ClusterSearch = SplitConfigArraytoStringCluster.search("Cluster");
// The above defined search give us the Starting Position of our Keyword. We want the blank value, so we have to split
// on Position 8 after the Start Position
var ClusterStart = ClusterSearch + 8;
// Here we split at the beginning of the Value with the rest of the string
var ClusterStringTemp = SplitConfigArraytoStringCluster.slice(ClusterStart);
// We split on the first "}" found. That’s our value End
var ClusterStringEnd = ClusterStringTemp.search(",");
// Here we take the start and the end we figured out before and save the value into the Variable
ClusterfromDB = ClusterStringTemp.slice(0, ClusterStringEnd);

// The data from the SQL Record is a "String" with is sepearted with ",". We have to Split the String in Single Files…..
// First, we put the String into a temporally Variable.
var SplitConfigArraytoStringFolder = VMInfofromDB.toString();
// In the Array, we search for the Keyword
var FolderSearch = SplitConfigArraytoStringFolder.search("Folder");
// The above defined search give us the Starting Position of our Keyword. We want the blank value, so we have to split
// on Position 7 after the Start Position
var FolderStart = FolderSearch + 7;
// Here we split at the beginning of the Value with the rest of the string
var FolderStringTemp = SplitConfigArraytoStringCluster.slice(FolderStart);
// We split on the first "," found. That’s our value End
var FolderStringEnd = FolderStringTemp.search(",");
// Here we take the start and the end we figured out before and save the value into the Variable
FolderfromDB = FolderStringTemp.slice(0, FolderStringEnd);

// The data from the SQL Record is a "String" with is sepearted with ",". We have to Split the String in Single Files…..
// First, we put the String into a temporally Variable.
var SplitConfigArraytoStringRP = VMInfofromDB.toString();
// In the Array, we search for the Keyword
var RPSearch = SplitConfigArraytoStringRP.search("ResourcePool");
// The above defined search give us the Starting Position of our Keyword. We want the blank value, so we have to split
// on Position 13 after the Start Position
var RPStart = RPSearch + 13;
// Here we split at the beginning of the Value with the rest of the string
var RPStringTemp = SplitConfigArraytoStringRP.slice(RPStart);
// We split on the first "}" found. That’s our value End
var RPStringEnd = RPStringTemp.search("}");
// Here we take the start and the end we figured out before and save the value into the Variable
RPfromDB = RPStringTemp.slice(0, RPStringEnd);

//—————————————————————————————————————–
// After we have our "configuration" Values, we have to check if there is a difference between the VM Data and
// the data stored in the DB.
if ((HostfromDB != runningHostName) || (ClusterfromDB != clusterName) || (RPfromDB != resourcePoolName) || (FolderfromDB != folderName)){
// When there is a difference, we set the Variable to true
VM_Host_Change = true;}
else {
// When there is no difference, we set the Variable to false
VM_Host_Change = false;}

After we finished our scripting we went to the “Decision”. Here we enter a name; I use “VM_Host_Change” and a description. In the Decision we need the Variable “Vm_Host_Change”

Local Parameter Variable Name Module Direction Type
VM_Host_Change VM_Host_Change VM_Host_Change in boolean

We set the Value in the Decision field to “is true”.

”"

Next we define the In- and Outputs for the “Scriptable Task”. I call the Workflow “Update active record for ‘VM_Host’”. We need the following variables:

Local Parameter Variable Name Module Direction Type
V_ID V_ID Update Active Record for ‘VM_Host’ in String
VMUUID VMUUID Update Active Record for ‘VM_Host’ in String
clusterName clusterName Update Active Record for ‘VM_Host’ in String
runningHostName runningHostName Update Active Record for ‘VM_Host’ in String
resourcePoolName resourcePoolName Update Active Record for ‘VM_Host’ in String
folderName folderName Update Active Record for ‘VM_Host’ in String
ClusterfromDB ClusterfromDB Update Active Record for ‘VM_Host’ in String
HostfromDB HostfromDB Update Active Record for ‘VM_Host’ in String
RPfromDB RPfromDB Update Active Record for ‘VM_Host’ in String
FolderfromDB FolderfromDB Update Active Record for ‘VM_Host’ in String
UpdateResult_VM_Host UpdateResult_VM_Host Update Active Record for ‘VM_Host’ in Number
VMHost_table VMHost_table Update Active Record for ‘VM_Host’ in SQL:Table
VMHost_ReadResult VMHost_ReadResult Update Active Record for ‘VM_Host’ in SQL:ActiveRecord
UpdateResult_VM_Host UpdateResult_VM_Host Update Active Record for ‘VM_Host’ Out Number

Here is the script which we need in this module:

// we need the original values to load the record from the DB
var NewArray = new Array(V_ID,VMUUID,ClusterfromDB,HostfromDB,RPfromDB,FolderfromDB)

// we search for the record in the DB with the data from there
VMHost_ReadResult = System.getModule("com.vmware.library.sql").findUniqueRecord(VMHost_table,NewArray);

var columns = {
 VMID : V_ID,
 VMUUID : VMUUID,
 Cluster : clusterName,
 Host : runningHostName,
 ResourcePool : resourcePoolName,
 Folder : folderName
};

UpdateResult_VM_Host = VMHost_table.updateRecord(VMHost_ReadResult, columns);
System.log("Update DB with new host information")

 

After we have finished our mappings, we can connect the different workflows together. Also here it is the same schema as before. We connect the “GetVMfromHost_Info” to the decision “VM_Host_Change” from there we connect the false path to the “Scriptable Task” above and the true Path to “Update active record from ‘VM_Host”. From there we connect to also to the Scriptable task.

”"

Now, I think everybody has an understanding from the method which is used here, so I will only provide the variables and the scripts for the last elements.

I call the next scriptable task “GetVMfromVM_Network”.  Here are the required in- and outputs and the script:

Local Parameter Variable Name Module Direction Type
V_ID V_ID GetVMInfofromVM_Network in string
VMNetwork_table VMNetwork_table GetVMInfofromVM_Network in SQL:Table
VMUUID VMUUID GetVMInfofromVM_Network in String
VMInfofromDB VMInfofromDB GetVMInfofromVM_Network in SQL:ActiveRecord
ipAddresses ipAddresses GetVMInfofromVM_Network in Array/string
networks networks GetVMInfofromVM_Network in Array/string
IPfromDB IPfromDB GetVMInfofromVM_Network out String
NetworksfromDB NetworksfromDB GetVMInfofromVM_Network out String
VM_Network_Change VM_Network_Change GetVMInfofromVM_Network out boolean
IpAddressToString IpAddressToString GetVMInfofromVM_Network out string
NetworksToString NetworksToString GetVMInfofromVM_Network out string
// ————————————————————-
// we search for the Data of the virtual Machine with the Name and the UUID. First we define the search columns
var columns = {
 VMID : V_ID,
 VMUUID : VMUUID,
};

// Get the Data from the Table and put them in a SQL Active Record
VMInfofromDB = VMNetwork_table.readRecords(columns);

// The data from the SQL Record is a "String" with is sepearted with ",". We have to Split the String in Single Files…..
// First, we put the String into a temporally Variable.
var SplitConfigArraytoStringIP = VMInfofromDB.toString();
// In the Array, we search for the Keyword "IPAddress"
var IPSearch = SplitConfigArraytoStringIP.search("IPAddress");
// The above defined search give us the Starting Position of our Keyword. We want the blank value, so we have to split
// on Position 10 after the Start Position
var IPStart = IPSearch + 10;
// Here we split at the beginning of the Value with the rest of the string
var IPStringTemp = SplitConfigArraytoStringIP.slice(IPStart);
// We split on the first "," followed from a space. That’s our value End. That’s different then before because
// the vm can have more than one ip which is separated thru a ","
var IPStringEnd = IPStringTemp.search(/\s?,\s/);
// Here we take the start and the end we figured out before and save the value into the Variable
IPfromDB = IPStringTemp.slice(0, IPStringEnd);

// The data from the SQL Record is a "String" with is sepearted with ",". We have to Split the String in Single Files…..
// First, we put the String into a temporally Variable.
var SplitConfigArraytoStringNet = VMInfofromDB.toString();
// In the Array, we search for the Keyword
var NetSearch = SplitConfigArraytoStringNet.search("Network");
// The above defined search give us the Starting Position of our Keyword. We want the blank value, so we have to split
// on Position 8 after the Start Position
var NetStart = NetSearch + 8;
// Here we split at the beginning of the Value with the rest of the string
var NetStringTemp = SplitConfigArraytoStringNet.slice(NetStart);
// We split on the first "," folowed from a space. That’s our value End. That’s different then before because
// the vm can have more than one network which is separated thru a ","
var NetStringEnd = NetStringTemp.search(/\s?,\s/);
// Here we take the start and the end we figured out before and save the value into the Variable
NetworksfromDB = NetStringTemp.slice(0, NetStringEnd);
//—————————————————————————————————————–
// After we have our "configuration" Values, we have to check if there is a difference between the VM Data and
// the data stored in the DB.

// Catch empty Network and IpAddresses and set a placeholder text
if ((ipAddresses == null) || (ipAddresses == "")) {
IpAddressToString = "No IP adress found"
} else {
IpAddressToString = ipAddresses.toString()
};

if ((networks== null) || (networks == "" )){
NetworksToString = "No networks found"
} else {
NetworksToString =networks.toString()
};

if ((IPfromDB != IpAddressToString) || (NetworksfromDB != NetworksToString)){
// When there is a difference, we set the Variable to true
VM_Network_Change = true;}
else {
// When there is no difference, we set the Variable to false
VM_Network_Change = false;}

When you have a deeper look at the script, you will see that there is a change between this script and the two scripts before. Here we have (as by the insert into the DB) to convert our API Network information into a string! You will see the same conversation in the datastore script. Next we work with the Decision above. I call it “VM_Network_Change” and set the Value “VM_network_change” to true. Here is the table with the Variables:

Local Parameter Variable Name Module Direction Type
VM_Network_Change VM_Network_Change VM_Network_Change in boolean

Our last part for this three pair configuration is the “Scriptable task”. I call it “Update active record for ‘VM_Network”. We use the following in- and outputs:

Local Parameter Variable Name Module Direction Type
V_ID V_ID Update active record for ‘VM_Network in String
VMUUID VMUUID Update active record for ‘VM_Network in String
NetworksToString NetworksToString Update active record for ‘VM_Network in String
IpAddressToString IpAddressToString Update active record for ‘VM_Network in String
IPfromDB IPfromDB Update active record for ‘VM_Network in String
NetworksfromDB NetworksfromDB Update active record for ‘VM_Network in String
VMNetwork_table VMNetwork_table Update active record for ‘VM_Network in SQL:Table
VMNetworkRead_result VMNetworkRead_result Update active record for ‘VM_Network in SQL:ActiceRecord
UpdateResult_VM_Network UpdateResult_VM_Network Update active record for ‘VM_Network Out Number

And here is the script:

// We must catch "null" values and change them to ""
// we do this for IPfromDB and NetworksfromDB
// we need the original values to load the record from the DB
if (IPfromDB == "null"){
IPfromDB = "";}
if (NetworksfromDB == "null"){
NetworksfromDB = "";}

var NewArray = new Array(V_ID,VMUUID,NetworksfromDB,IPfromDB)

// we search for the record in the DB with the data from there
VMNetworkRead_result = System.getModule("com.vmware.library.sql").findUniqueRecord(VMNetwork_table,NewArray);

var columns = {
 VMID : V_ID,
 VMUUID : VMUUID,
 Network : NetworksToString,
 IPAddress : IpAddressToString
};

UpdateResult_VM_Network = VMNetwork_table.updateRecord(VMNetworkRead_result, columns);
System.log("Update DB with new network Information")

 

Now we can make our connections. Just follow the logic witch was used before. It is the same here…

”"

Now let’s configure the last three pair of Workflows. We start with the scriptable task. I name it “GetVMfromVM_Datastore” and here are the used variables:

Local Parameter Variable Name Module Direction Type
V_ID V_ID GetVMInfofromVM_Datastore in string
VMDatastore_table VMDatastore_table GetVMInfofromVM_Datastore in SQL:Table
VMUUID VMUUID GetVMInfofromVM_Datastore in String
VMInfofromDB VMInfofromDB GetVMInfofromVM_Datastore in SQL:ActiveRecord
datastoresName datastoresName GetVMInfofromVM_Datastore in Array/string
diskSizes diskSizes GetVMInfofromVM_Datastore in Array/Number
DatastorefromDB DatastorefromDB GetVMInfofromVM_Datastore out String
DiskfromDB DiskfromDB GetVMInfofromVM_Datastore out String
VM_Datastore_Change VM_Datastore_Change GetVMInfofromVM_Datastore out boolean
DiskSizetoString DiskSizetoString GetVMInfofromVM_Datastore out String
DatastoreNamestoString DatastoreNamestoString GetVMInfofromVM_Datastore out String

And here is the required script:

// ————————————————————-
// we search for the Data of the virtual Machine with the Name and the UUID. First we define the search columns
var columns = {
 VMID : V_ID,
 VMUUID : VMUUID,

};

// Get the Data from the Table and put them in a SQL Active Record
VMInfofromDB = VMDatastore_table.readRecords(columns);

// The data from the SQL Record is a "String" with is sepearted with ",". We have to Split the String in Single Files…..
// First, we put the String into a temporally Variable.
var SplitConfigArraytoStringDisk = VMInfofromDB.toString();
// In the Array, we search for the Keyword
var DiskSearch = SplitConfigArraytoStringDisk.search("DiskSize");
// The above defined search give us the Starting Position of our Keyword. We want the blank value, so we have to split
// on Position 9 after the Start Position
var DiskStart = DiskSearch + 9;
// Here we split at the beginning of the Value with the rest of the string
var DiskStringTemp = SplitConfigArraytoStringDisk.slice(DiskStart);
// We split on the first "," folowed from a space. That’s our value End. That’s different then before because
// the vm can have more than one ip which is separated thru a ","
var DiskStringEnd = DiskStringTemp.search(/\s?,\s/);
// Here we take the start and the end we figured out before and save the value into the Variable
DiskfromDB = DiskStringTemp.slice(0, DiskStringEnd);

// The data from the SQL Record is a "String" with is sepearted with ",". We have to Split the String in Single Files…..
// First, we put the String into a temporally Variable.
var SplitConfigArraytoStringData = VMInfofromDB.toString();
// In the Array, we search for the Keyword
var DataSearch = SplitConfigArraytoStringData.search("Datastore");
// The above defined search give us the Starting Position of our Keyword. We want the blank value, so we have to split
// on Position 10 after the Start Position
var DataStart = DataSearch + 10;
// Here we split at the beginning of the Value with the rest of the string
var DataStringTemp = SplitConfigArraytoStringData.slice(DataStart);
// We split on the first "}". That’s our value End
var DataStringEnd = DataStringTemp.search("}");
// Here we take the start and the end we figured out before and save the value into the Variable
DatastorefromDB = DataStringTemp.slice(0, DataStringEnd);
//—————————————————————————————————————–
// After we have our "configuration" Values, we have to check if there is a difference between the VM Data and
// the data stored in the DB.
// Catch empty disksizes and datastoreName and replace with a string
if ((diskSizes == null) || (diskSizes == "")){
DiskSizeToString = "Could not read Disk Size"
} else {
DiskSizeToString = diskSizes.toString();
};

if ((datastoresName == null) || (datastoresName = "")) {
DatastoreNamesToString = "Could not read Datastore Name"
} else {
DatastoreNamesToString = datastoresName.toString();
};

if ((DiskfromDB != DiskSizeToString) || (DatastorefromDB != DatastoreNamesToString)){
// When there is a difference, we set the Variable to true
VM_Datastore_Change = true;}
else {
// When there is no difference, we set the Variable to false
VM_Datastore_Change = false;}

Next we change the name for the decision to “VM_Datastore_Change”. As input we need:

Local Parameter Variable Name Module Direction Type
VM_Datastore_Change VM_Datastore_Change VM_Datastore_Change in boolean

Also here we set the Value VM_Datastore_Change to “true”.

Our last configuration must be done on the “Scriptable task”. I call it “Update active record for ‘VM_Datastore’”. Here we need the in- and outputs:

Local Parameter Variable Name Module Direction Type
V_ID V_ID Update active record for ‘VM_Datastore’ in String
VMUUID VMUUID Update active record for ‘VM_Datastore’ in String
DiskSizetoString DiskSizetoString Update active record for ‘VM_Datastore’ in String
DatastoreNamesToString DatastoreNamesToString Update active record for ‘VM_Datastore’ in String
DiskfromDB DiskfromDB Update active record for ‘VM_Datastore’ in String
DatastorefromDB DatastorefromDB Update active record for ‘VM_Datastore’ in String
VMDatastore_table VMDatastore_table Update active record for ‘VM_Datastore’ in SQL:Table
VMDatastoreRead_result VMDatastoreRead_result Update active record for ‘VM_Datastore’ in SQL:Active Record
UpdateResult_VM_Datastore UpdateResult_VM_Datastore Update active record for ‘VM_Datastore’ out Number

And this script:

// We must catch "null" values and change them to ""
// we do this for DiskfromDB and DatastorefromDB
// we need the original values to load the record from the DB
if (DiskfromDB == "null"){
DiskfromDB = "";}
if (DatastorefromDB == "null"){
DatastorefromDB = "";}

// we search for the record in the DB with the data from there
var NewArray = new Array(V_ID,VMUUID,DiskfromDB,DatastorefromDB)

VMDatastoreRead_result = System.getModule("com.vmware.library.sql").findUniqueRecord(VMDatastore_table,NewArray);

// Now we start to update the record with the new data
var columns = {
 VMID : V_ID,
 VMUUID : VMUUID,
 DiskSize : DiskSizeToString,
 Datastore : DatastoreNamesToString
};
UpdateResult_VM_Datastore = VMDatastore_table.updateRecord(VMDatastoreRead_result, columns);
System.log("Update DB with new Storage Information")

At least we have to make our last connections. We start from “GetVMfromVM_Datastore” and go to the “VM_Datastore_Change”. From there we go with the false (the red) line to “NumberofVMs”. With the true (the green) line we go to “Update active record for ‘VM_Datastore’”. From there we connect to “NumberofVMs”.