Start a Conversation

Unsolved

This post is more than 5 years old

7841

January 7th, 2011 20:00

HOWTO Make a PowerShell server side VMware Virtual Center Plugin

The post below is meant to give an idea of how one would go about creating a VMware Virtual Center plugin.  The post will demonstrate how to create a VC plugin for visibility of external sites specific to objects in VC, and allow you to perform actions on objects by way of menus.  It as well leverages the task manager as the bottom of VC to show status and for now solely to show that the process has completed.  This is different from other plugins because it leverage, JSP and Powershell to create a plugin that exists on the VC server.  This is great because there are no client installs, and we can create a commercial grade plugin which can perform operations per object.

What you are going to see is really meant to serve as a specific example soup to nuts on how to get a plugin up and running.  However, you can pick the process apart and apply it to whichever language, or use case you would like.  If you’re in a hurry, then Phase 1, 3, and 7 will do it all!

I would hope that this document would be used more for lab environments and non-production systems.  My goal with releasing this information is to enable the VMware community with the some easy to use instructions for VC plugins in order open the doors to those creative posher’s that haven’t had a medium to bring their innovative ideas to VC.

I am going to go about this in a different order than you might suspect because I am assuming that you already have a PowerShell script or commands ready that output what you want to see in VC.  If not, don’t worry I have a couple of examples to use to get you started.

The phases will progress from basics to the more complex end and highly dynamic state which can be used and modified to serve just about any VC plugin need.

Please refer to the document attached below for images and screenshots referenced in the post.

Phase 1 – Register a new plugin with VC

http://read.virtualizeplanet.com/?p=352

http://virtualizeplanet.com/wordpress/wp-content/plugins/download-monitor/download.php?id=12

I am mostly going to refer to Virtual Planet for this one since they wrote an application that talks via VMware API’s to VC to register a new plugin.  I will show you by example below how to make it work.   However, there are ways to do this via Powershell and others, but I’m not going to focus on that in this post.

Launch the Plugin Wizard application

Start -> VirtualizePlanet -> Plugin Wizard

Enter Step 1 XML Config information

This step asks for certain information that will be displayed under Plugin Management and how it will be displayed as a tab in VC.  This first step will actually build the XML file that is requested every time  VC client opens.  It is asking for some information here, but I will show you how to modify it later, so don’t worry too much about what Step1 says.  The three important fields are “Title” (what text will show up on tabs in VC), “The URL you want to open” (what script should VC post relevant information to and execute), and “Position of Plugin Tab” (what object should the tab be displayed on).

Save XML

Once the information is filled in, press Save XML Plugin.  It will ask for a location, save it somewhere you can reference when it comes time to copy the XML file to its end location.

The Step 2 tab at the top of the plugin asks for information that will be stored with VC by way of API’s and the plugin registration process.  The critical fields here are the “Name in PluginManager (how it is listed) and “Url to XML file” (what XML file is opened everytime VC is freshly launched to see how to lay out tabs and executions).  The XML file in the previous step is what will be referenced below under “Url to XML file” but we will rename it to a JSP page.  You should enter the information (relevant to your site) as you see it below if following the guide.  Press the GO button and the registration process will complete with a “Finished” dialogue.

That’s it! The plugin is officially registered and will be listed automatically under the plugin manager.  When you browse the HostSystem objects you will see the tab listed.

Phase 2 – Prepping Powershell and PowerCLI

Phase 2 - Step 1

This phase involves ensuring that powershell will run properly when needed.  I work in the lab environment mostly, so in order to simplify things I set the execution-policy to unrestricted.  By the way have you installed PowerCLI 4.1.1? If not please search google for it and download and install it.

                           

Setting the execution policy

Do the following procedure once for PowerShell and once for PowerCli

Start -> type powershell in run box -> at top right click powershell (x86) -> Run as Administrator

Enter “set-executionpolicy unrestricted”  and press “Y” to allow any script to run.

Phase 3 – Copying and Testing JSP/PS Scripts

Phase 3 – Step 1

So if you’ve gotten past the previous couple steps, you’re almost done and this is where the real fun begins.  The next thing that we are going to do is copy the relevant scripts to our server that does the processing.  For this example I am using the VC 4.1 server and have written JSP’s to be able to run under Tomcat.  And don’t worry if you don’t know JSP, I have examples that will help you through it.

