mercoledì 16 aprile 2014

VMware: run PowerCLI on Android using a PHP back-end

I'm passionate about Android since the beginning, I still remember how cool it was my 7" tablet with Android 1.5 Cupcake the day I bought it about 5 years ago. Since then I spent a good amount of time, mostly during the evenings while studying for my MS in computer engineering, to develop for Android. It's been a couple years since my last Android related project so I decided to come up with a post which brings together two of the things I mostly like: VMware & Android.

After a bit of nostalgia in post introduction let me explain what we are going to do: we are about to create an Android application which allow us to write and run PowerCLI scripts directly from our phone/tablet. This is possible using a back-end PHP page that will receive PowerCLI commands and will run them returning back the output.

PHP back-end will run PowerCLI cmdlets by using shell_exec() function as it was in WebPowerCLI. Android app will be the front-end and will pass commands to the back-end by performing an HTTP Post.

This is just an example, a starting point from which you can develop something more interesting. Back-end URL is coded statically, as well as the Connect-VIServer cmdlet. You could improve this by introducing, for example, the capability for your users to select the back-end URL as well as the customization of Connect-VIServer cmdlet. From a security perspective, especially when used from outside your network, an SSL (possibly heartbleed-free) connection should be adopted in order to protect data transmitted from your Android device to the server.

Let's start by discussing a bit about the back-end PHP page. In order to properly work this web page must be hosted on a Windows IIS web server on which PowerCLI is installed. You can refer to WebPowerCLI instructions in order to setup your Windows server with IIS, PHP & PowerCLI.

The PHP back-end page code is quite simple:



As you can see all the heavy lifting is performed by this instruction:

 $query = shell_exec("$powercli")  

which executes executes PowerCLI and runs the passed commands.

The front-end is simple as well, HTTPPostActivity.java contains all the code while layout design is defined in layout/main.xml file. values/strings.xml contains all text strings used in the app. Using separate files for different tasks is a good practice that enormously increase code readability, this concept is related to MVC which I briefly explained in Dynamic reports using PowerCLI and AngularJS.

This code was written in Eclipse with ADT Plugin.

Download HTTPPostExample from GitHub

The following images depicts how our app will look like:



In HTTPPostActivity.java there are two elements noteworthy: the first is the postData() function which executes an HTTP post to the URL of the back-end PHP page.

This function is called in:

 this.postData("sendpowercli", inputCommandText.toString().replaceAll("#[^;]*", ""));  

where sendpowercli MUST reflect the POST variable expected in PHP page:

 $variable1=$_POST["sendpowercli"];  

while inputCommandText contains the PowerCLI code inserted by the user, accordingly trimmed in order to ignore PowerCLI comments and replacing new lines with ;.

The second element to pay attention to is the AsynchTask, this will execute the HTTP post in background without freezing the user interface and presenting a "loading in progress" pop-up.



 //Asynch Task  
 private class RunPowerCli extends AsyncTask<String, Void, String> {  
      @Override  
      protected String doInBackground(String... params) {  
           inputCommandText = inputText.getText().toString().replaceAll("\\n", ";"); //Every command must be separated using ;  
           this.postData("sendpowercli", inputCommandText.toString().replaceAll("#[^;]*", "")); //Ignore PowerCLI comments  
           return response;  
      }  
      @Override  
      protected void onPostExecute(String result) { //When execution completed set text  
           TextView txt = (TextView) findViewById(R.id.output);  
           txt.setText(response);  
           pd.dismiss();  
      }  
 }  

That's all!!

Nessun commento:

Posta un commento