Wavemaker

0

Wavemaker and vCO – The next level

Remember these?

http://www.vcoportal.de/2011/11/using-wavemaker-as-web-frontend-for-vco/
http://www.virtuallyghetto.com/2011/12/leveraging-vcd-vco-wavemaker-part-1.html
http://www.virtuallyghetto.com/2011/12/leveraging-vcd-vco-wavemaker-part-2.html
http://mighty-virtualization.blogspot.de/2011/11/vco-wavemaker-your-cloud-webservice.html
http://mighty-virtualization.blogspot.de/2011/11/vco-wavemaker-your-cloud-webservice_24.html

Well, it has been quite a while since then, and a lot happened to Wavemaker in between:
https://www.youtube.com/watch?v=zSn7WhX5Wc0 

This week VMware released a new Fling: “Wavemaker Integration with vCenter Orchestrator”

https://labs.vmware.com/flings/wavemaker-integration-for-vcenter-orchestrator

This fling allows you to:

  • Run the included WaveOperator demo project, that provides common tasks (like start and monitor workflow execution), comparable to the weboperator webview in vCO
  • Use the widgets to create your own web interface for your workflows
  • Use the Java Services that expose the vCO API into Wavemaker projects

Sounds cool? Is cool! No more manual getting things together, but predefined wavemaker widgets for your workflows to just drag and drop into yourweb interface!

But wait, there’s more! The project is available open source on Github: https://github.com/vmware/wavemaker_integration

So you can even expand the functionality to your needs, or adopt the code for your projects.

0

What’s the future of WaveMaker? And: WaveMaker book available