Rename XML file to  JSP

Open the directory where you saved the XML file that was produced in Phase 1.  Let’s rename the extension to “.jsp”.

Copy JSP XML file and cust_get_ps.jsp to VC server

Any which way you can you want to get the JSP file to the VC server under the following directory.

\Program Files\VMware\Infrastructure\tomcat\webapps\ROOT

Testing that the JSP XML file works

Open Internet Explorer or any browser and enter the address of the VC server where you copied the JSP XML file with “:8443/cust_get_ps_xml.jsp” on the end.  The “cust..” portion will be the filename that you created.

Example - https://ip:8443/cust_get_ps_xml.jsp

The page should return something looking like “com.vmware.pubs.sdkteam Custom PS Plugin Custom false..” and the image below.  If you right click and say View Source, you will see the XML file contents exactly as it was before copying.

BTW.. Below is what it looked like before moving it to the server, so you can see it’s exactly the same after renaming to JSP.  I ran into some caching behavior, I think, due to Tomcat displaying static files with extensions that dictate static pages.

Done! This is the file that VC will load everytime a VI client opens that describes what Tabs,etc. to paint for this plugin.

Testing that the JSP executing PS  works

Open Internet Explorer or another browser again and reference the following link.

https://ip:8443/cust_get_ps.jsp

This will execute a JSP page that calls a powershell script to show the enumeration of a date object in an HTML table like the screenshot below.  If not then you’ve got some troubleshooting to do!

Did it look something like this?

If it did, then it’s because the PowerShell script had a problem executing.  In my case when going through this I got the error due to the wrong version of PowerCLI being installed (<4.1.1.).  I came this to conclusion by taking the command that is was outputted in the window and pasting it into a “cmd” window and looking at the results.

Troubleshooting execution

As you can see the script was missing a vim.psc1 file being in a certain location and it was fixed by downloading and installing the latest PowerCLI.  This however is great example of how you will be troubleshooting the script going forward.  Unfortunately , errors from Pshell will cause the process to hang when it is executed from a JSP.  So the real scripts I use have a variable set that suppresses all errors from PowerShell.  If you do have a script hang, you can always uncomment the cmd write line of the script to display it on the screen.  Key here though is to kill powershell so the command can finish and JSP can output the cmd.  A powershell command for this to do it in mass is “stop-process –processname powershell”.

Below is another error I got due to not setting execution policy (as described in prep section) under the administrator user.

Phase 3 – Step 2

Breaking the cust_get_ps.jsp script down

cust_get_ps.jsp

<%@ page   contentType="text/html; charset=iso-8859-1"   language="java" import="java.util.*, java.io.*" %>

<%

// the instantiation of   our command that gets execute by JSP   

String cmd =   "c:\\windows\\syswow64\\WindowsPowerShell\\v1.0\\powershell.exe -psc   \"C:\\Program Files (x86)\\VMware\\Infrastructure\\vSphere   PowerCLI\\vim.psc1\" -Command \"& {";

// try to remove as many   errors as possible-- pshell errors cause powershell to hang, only ones that   would come up should be due to having a || or ;| --watch for concatenation of   cmd lines

cmd = cmd +   "$ErrorActionPreference = 'SilentlyContinue';";

// the styling for   powershell table

cmd = cmd + "$a =   '';";

// the powershell script

cmd = cmd +   "get-date";

// watch to make sure   line before doesn't have ;

// take the output and   place it in a nice html table with the formatting specified above

cmd = cmd + " |   convertto-html -head $a}\"";

// execute the command   and output the data to the print.. this can hang and leave a powershell   process running if there is an error generated from pshell.. I have supress   errors on above, and this way of executing doesn't like 2>&1, only   errors should be due to || or ;|

Process proc =   Runtime.getRuntime().exec(cmd);

proc.getOutputStream().close();

InputStream inputstream =   proc.getInputStream();

InputStreamReader   inputstreamreader = new InputStreamReader(inputstream);

BufferedReader   bufferedreader = new BufferedReader(inputstreamreader);

String line;

while ((line =   bufferedreader.readLine()) != null) {

                out.print(line);

}

// for troubleshooting   enable this, if script is hanging via tomcat then kill all powershells and   the line below will show in the browser.. then excute the command below   manually from cmd.. "stop-process -processname powershell"

                     out.println(cmd);

%>

Phase 4 – Testing the Plugin

If you’ve gotten this far then you’re ready to see your plugin in action.  Go ahead and open VI client pointed at the server that have been working with through the example.

Is the plugin registered?

Once it loads check that the plugin is listed uner Plug-Ins -> Manage Plug-Ins

If it isn’t listed then you need to go back to Phase 1 for registering the plugin.  If it doesn’t say enabled and there is an error in the description then you need to check the paths that were registered as part of Phase1 and compare them to what you just tested.  An error here usually means VC can’t get to the paths that are registered to this plugin to find the XML file.

Check the plugin

So if you see it listed then you’re ready to go.  On the left side, click an ESX host.  From there you will see the window open on the right with a handful of tabs, on the right side should be our plugin called “Cust-get_ps”.  Go ahead and click it.  What should be displayed at this point is exactly the same as the screenshot where you ran the JSP file from the webserver previsouly showing the date in a formatted table.

If so then congrats! You have a working (maybe first) Virutal Center plugin!  The plugin of course at this state isn’t of much value since it is only showing the date, but if you’re interested let’s move into the real meaty stuff and get some value into that plugin.  I commonly come back to this basic state to test things out to ensure that Powershell is executing as I expect it via JSP.

Phase 4 – Gathering data for VC related functions (optional)

This portion is really what most people are coming for and is where I think you may find the most value.  We’ve done some good stuff so far though.  We have a working plugin in VC via JSP launching Powershell scripts.

There is however a few things that we are missing from the puzzle to have a script act on what you see above in a meaningful way.  What we know is that the script is being executed from a certain portion of VC and executed based on an object.  For example what you see above is that the script is being executed due to the ESX host listed on the left (the object).  Now the key part here is to take that gathe that information along with some other pieces and use it to post relevant information for that object as part of the Pshell script.

The other information missing along with the object is, vCenter server, and vCenter session.  In order for the script to be able to do anything we need the object to act on, what vCenter server the request came from, and credentials to be able to get access to that VC server.  Luckily these are all items that are POSTed to the JSP script and I’m going to show you the scripts that I wrote to retrieve and use them.

What exactly is coming from VC that JSP needs to parse?

In order to see the actual posted variables you must edit the XML JSP file above to point to the the following JSP page (or play a shell game and rename files).  I am going through this section because it can be very useful to grab session information and the actual “moref”  that is being passed from VC to your ASP page.  I will use it after this section to show how we can figure out what object the “moref” is referring to.

Below is the enumeration script that can be copied to the server which should be referenced as the under the XML JSP script for “URL display”.

cust_post_enumerate.jsp

<%@ page contentType="text/html;   charset=iso-8859-1" language="java" import="java.util.*,   java.io.*" %>

<%

  Enumeration eParams  = request.getParameterNames();

  while(eParams.hasMoreElements())

  {

    String strParam = (String)eParams.nextElement();

%>

 

 

 

 

<%

  }

%>

<%= strParam %> <%=   request.getParameter(strParam) %>

As you can see a very simple script that just enumerates through all posted variables and outputs them.  You can see in the screenshot below that we are posting “moref” and “serviceUrl” and the script outputs them on lines as they were entered.  Now let’s see what this looks like from VC!

Below is the XML JSP file edited to point to the enumeration script so we can get a sneak peak at what is being posted.  So, edit the file and then close and reopen VC and check the plugin output.

Once you have VC launched again, click an ESX host object and then hit the Cst-get_ps tab again.  You will now see the output of that enumeration but with 4 lines.  This is the goldmine!  These are the key items that our script needs to know in order to do 1) get authentication to the VC server 2) to find the object we are talking about and then 3) do whatever else VMware related with that object via Powershell.

Let’s do something useful with that information

Keep in mind that the authentication information (sessionId) is only valid when the VC session you got it from is running!  Sound cool?  So the plugin is actually reusing the VC session you are logged into’s authentication session for VC access.

The next step is to make use of the information that we now have, see the next script which will use the authentication information to lookup what object the “moref” is referring to.

cust_get_ps_esxhost.jsp – new stuff in bold