Earlier this year WaveMaker, our preferred tool to built custom web frontends for vCenter Orchestrator, moved from VMware to Cloudjee Inc, a spin-off of Pramati Technologies (http://dev.wavemaker.com/blog/2013/05/30/cloudjee-inc/). In September the new owner hold a nice webex about their future plans with WaveMaker. See for yourself:

These are really exciting plans, looking forward to give the new mobile features a try!

And more good news: Ed Callahan has published a book about “Easy Web-Development with WaveMaker”, which I absolutely recommend you to have a look at! http://www.packtpub.com/easy-web-development-with-wavemaker/book 1783OS Easy Web Development with WaveMaker 0

2

Application Onboarding with vCO and WaveMaker

Last month I had a customer, who wanted an onboarding process for his virtual machines. This onboarding should work as follow:
– There is a standard Linux template for all virtual machines
– The users can choose from a web site what machine type is required
– From the website a vCO workflow is started which clones the template and installed the required packages into the VM
– At the end the application configuration is done
To be honest, the customer requirements were quite simple so the usage of Puppet or Chef was not an option.
After everything the customer wanted was clear, I thought about the options and came to the idea to choose the vCO and WaveMaker for the solution.
I don’t like passwords in Workflows so the first think I did, was creating a vCO SSH Key. This could be done with a predefined workflow in vCO.

After I had my SSH public key, I created the Linux template with the public key in the file /root/.ssh/authorized_keys
You can do this manually or also use a predefined vCO Workflow

This allows me, to administer the Linux VM without the need for a password.
The next thing I did, was to create a folder on the vCO Appliance. I created the folder under the root directory with the name ConfigFiles. The vCO has a secure configuration so to allow the vCO Server to access this folder you must allow this explicit. For that, you have to edit the file: js-io-rights.conf on the vCO appliance this file is located under the path:

/opt/vmo/app-server/server/vmo/conf/js-io-rights.conf

I added my created path and after that, the file was looking like this:


-rwx /
+rwx /var/run/orchestrator
+rx ../../configuration/jetty/logs/
+rx ../server/vmo/log/
+rx ../bin/
+rx ./boot.properties
+rx ../server/vmo/conf/
+rx ../server/vmo/conf/plugins/
+rx ../server/vmo/deploy/vmo-server/vmo-ds.xml
+rx ../../apps/
+r ../../version.txt
+rw /ConfigFiles

After you have done this editing, you must restart the vCO Service to take the changes in effect.
For later use, I placed a file with the name “named.conf” into the folder. This file contains the configuration for the bind installation which I will use later in this Blog post.
For our Onboarding, we need the SCP workflow. With the predefined workflow, we have a little problem…..it doesn’t work with ssh Keys. So we have to modify the predefined workflow. Therefore we copy the existing workflow.

I called my workflow “SCP Put command with SSH Key”. After we have copied the workflow, we have to modify it.

We have to change the content in the SCP put file Scriptable task.

try{
var session = new SSHSession(hostName,username);

if(passwordAuthentication){
System.log("Connecting with password");
} else {
if(path == null || path == ""){
System.log("using default");
path = defaultKeyPairPath;
}
System.log("Connecting with key pair ("+path+")");
password = passphrase;
}

session.connectWithPasswordOrIdentity(passwordAuthentication,password,path);
System.log("Connected!");

session.putFile(localFile,remoteFile) ;
output = session.getOutput();
error = session.getError();
exitCode = session.exitCode;

System.log("Output: '"+output+"'");
System.log("Error: '"+error+"'");
System.log("Exit code: '"+exitCode+"'");

session.disconnect();

} catch (e) {
throw "Unable to execute command " + e;
}

After we have made the scripting changes, we need to add an Attribute. I choose defaultKeyPairPath as name. It is from type string and added as value ../server/vmo/conf/vco_key (the path to the vCO SSH Key).

On the input site of the workflow we have to add three Inputs. The first we have to create is passwordAuthentication from type boolean. As default value we choose no. The second Input variable is path from type path. The last one we need is passphrase from type SecureString. The last one is required, if we protect our SSH Key with a passphrase.

After we have created the SCP Put command with SSH Key it is time to build our workflow.
In this blog, we create a simple onboarding workflow to configure a Name Server with bind. The Template I use is a Cent-OS Minimal installation with installed VMwareTools and the SSH Public Key from the vCO Server.
I created a new Workflow with the name “Blog_Configure_DNS”.

In this workflow we go to the schema and add the following Workflows.
The first one is a Workflow with the name “Clone, Linux with single NIC” to clone the template. The second workflow we use is “Run SSH command”. The next one is our “SCP put command with SSH Key” and as last one we also use “Run SSH Command”.

Now we rename the commands. I rename the first “Run SSH….” to “Install named” the “SCP put command….” to “Put configuration named.conf” and the last Workflow to “Restart named”.

After the workflow design, you have to create the needed Attributes, In- and Outputs for every element. I did some examples in my “Little CMDB” series so if you are not familiar to create the needed parameter take a look here:

http://www.vcoportal.de/2012/07/introducing-the-littlecmdb-a-vcenter-orchestrator-wavemaker-demo-project/
and following.

When you’re finished with this, we have to build up the WaveMaker interface.
There are also a lot of good examples available to do this. You will find lot information here:
Using WaveMaker as Web-Fontend for vCO

http://www.vcoportal.de/2011/11/using-wavemaker-as-web-frontend-for-vco/

Off-topic(?): Lessons learned with WaveMaker
http://www.vcoportal.de/2012/02/lessons-learned-with-wavemaker/

Howto setup LDAP-Authentication for Wavemaker (Part 1 & Part2)
http://www.vcoportal.de/2012/05/howto-setup-ldap-authentication-for-wavemaker-part-1/

http://www.vcoportal.de/2012/07/introducing-the-littlecmdb-a-vcenter-orchestrator-wavemaker-demo-project/

To choose the right configuration, you can create a Drop Down field with different options. Here a Screen Shot for the DNS Server.

And here a Screen Shot for the DHCP Server with definition of the Scope.

Beside the option to use WaveMaker, you could also use an automatic provisioning depending on the actual load of a resource pool. I made an example video to show how it could be done with the vCO. You can find the video here:

http://www.vcoportal.de/2012/11/generate-vms-based-on-actual-load-in-a-resource-pool/
So have fun and orchestrate your virtual environment 😉

1

How to integrate Selenium into WaveMaker

What is Selenium?

Short version: Selenium can be used to automate browsers, i.e. to perform 1000 Google searches, or to comment on a friend’s picture on Facebook 10000 times  (I guess so, didn’t try yet ;)).

Why integrating Selenium into WaveMaker?

The reason for me has been: Performance and Load testing of an existing WaveMaker application, by using almost the same conditions as the future customer.

That meant for me: Creating hundreds of new database entries manually by using the graphical user interface…