<%@ page   contentType="text/html; charset=iso-8859-1"   language="java" import="java.util.*, java.io.*" %>

<%

// the instantiation of   our command that gets execute by JSP   

String cmd =   "c:\\windows\\syswow64\\WindowsPowerShell\\v1.0\\powershell.exe -psc   \"C:\\Program Files (x86)\\VMware\\Infrastructure\\vSphere   PowerCLI\\vim.psc1\" -Command \"& {";

// the POSTed   variables that VC sent so we can later go back and reuse the same session to   get access to VC, find what object was clicked, and then do whatever needed

String serviceurl =   request.getParameter("serviceUrl");

String moref =   request.getParameter("moref");

String sessionId =   request.getParameter("sessionId");

// parse out the   POSTed variables to whats needed

String[] arrserviceurl   = serviceurl.split("/");

String[] arrmoref =   moref.split(":");

// try to remove as many   errors as possible-- pshell errors cause powershell to hang, only ones that   would come up should be due to having a || or ;| --watch for concatenation of   cmd lines

cmd = cmd +   "$ErrorActionPreference = 'SilentlyContinue';";

// reuse vc session   that VC passed to the JSP page

cmd = cmd +   "connect-viserver -Notdefault -warningaction 0 -erroraction 0 -server   " + arrserviceurl[2] + " -session " + sessionId + "|   out-null;";

// figure out which   object VC passed from mouse click

cmd = cmd +   "$esxhost=(get-vmhost -server " + arrserviceurl[2] + " |   get-view | where { $_.MoRef -match '" + arrmoref[1] + "' }   ).Name;";

// convert the   hostname to ip to use hosts DNS instead of client

cmd = cmd +   "$esxip=[system.net.dns]::gethostaddresses($esxhost)[0].IPAddressToString;";

// the styling for   powershell table

cmd = cmd + "$a =   '';";

// the powershell script

//cmd = cmd +   "get-date";

cmd = cmd + "write   $esxip";

// watch to make sure   line before doesn't have ;

// take the output and   place it in a nice html table with the formatting specified above

//cmd = cmd + " | convertto-html   -head $a}\"";

cmd = cmd +   "}\"";

// execute the command   and output the data to the print.. this can hang and leave a powershell   process running if there is an error generated from pshell.. I have supress   errors on above, and this way of executing doesn't like 2>&1, only   errors should be due to || or ;|

Process proc =   Runtime.getRuntime().exec(cmd);

proc.getOutputStream().close();

InputStream inputstream =   proc.getInputStream();

InputStreamReader   inputstreamreader = new InputStreamReader(inputstream);

BufferedReader   bufferedreader = new BufferedReader(inputstreamreader);

String line;

while ((line =   bufferedreader.readLine()) != null) {

                out.print(line);

}

// for troubleshooting   enable this, if script is hanging via tomcat then kill all powershells and   the line below will show in the browser.. then excute the command below   manually from cmd.. "stop-process -processname powershell"

//                  out.println(cmd);

%>

Take this information and post it manually to the script!

Ok so you’ve seen that there really isn’t much being added but we have done exactly what we needed to in order to make the script functional.  We now have as an output the object that was referenced as the “moref” and we have access in the future to be able to run PowerCLI commands against the VC server.

Go ahead and open a web browser again and point it to the below url.  However, replace what we have after serviceUrl, moref, and sessionId with what was returned from your VC.

https://10.28.129.40:8443/cust_get_ps_esxhost.jsp?serviceUrl=https://10.28.129.40/sdk&moref=HostSystem:host-176&sessionId=B2457954-A3AE-436B-99A5-8282684CBF16

What you should get is something like the screenshot below.  What is that IP? That’s the IP of the ESXhost that we selected under VC.  Great, so now we have all we need to continue!

Phase 5 – Applying the Powershell VC Plugin to a real script

If you’ve made it through everything so far then you’ve been through a lot.  What I’m going to highlight next is the use of a powershell script that I wrote that pulls ESXtop data via get-esxtop and does calculations/deltas to give useful per sampling information.

Copy cust_get_esxtop_adapters.ps1

The first step to make this work is to create a location on the system ie c:\scripts and copy the cust_get_esxtop_adapters.ps1 script to that directory for later execution.