And that meant for me: FIND ANOTHER WAY!!!

And luckily I did. After reading some tutorials and writing some simple programs I decided to automate a WaveMaker application… and I failed miserably!

I describe the problem later… now it’s your turn 🙂

Preparations

1. Download the Selenium java driver

2. Install the Selenium IDE plugin

3. Install Firebug

4. Create a new project in WaveMaker without using any template. Save and close it.

5. Now open the zip file you have downloaded in step 1 and copy all the 38 jar files to your WaveMaker project’s lib folder.

6. Open your WaveMaker project again.

Part 1 – GUI

Part 2 – Source


dojo.declare("Main", wm.Page, {
"preferredDevice": "desktop",
start: function() {

this.varTheEntries.addItem({item: "demo1", amount: "one"});
this.varTheEntries.addItem({item: "demo2", amount: "two"});
this.varTheEntries.addItem({item: "demo3", amount: "three"});
},

buttonAddItemClick: function(inSender) {
try {
// Add new item to varTheEntries
this.varTheEntries.addItem({item: this.inputItem.dataValue, amount: this.inputAmount.dataValue});
// clear input fields
this.inputItem.clear();
this.inputAmount.clear();

} catch(e) {
console.error('ERROR IN buttonAddItemClick: ' + e);
}
},

buttonRemoveItemClick: function(inSender) {
try {
// Remove selected item from varTheEntries
this.varTheEntries.removeItem(this.dojoGridEntries.selectedItem);
// disable button
this.buttonRemoveItem.disable();

} catch(e) {
console.error('ERROR IN buttonRemoveItemClick: ' + e);
}
},

_end: 0
});

Part 3 – Services

1. Type Definition

To keep it simple, the shopping list will contain entries with just two attributes: item and amount.

To save this data in a single Variable, you need to create a new Type Definition first.

Insert a new Type Definition

Close that confusing window

Type "myEntry" for name

Right-click the new definition to add a new field

Type fieldName "item" and leave fieldType to "String". Then click addField

Type in “amount” for the second field’s name and leave the fieldType to “String”.

A little bit confusing: After typing “amount” and hitting Enter, the field is created but it doesn’t appear in the navigator view on the upper left hand side.

But if you close and open your project again, it will be displayed correctly.

2. Variable

Now you can create a Variable which uses the new Type Definition. Be sure to check “isList”.

Insert a new Variable

Enter "varTheEntries" for name, choose your Type Definition as type and check the "isList" checkbox

Now you can bind the dojo grid’s dataSet to varTheEntries

At this point, the application should be functional, but also quite boring…

Part 4 – Selenium

Create a new JavaService

Replace the created code with the one shown below.


package com.selenium;

import com.wavemaker.runtime.javaservice.JavaServiceSuperClass;
import com.wavemaker.runtime.service.annotations.ExposeToClient;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;

@ExposeToClient
public class SeleniumTest extends JavaServiceSuperClass {

public SeleniumTest() {
super(INFO);
}

public void createEntries(int numberToCreate) {

WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 20);

driver.get("http://localhost:8094/Selenium_Integration_01/");

for(int i=0; i<numberToCreate; i++)
{
// click the textBox and enter text for item
WebElement textBoxItem = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//input")));
// alternative
//WebElement textBoxItem = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("/html/body/div/div/div/div[2]/div[2]/div[3]/div/div/div[2]/div/input")));
textBoxItem.click();
textBoxItem.sendKeys("awesomeItem " + i);

// click the textBox and enter text for amount
WebElement textBoxAmount = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("/html/body/div/div/div/div[2]/div[2]/div[3]/div/div[2]/div[2]/div/input")));
textBoxAmount.click();
textBoxAmount.sendKeys("some");

// click button "Add Item"
WebElement buttonAddItem = wait.until(ExpectedConditions.elementToBeClickable(By.id("main_buttonAddItem")));
buttonAddItem.click();
}
}

public void deleteEntries(int numberToDelete) {

WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 20);

driver.get("http://localhost:8094/Selenium_Integration_01/");