An updated JSP – cust_get_esxtop.jsp (bold is new)

See the script below.  There are two new sections which are going to deliver all of our value add.  One is more authentication in the form of a hash table so we can look up what ESX passwords to use based on what VC system we are talking to (since esxtop is directed at ESXhosts).  And the other is the powershell script that we will be executing with the dynamic portions in the target esxhost and the password for that host.

<%@ page   contentType="text/html; charset=iso-8859-1"   language="java" import="java.util.*, java.io.*" %>

<%

// the instantiation of   our command that gets execute by JSP   

String cmd =   "c:\\windows\\syswow64\\WindowsPowerShell\\v1.0\\powershell.exe -psc   \"C:\\Program Files (x86)\\VMware\\Infrastructure\\vSphere   PowerCLI\\vim.psc1\" -Command \"& {";

// the POSTed variables   that VC sent so we can later go back and reuse the same session to get access   to VC,

find what object was   clicked, and then do whatever needed

String serviceurl =   request.getParameter("serviceUrl");

String moref =   request.getParameter("moref");

String sessionId =   request.getParameter("sessionId");

// parse out the POSTed   variables to whats needed

String[] arrserviceurl =   serviceurl.split("/");

String[] arrmoref =   moref.split(":");

// hash table to enter   passwords for ESX hosts (expecting same pass for each ESX host attached to   each VC) once we

determine which   object is being queried, only needed at the moment to do direct get-esxtop   queries, others should resuse

vc session

Hashtable password =   new Hashtable();

password.put("10.10.10.1","pass1");

password.put("10.10.10.2","pass3");

password.put("10.10.10.3","pass3");

// try to remove as many   errors as possible-- pshell errors cause powershell to hang, only ones that   would come up should be

due to having a || or ;|   --watch for concatenation of cmd lines

cmd = cmd +   "$ErrorActionPreference = 'SilentlyContinue';";

// reuse vc session that   VC passed to the JSP page

cmd = cmd +   "connect-viserver -Notdefault -warningaction 0 -erroraction 0 -server   " + arrserviceurl[2] + " -session " + sessionId

+ "|   out-null;";

// figure out which   object VC passed from mouse click

cmd = cmd +   "$esxhost=(get-vmhost -server " + arrserviceurl[2] + " |   get-view | where { $_.MoRef -match '" + arrmoref[1] + "' }

).Name;";

// convert the hostname   to ip to use hosts DNS instead of client

cmd = cmd +   "$esxip=[system.net.dns]::gethostaddresses($esxhost)[0].IPAddressToString;";

// the styling for   powershell table

cmd = cmd + "$a =   '';";

// the powershell   script

cmd = cmd +   "c:\\scripts\\cust_get_esxtop_adapters.ps1 -once -esxhost $esxip   -esxuser root -esxpassword " + password.get(arrserviceurl[2])  +"   -interval 5 -rollout | select   DeviceName,PathName,Datastore,NumOfCommands/s,NumOfReadOps/s,NumOfWriteOps/s,MBytesRead/s,MBytesWritten

/s,msPerReadGuest,msPerWriteGuest";

//cmd = cmd +   "get-date";

// watch to make sure   line before doesn't have ;

// take the output and   place it in a nice html table with the formatting specified above

cmd = cmd + " |   convertto-html -head $a}\"";

// execute the command   and output the data to the print.. this can hang and leave a powershell   process running if there is an

error generated from   pshell.. I have supress errors on above, and this way of executing doesn't   like 2>&1, only errors should be

due to || or ;|

Process proc =   Runtime.getRuntime().exec(cmd);

proc.getOutputStream().close();

InputStream inputstream =   proc.getInputStream();

InputStreamReader   inputstreamreader = new InputStreamReader(inputstream);

BufferedReader   bufferedreader = new BufferedReader(inputstreamreader);

String line;

while ((line =   bufferedreader.readLine()) != null) {

                out.print(line);

}

// for troubleshooting   enable this, if script is hanging via tomcat then kill all powershells and   the line below will show in the

browser.. then excute the   command below manually from cmd.. "stop-process -processname powershell"

//out.println(arrserviceurl[2]);

//out.println(sessionId);

//out.println(arrmoref[1]);

//out.println(cmd);

%>