try {

for(int j=0; j<numberToDelete; j++) {

// Select first dojoGrid column
WebElement dojoColumnFirst = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//td")));
dojoColumnFirst.click();

// Click button Remove Item
WebElement buttonRemove = wait.until(ExpectedConditions.elementToBeClickable(By.id("main_buttonRemoveItem")));
buttonRemove.click();

}

} catch (Exception e) {
log(ERROR, "Error in deleteEntries: " + e);
}
}
}

The JavaService now has two methods: createEntries and deleteEntries.
Create two serviceVariables and bind them to those methods.
Don’t forget to bind the inputs. svCreateEntries expects an Integer for numberToCreate, svDeleteEntries expects an Integer for numberToDelete.
So you have to bind those inputs to the corresponding text boxes on the canvas.


Finally, you have to tell the two “Let’s go” buttons what to do when they are clicked.

     

And that's it, the application should now do the following:

You: “Now I’m clicking Let’s go”

WebDriver: “Hey Firefox, give me a new window and open “http://localhost:8094/Selenium_Integration_01/”

Firefox: “Ok!”

WebDriver: “Wow, nice website! There should be an element at position “//input”. Let’s check if I can click it. If not, let’s wait 20 seconds for it. Ah, there it is! Now I click it and send some text.”

WebDriver: “Another element at position “/html/body/div/div/div/div[2]/div[2]/div[3]/div/div[2]/div[2]/div/input”. Waiting… got it! Click, send text.”

WebDriver: “Me again? A button with id “main_buttonAddItem”? There it is. Click it!”

…and a second time…

Quite the same procedure as for createEntries…

But now, we simply tell the WebDriverWait to select the first column of the dojo grid (“//td”) and click the Remove Item button – in this case both actions three times.

If would like to delete column x, you can do the following:

While recording with the Selenium IDE, click the second column of the grid, then the third column. When selecting “xpath:position” as target, you will get:

As you can see, the difference is the number of the first div. To delete column x, you would write something like this:


if(position == 1)
{
WebElement dojoColumnFirst = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//td")));
dojoColumnFirst.click();
}

else
{
WebElement dojoColumnX = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div["+position+"]/table/tbody/tr/td")));
dojoColumnX.click();
}

Problem:The id’s

The text box for the item’s name is called “inputItem” within the project. But if you run the application and analyze the item with Firebug, you will realize, that it’s now called “dijit_form_TextBox_0”.

Wouldn’t be a problem, if it would keep this id all the time, but it doesn’t! Every item, which’s id has a number in it, can change at runtime.

So the best way to identify those elements is using xpath. (I didn’t have problems with button id’s)

1. Using the Selenium IDE to get xpath or id of an element

  • Run the application and hit CTRL + ALT + S to open the Selenium IDE

  • The Selenium IDE should now use the project’s URL and be in record mode
  • Click the Item text box, enter some text and hit Enter
  • The Selenium IDE should now show two commands

  • Click the type command to show it’s details.

  • You see, the type command uses the id “dijit_form_TextBox_0”, which we don’t want to use.
  • Click the Target select menu to show all available methods for identifying the text box element. You will see, except of one, they are all containing “…TextBox_0…”. So let’s trust that single one which doesn’t  😉
  • Code line in Java Service: WebElement textBoxItem = wait.until(ExpectedConditions.elementToBeClickable(By.xpath(“//input“)));

  • Close Selenium IDE

2. Using Firebug to get xpath of an element

  • On the running application’s window, right-click the Item text box and “Inspect Element with Firebug”

  • Now the console will open and highlight the part of code which was generated for the text box’s input field

  • Now just hover your cursor over the text in that highlighted area and you will see the complete xpath expression

  • Unfortunately, I didn’t find a way to copy & paste that expression, so you have to write it down
  • Code line in Java Service: WebElement textBoxItem = wait.until(ExpectedConditions.elementToBeClickable(By.xpath(“/html/body/div/div/div/div[2]/div[2]/div[3]/div/div/div[2]/div/input“)));

Ok, that’s it so far. I will keep trying some other cool stuff and hopefully I soon have something more to share 🙂

Have fun, kindest regards

Tobi

Download the sample project

Selenium Sample Project
Selenium Sample Project
Selenium_Integration_01.1.Alpha1.zip
22.0 MiB
Details...
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.

De Vcoportal Part7
De Vcoportal Part7
de.vcoportal.package_part7.package
126.3 KiB
Details...
Page 1 of 41234