Change JSP XML page to point at new JSP

Go ahead and change the JSP XML file to look something like the following in order to point back to the new script you created above.

Test the script

You can if you choose run the script that you just created above manually.  However, you need to go through the optional steps above and grab the relevant information that VC is posting to make the script work and incorporate them in the URL when you enter it in IE.  Feel free if you want to see it run outside of IE!

Launch the Powershell plugin

Go ahead and close and open VI client again towards the VC you’ve been working with.  From there you should go to the ESXhost object and choose the “Cust-get_ps” tab as you have been.

What you should see is something like the following.  A table showing all of your datastores and their relevant latency information that was chosen within the cust_get_esxtop script.

AND THAT’S IT!  You now have a pretty cool way to see relevant datastore stats from ESXtop within you’re a VC plugin.  The opportunities are now endless for fellow pshellers out there!

Note: Right click and refresh to get latest info, or make the JSP/HTML fancier! =)

Phase 6 – A more advanced JSP XML file

What we’ve done so far has opened the doors to some great stuff in the powershell world.  The next two phases are what really make the VC plugin dynamic, extensible, and similar to those commercial grade efforts you see out there.   So let’s go through what needs to happen to make the plugin extra functional which is going to around making the JSP XML file more dynamic.  First of all, I want to make the plugin show up on all menus and be a tab under all objects.  This will allow for the plugin to be useful on any object in the inventory.

For this example there are two more files to look at.   The first one below is the JSP XML which has been modified to make use of arrays containing all of the attach points that the plugin can be placed and builds out an XML file accordingly.  Notice how there are two iteration loops and we are simple going through the InventoryMenus array and the InventoryView array and creating proper XML files based on that information.  I have also included the enumeration script to be run for views, and the

cust_get_ps_xml.jsp

com.vmware.pubs.sdkteam

Custom   PS Plugin

Custom

false

<%

String[] HomeView =   {"Administration","Applications","Inventory","Management"};

String[] InventoryView =   {"Cluster","Datacenter","DatacenterFolder","Datastore","DatastoreFolder","DistributedVirtualSwitch","HostSystem",

"ComputeResourceFolder","Network","NetworkFolder","ResourcePool","Template","VirtualMachine",

"VirtualMachineFolder","VirtualService"};

String[] MainMenus =   {"Administration","Edit","File","File_Export","File_new","File_Report","Help","Inventory",

"Plugins","View","View_Inventory"};

String[] InventoryMenus =   {"Cluster","Datacenter","DatacenterFolder","Datastore","DatastoreFolder",

"DistributedVirtualSwitch","HostSystem","CopmuteResourceFolder","Network","NetworkFolder","ResourcePool",

"Role","ScheduledTasks","Tasks","Template","VirtualMachine","VirtualMachineFolder","VirtualService"};

String[] Toolbars =   {"Cluster","Datacenter","DatacenterFolder","Datastore","DatastoreFolder",

"DistributedVirtualSwitch","HostSystem","ComputeResourceFolder","Network","NetworkFolder","ResourcePool",

"Template","VirtualMachine"};

int i=0;

for(i=0;i

{

                out.println(" +   "\">");

                out.println(" Cust-get_ps");

                out.println(" https://" +   request.getHeader("host") +   "/cust_post_

enumerate.jsp?");

                out.println("");

}

for(i=0;i

{

                out.println(" +   "\">");

                out.println(" Cust-get_ps");

                out.println(" https://" +   request.getHeader("host") +   "/cust_ps_lookup_

exec_action.jsp?");

                out.println("");

}

%>

So what does it look like when you get this done?

Now what you can see from the above screenshots is that we have the plugin now showing up on all VC objects for view and actions to be performed!  Now the next step is to do something similar to what we did in previous steps where instead of leveraging the enumeration script, we leverage the moref lookup script as I showed in the script above.  Let’s see what that now looks like..

Cust_ps_lookup_moref.jsp

<%@ page   contentType="text/html; charset=iso-8859-1"   language="java" import="java.util.*, java.io.*" %>

<%

// the instantiation of   our command that gets execute by JSP   

String cmd =   "c:\\windows\\syswow64\\WindowsPowerShell\\v1.0\\powershell.exe -psc   \"C:\\Program Files (x86)\\VMware\\Infrastructure\\vSphere   PowerCLI\\vim.psc1\" -Command \"& {";

// the POSTed variables   that VC sent so we can later go back and reuse the same session to get access 

to VC, find what object was clicked, and then do whatever needed

String serviceurl =   request.getParameter("serviceUrl");

String moref =   request.getParameter("moref");

String sessionId =   request.getParameter("sessionId");

// parse out the POSTed   variables to whats needed

String[] arrserviceurl =   serviceurl.split("/");

String[] arrmoref =   moref.split(":");

// try to remove as many   errors as possible-- pshell errors cause powershell to hang, only ones that

  would come up should be due to having a || or ;| --watch for concatenation of   cmd lines

cmd = cmd +   "$ErrorActionPreference = 'SilentlyContinue';";

// reuse vc session that   VC passed to the JSP page

cmd = cmd +   "connect-viserver -Notdefault -warningaction 0 -erroraction 0 -server   " + arrserviceurl[2] +

" -session " + sessionId + "|   out-null;";

// figure out what the   object name is passed from mouse click (by moref)

cmd = cmd +   "$objectname=(get-view -server " + arrserviceurl[2] + " -id   " + arrmoref[0] + "-"

+ arrmoref[1] + ").Name;";

// the styling for   powershell table

cmd = cmd + "$a =   '';";

// the powershell   script

cmd = cmd +   "write $objectname}\"";

// execute the command   and output the data to the print.. this can hang and leave a powershell  

process running if there is an error generated from pshell.. I have supress   errors on above, and this

way of executing doesn't like 2>&1, only   errors should be due to || or ;|

Process proc =   Runtime.getRuntime().exec(cmd);

proc.getOutputStream().close();

InputStream inputstream =   proc.getInputStream();

InputStreamReader   inputstreamreader = new InputStreamReader(inputstream);

BufferedReader   bufferedreader = new BufferedReader(inputstreamreader);

String line;

while ((line =   bufferedreader.readLine()) != null) {

                out.print(line);

}

// for troubleshooting   enable this, if script is hanging via tomcat then kill all powershells and   the line

below will show in the browser.. then excute the command below   manually from cmd.. "stop-process

-processname powershell"

                //     out.println(cmd);

%>

Ok, great so now you see we have the plugin working on all objects, and we are actually doing a proper lookup to find out what the actual name of the moref is so we can perform scripts and do forwards to outside web apps with object related information.  This is where this script goes beyond a lot of what’ve you seen in other areas out there.  Instead of just opening links to a generic page for VMware, we are actually able to send object specific information along with it so we can get some specific information to show up that is useful for the object we are on.  Now let’s continue on to the best part, performing actions on these objects!

Phase 7 – Perform actions on the objects in VC

We showed in the previous step that there’s now a menu for the object.  We actually hinted a bit at the next script already when highlighting the previous phase.  What we are now going to do is go through a new JSP script that will perform the lookups for moref to object name, and then will actually work directly with the task manager at the bottom of the VC window.  This way we can show when something has been kicked off and that it got kicked off on the right object.

At the moment, I have not added custom tasks to VC, so I am going to be reusing the “import physical machine” task.  Yes, not quite polished but I think showing this functionality off will probably get some wheels spinning and either myself or someone else will have it done shortly =)

Now the script below isn’t actually going to be performing any actions, this is left up to you by this point.  I am assuming that you have gone through the steps above and will know exactly where to place the powershell command.

Cust_ps_lookup_exec_action.jsp

<%@ page   contentType="text/html; charset=iso-8859-1"   language="java" import="java.util.*, java.io.*" %>

<%

// the instantiation of   our command that gets execute by JSP   

String cmd =   "c:\\windows\\syswow64\\WindowsPowerShell\\v1.0\\powershell.exe -psc   \"C:\\Program Files (x86)\\VMware\\Infrastructure\\vSphere   PowerCLI\\vim.psc1\" -Command \"& {";

// the POSTed variables   that VC sent so we can later go back and reuse the same session to get access   to VC, find

what object was clicked, and then do whatever needed

String serviceurl =   request.getParameter("serviceUrl");

String moref =   request.getParameter("moref");

String sessionId =   request.getParameter("sessionId");

// parse out the POSTed   variables to whats needed

String[] arrserviceurl =   serviceurl.split("/");

String[] arrmoref =   moref.split(":");

// try to remove as many   errors as possible-- pshell errors cause powershell to hang, only ones that   would come up

should be due to having a || or ;| --watch for concatenation of   cmd lines

cmd = cmd +   "$ErrorActionPreference = 'SilentlyContinue';";

// reuse vc session that   VC passed to the JSP page

cmd = cmd +   "$vc=connect-viserver -Notdefault -warningaction 0 -erroraction 0   -server " + arrserviceurl[2] + "

-session " + sessionId +   "| out-null;";

// figure out what the   object name is passed from mouse click (by moref)

cmd = cmd +   "$objectname=(get-view -server " + arrserviceurl[2] + " -id   " + arrmoref[0] + "-" + arrmoref[1] + ").Name;";

// open the task manager   and add a new task

cmd = cmd +   "$taskmgr = get-view -server " + arrserviceurl[2] + "   taskmanager;";

// set parameters for   task and add task to taskmanager

cmd = cmd +   "$moref = (get-view -server " + arrserviceurl[2] + " -id   " + arrmoref[0] + "-" + arrmoref[1]

+ ").moref;";

cmd = cmd +   "$params =   @($moref,'com.vmware.converter.Import.P2V',$vc.user,$true,$null);";

cmd = cmd +   "$newtask =   $taskmgr.gettype().getmethod('CreateTask').invoke($taskmgr,$params);";

cmd = cmd +   "$taskview = (get-view -server " + arrserviceurl[2] + " -id   $newtask.task);";

cmd = cmd +   "$taskview.SetTaskState('running',$null,$null);";

cmd = cmd +   "$taskview.UpdateProgress('5');";

cmd = cmd +   "$taskview.UpdateProgress('100');";

cmd = cmd +   "$taskview.SetTaskState('success',$null,$null);";

// the styling for   powershell table

cmd = cmd + "$a =   '';";

// the powershell script

cmd = cmd + "write   $objectname}\"";

// execute the command   and output the data to the print.. this can hang and leave a powershell   process running

if there is an error generated from pshell.. I have supress   errors on above, and this way of executing doesn't

like 2>&1, only   errors should be due to || or ;|

Process proc =   Runtime.getRuntime().exec(cmd);

proc.getOutputStream().close();

InputStream inputstream =   proc.getInputStream();

InputStreamReader   inputstreamreader = new InputStreamReader(inputstream);

BufferedReader   bufferedreader = new BufferedReader(inputstreamreader);

String line;

while ((line =   bufferedreader.readLine()) != null) {

                out.print(line);

}

// for troubleshooting   enable this, if script is hanging via tomcat then kill all powershells and   the line below will

show in the browser.. then excute the command below   manually from cmd.. "stop-process -processname

powershell"

                     out.println(cmd);

%>

And here you have it below, an action on an object and an acknowledgement in the task view!

Phase 8 – The future!

This is all pretty exciting stuff for those that haven’t developed a plugin before.  I’m actually excited to have completed this writeup so that I can get back to the lab and start applying all of my powershell scripts to it to make some cool stuff happen.

If I was going to put on my technologist hat for this I would expect there to be a good amount of nuggets that get pulled from here and reused in other ways.  There seem to be a handful of firsts here.. taskmanager additions, dynamic JSP XML, VC plugin instantiated JSP->powershell execution, etc, etc.  Please feel free to reuse the code, and I am very interested to hear what you’re doing with it so drop me a line or post a question to this thread.

And as you’re probably wondering, can’t this be easier? Well yes of course, and I expect to have someone step up to automate a couple of things here and make a .net application for it.  But for those that are actually in the powershell world, I don’t think there’s much here that is very tough.  If you’re not concerned about how it all works, then do Phase 1,3, and 7 and you’re good to go!

References

https://www.vmware.com/support/developer/vc-sdk/visdk400pubs/sdk40programmingguide.pdf

Clint Kitson

@clintonskitson

EMC vSpecialist

3 Attachments

12 Posts

January 10th, 2011 07:00

Color me impressed! Great job Clint!

--

-a

7 Posts

January 10th, 2011 13:00

Very Nicely Done!!!

No Events found!

Top