In this series of post’s let’s start to explorer the Citrix XenServer SDK and how we can start to use it in different types of applications to build interesting solutions.

So, Let’s set the stage :).

To start delving into the SDK, lets create a SharePoint webpart that will list all virtual machines on a given XenServer and allow the user to stop, start and pause each virtual machine through the webpart UI.

Here is a screenshot of what the part will look like when finished. You can also get the WSP file below if you want to install it into your SharePoint rig to play around with it. Note that this just a prototype app, but I intend on extending it to additional functionality. If you want to download the SharePoint solution file you can get it here.

 

image

In order to make this web part more re-usable we are going to have to be able to set some properties specific to our environment. We can do that enabling custom properties on the webpart. Below is a screen shot of the properties window of the web part. This allows you to add a XenServer and the XenServer information so the webpart can be used with multiple XenServers.
image

 

So, in order to build this webpart we are going to use a couple of different technologies.

1) jQuery (This will allow us to make some ajax calls to a wcf service that return XenServer information.

2) WCF (Windows Communication Foundation). This is a really simple WCF get enabled service to return different XenServer information.

3) SharePoint WebPart Development. (I wont get to detailed in this, but we will be using WSPBuilder to package up the SharePoint solution and a feature receiver to create some needed files upon activation of the web part.

 

WCF Implementation

While we could strictly put all the XenServer SDK code directly in the web part, this would make it more difficult for perform ajax based query’s and make the interface much more post back based. To eliminate this, we are going to implement the XenServer API in a service layer (Seperate DLL), and then package that up in our solution deployment. Remember this is a sample app, so the service implementation is pretty bare bones (Something I plan on adding to).  Side Note: In order to get sharepoint to host WCF services I have included in the solution a DLL that is a virtual path provide to help with the hosting.

As with any WCF implementation, the first this we need to define is the interface for implementation. In this simple implementation all method will be REST aware and will return either a string or an XML response.

There are four main methods here that are of interest

1) GetVirtualMachines – This method will return a list of VirtualMachine objects and will accept parameters for the host, port, username and password 
2) StopVM – This method returns a Boolean stating weather or not the call was sucessful and will accept parameters for the host, port, username, password, and VM UUID.
3) StartVM - This method returns a Boolean stating weather or not the call was sucessful and will accept parameters for the host, port, username, password, and VM UUID.
4) PauseVM - This method returns a Boolean stating weather or not the call was sucessful and will accept parameters for the host, port, username, password, and VM UUID.

The definition of the Interface is below.

   1: [ServiceContract]

   2:     public interface IXenServer

   3:     {

   4:         [OperationContract]

   5:         [WebGet(ResponseFormat = WebMessageFormat.Xml)]

   6:         string ServiceStatus();

   7:         [OperationContract]

   8:         [WebGet(ResponseFormat = WebMessageFormat.Xml)]

   9:         List<Classes.VirtualMachine> GetVirtualMachines(string host, string port, string username, string password);

  10:         [OperationContract]

  11:         [WebGet(ResponseFormat = WebMessageFormat.Xml)]

  12:         bool StopVM(string host, string port, string username, string password, string XenServerVMUUID);

  13:         [OperationContract]

  14:         [WebGet(ResponseFormat = WebMessageFormat.Xml)]

  15:         bool StartVM(string host, string port, string username, string password, string XenServerVMUUID);

  16:         [OperationContract]

  17:         [WebGet(ResponseFormat = WebMessageFormat.Xml)]

  18:         bool PauseVM(string host, string port, string username, string password, string XenServerVMUUID);

  19:         [OperationContract]

  20:         [WebGet(ResponseFormat = WebMessageFormat.Xml)]

  21:         string GetVMStatus(string host, string port, string username, string password, string XenServerVMUUID);

  22:  

  23:     }

Now, in our Interface definition method GetVirtualMachine we specify that this method will return a list of VirtualMachine objects. This virtual machine object is simply a class that we need to define that has some properties on it, specifically a Name property, a description property, a UUID property and a Status property. The class definition with the properties is defined below. Remember since this is a WCF return class, we need to decorate the class with the datacontract attribute and for each property we want returned, they need to be decorated with the DataMember attribute.

   1: [DataContract]

   2:     public class VirtualMachine

   3:     {

   4:         [DataMember]

   5:         public string Name { get; set; }

   6:         [DataMember]

   7:         public string Description { get; set; }

   8:         [DataMember]

   9:         public string UUID { get; set; }

  10:         [DataMember]

  11:         public string Status { get; set; }

  12:     }

 

So now we have our Interface definition and our return class definition, now we can implement our class that adheres to the Interface definition.

   1: public class XenServer : IXenServer

   2:    {

   3:        internal XenAPI.Session GetSession(string host, int port, string username, string password)

   4:        {

   5:            try

   6:            {

   7:                XenAPI.Session _session = new XenAPI.Session(host, port);

   8:                _session.login_with_password(username, password);

   9:  

  10:                return _session;

  11:            }

  12:            catch (System.Exception loginError)

  13:            {

  14:                return null;

  15:            }

  16:        }

  17:        internal bool SessionLogout(XenAPI.Session Session)

  18:        {

  19:            Session.logout();

  20:            return true;

  21:        }

  22:  

  23:        public List<Classes.VirtualMachine> GetVirtualMachines(string host, string port, string username, string password)

  24:        {

  25:            System.Collections.Generic.List<Classes.VirtualMachine> _returnVirtualMachines = new System.Collections.Generic.List<Classes.VirtualMachine>();

  26:  

  27:            XenAPI.Session _session = this.GetSession(host, Convert.ToInt32(port), username, password);

  28:  

  29:            System.Collections.Generic.List<XenAPI.XenRef<XenAPI.VM>> _allVMs = XenAPI.VM.get_all(_session);

  30:            foreach (XenAPI.XenRef<XenAPI.VM> _xenRefVm in _allVMs)

  31:            {

  32:                XenAPI.VM _vm = XenAPI.VM.get_record(_session, _xenRefVm);

  33:                if (!_vm.is_a_template && !_vm.is_control_domain)

  34:                {

  35:                    Classes.VirtualMachine _newVm = new Classes.VirtualMachine();

  36:                    _newVm.Name = _vm.name_label;

  37:                    _newVm.Description = _vm.name_description;

  38:                    _newVm.UUID = _vm.uuid;

  39:                    switch (_vm.power_state)

  40:                    {

  41:                        case XenAPI.vm_power_state.Halted:

  42:                            _newVm.Status = "Halted";

  43:                            break;

  44:                        case XenAPI.vm_power_state.Paused:

  45:                            _newVm.Status = "Paused";

  46:                            break;

  47:                        case XenAPI.vm_power_state.Running:

  48:                            _newVm.Status = "Running";

  49:                            break;

  50:                        case XenAPI.vm_power_state.Suspended:

  51:                            _newVm.Status = "Suspended";

  52:                            break;

  53:                        case XenAPI.vm_power_state.Unknown:

  54:                            _newVm.Status = "Unknown";

  55:                            break;

  56:                    }

  57:                    _returnVirtualMachines.Add(_newVm);

  58:                    _newVm = null;

  59:                }

  60:            }

  61:            this.SessionLogout(_session);

  62:            _session = null;

  63:            return _returnVirtualMachines;

  64:        }

  65:  

  66:        public bool StopVM(string host, string port, string username, string password, string XenServerVMUUID)

  67:        {

  68:            XenAPI.Session _session = this.GetSession(host, Convert.ToInt32(port), username, password);

  69:  

  70:            XenAPI.XenRef<XenAPI.VM> virtualMachine = XenAPI.VM.get_by_uuid(_session, XenServerVMUUID);

  71:            if (virtualMachine != null)

  72:            {

  73:                XenAPI.VM.hard_shutdown(_session, virtualMachine);

  74:            }

  75:  

  76:            this.SessionLogout(_session);

  77:            _session = null;

  78:  

  79:            return true;

  80:        }

  81:  

  82:        public bool StartVM(string host, string port, string username, string password, string XenServerVMUUID)

  83:        {

  84:            XenAPI.Session _session = this.GetSession(host, Convert.ToInt32(port), username, password);

  85:  

  86:            XenAPI.XenRef<XenAPI.VM> virtualMachine = XenAPI.VM.get_by_uuid(_session, XenServerVMUUID);

  87:            if (virtualMachine != null)

  88:            {

  89:                XenAPI.VM.start(_session, virtualMachine, false, true);

  90:            }

  91:  

  92:            this.SessionLogout(_session);

  93:            _session = null;

  94:  

  95:            return true;

  96:        }

  97:  

  98:        public bool PauseVM(string host, string port, string username, string password, string XenServerVMUUID)

  99:        {

 100:            XenAPI.Session _session = this.GetSession(host, Convert.ToInt32(port), username, password);

 101:  

 102:            XenAPI.XenRef<XenAPI.VM> virtualMachine = XenAPI.VM.get_by_uuid(_session, XenServerVMUUID);

 103:            if (virtualMachine != null)

 104:            {

 105:                XenAPI.VM.suspend(_session, virtualMachine);

 106:            }

 107:  

 108:            this.SessionLogout(_session);

 109:            _session = null;

 110:  

 111:            return true;

 112:        }

 113:  

 114:        public string GetVMStatus(string host, string port, string username, string password, string XenServerVMUUID)

 115:        {

 116:            string _tmpStatus = null;

 117:            XenAPI.Session _session = this.GetSession(host, Convert.ToInt32(port), username, password);

 118:  

 119:            XenAPI.XenRef<XenAPI.VM> virtualMachineObject = XenAPI.VM.get_by_uuid(_session, XenServerVMUUID);

 120:            if (virtualMachineObject != null)

 121:            {

 122:                XenAPI.VM virtualMachine = XenAPI.VM.get_record(_session, virtualMachineObject);

 123:                switch (virtualMachine.power_state)

 124:                {

 125:                    case XenAPI.vm_power_state.Halted:

 126:                        _tmpStatus = "Halted";

 127:                        break;

 128:                    case XenAPI.vm_power_state.Paused:

 129:                        _tmpStatus = "Paused";

 130:                        break;

 131:                    case XenAPI.vm_power_state.Running:

 132:                        _tmpStatus = "Running";

 133:                        break;

 134:                    case XenAPI.vm_power_state.Suspended:

 135:                        _tmpStatus = "Suspended";

 136:                        break;

 137:                    case XenAPI.vm_power_state.Unknown:

 138:                        _tmpStatus = "Unknown";

 139:                        break;

 140:                }

 141:            }

 142:  

 143:            this.SessionLogout(_session);

 144:            _session = null;

 145:  

 146:            return _tmpStatus;

 147:        }

 148:  

 149:        public string ServiceStatus()

 150:        {

 151:            return "Running";

 152:        }

 153:  

 154:    }

 

Lets examine the GetVirtualMachinesmethod here start to dig into the XenServer API.

The first thing we need to do is to get a session to the XenServer server. Everything in Xen works on the session so we need to create/attach to one :) The following line will do that (along with the internal function).

internal XenAPI.Session GetSession(string host, int port, string username, string password)

        {

            try

            {

                XenAPI.Session _session = new XenAPI.Session(host, port);

                _session.login_with_password(username, password);

 

                return _session;

            }

            catch (System.Exception loginError)

            {

                return null;

            }

        }

In the helper function above, we create a new session object by passing in the host and port of the XenServer we would like to connect to. By default you can connect to port 80 on a standard XenServer install.
Once connected to the XenServer, we wil lneed to login to the session with a specified username and password. If that goes smoothly then we now have a session that we can start to manipulate.
 
XenAPI.Session _session = this.GetSession(host, Convert.ToInt32(port), username, password);

After we have retrieved a session from our XenServer, the next step would be to list the Virtual Machines that are located on the box. That can be accomplished by making the following call
System.Collections.Generic.List<XenAPI.XenRef<XenAPI.VM>> _allVMs = XenAPI.VM.get_all(_session);

Ok, so lets break this down, this is returning a list of XenRef objects which contains a list of VM objects. Not so bad. So now we have our lists of lists of VM’s :) we can now do something with it, say loop through it.
foreach (XenAPI.XenRef<XenAPI.VM> _xenRefVm in _allVMs)

           {

               XenAPI.VM _vm = XenAPI.VM.get_record(_session, _xenRefVm);

               if (!_vm.is_a_template && !_vm.is_control_domain)

               {

                   Classes.VirtualMachine _newVm = new Classes.VirtualMachine();

                   _newVm.Name = _vm.name_label;

                   _newVm.Description = _vm.name_description;

                   _newVm.UUID = _vm.uuid;

                   switch (_vm.power_state)

                   {

                       case XenAPI.vm_power_state.Halted:

                           _newVm.Status = "Halted";

                           break;

                       case XenAPI.vm_power_state.Paused:

                           _newVm.Status = "Paused";

                           break;

                       case XenAPI.vm_power_state.Running:

                           _newVm.Status = "Running";

                           break;

                       case XenAPI.vm_power_state.Suspended:

                           _newVm.Status = "Suspended";

                           break;

                       case XenAPI.vm_power_state.Unknown:

                           _newVm.Status = "Unknown";

                           break;

                   }

                   _returnVirtualMachines.Add(_newVm);

                   _newVm = null;

               }

           }

 
 
 
 

JQuery Implementation:

Using JQuery in a SharePoint web part is pretty simple, well, simple with a few helper functions :). The basic jist here is you will have to inject the JQuery script tag into the sharepoint page that the webpart is on from the webpart code. Use can use this same method to include any JQuery plugin’s that you want to use in your webpart. In our example we are going to use the following JQuery files.

1) JQuery-1.3.2.js (Main JQuery file)

2) impromptu.js ( JQuery plugin that enables a login box to appear when clicking on the actions for each VM)

3) jquery.datatable.js (JQuery plugin that enables a databound datagrid) 
4) XenServerVMManegment.js (WebPart JavaScript responsible for making all the AJAX calls to the SCF services, etc)

Once you have the file in your WSPBuilder project, you are going to have to write code to inject the script tags into the sharepoint page where the part lives on I use two helper functions that allow me to add both JS files and CSS files dynamically from code. They are as follows.

Helper function to add JavaScript files to the SharePoint page.

public static void RegisterScript(string scriptPath, WebPart webpart)

{

    string IncludeScriptFormat = @"<script language=""{0}"" src=""{1}""></script>";

    if (!webpart.Page.ClientScript.IsClientScriptBlockRegistered(scriptPath))

    {

        string includescript = String.Format(IncludeScriptFormat, "javascript", scriptPath);

        webpart.Page.ClientScript.RegisterClientScriptBlock(webpart.GetType(), scriptPath, includescript);

    }

}

Helper function to add CSS files to the SharePoint Page.

public static void RegisterCSS(string cssPath, WebPart webpart)

        {           

            ContentPlaceHolder _Header = (ContentPlaceHolder)webpart.Page.Master.FindControl("PlaceHolderAdditionalPageHead");

            if (_Header != null)

            {

                CssRegistration cssControls = new CssRegistration();

 

                cssControls.Name = cssPath;

                

                _Header.Controls.Add(cssControls);

            }

        }

 

Once you have these two helper functions in your webpart code, you can add the following code to the CreadChildControls method in your webpart code. By using the methods above, it will allow us to register our scripts and CSS so we can then start using them within the sharepoint webpart.

RegisterScript(this.StripHTTPAndServer(_classResourcePath) + @"\JS\jquery-1.3.2.js", this);

RegisterScript(this.StripHTTPAndServer(_classResourcePath) + @"\JS\jquery.dataTables.js", this);

RegisterScript(this.StripHTTPAndServer(_classResourcePath) + @"\JS\impromptu.js", this);

RegisterScript(this.StripHTTPAndServer(_classResourcePath) + @"\JS\jquery.throbber.js", this);

RegisterScript(this.StripHTTPAndServer(_classResourcePath) + @"\JS\XenServerVMManagement.js?nocache=" + System.DateTime.Now.ToString("MMddyyyyhhmmss"), this);

 

So after the webpart has been loaded and shows up in the sharepoint page, the JavaScript/JQuery will now kick off.

//JQuery, when the DOM document is ready call a specific function.

$(document).ready(customReadyFunction);

 

//Document ready function. This is the function we tell JQuery to execute when the DOM is ready to reaverse.

function customReadyFunction() {

    //Create the data table.

    xenServerVMDataTable = $("#xenServerVMMachines").dataTable();

 

    //call the WCF service to get all VM's

    var serviceURL = "/_XenServerWCF/XenServer.svc/GetVirtualMachines?host=" + xsServer + "&port=" + xsPort + "&password=" + xsPassword + "&username=" + xsUsername;

    $.ajax({

        url: serviceURL,

        type: 'GET',

        dataType:'xml',

        success:getXenServersSuccessCallback,

        failure:getXenServersFailureCallback

    });

}

The JQuery/JavaScript above sets up and calls a custom function when the DOM is ready. This custom function is responsible for calling the WCF XenServer Service via an AJAX call.

SharePoint:

While the majority of the code resides in the JavaScript files, there are a couple of items we can touch on related to sharepoint.

The first is we have defined several custom properties that will allow the users to change XenServer settings. Like the following.

[Personalizable(PersonalizationScope.Shared)]

[WebBrowsable(true)]

[System.ComponentModel.Category("XenServer Settings")]

[WebDisplayName("XenServer Host Name (or IP)")]

[WebDescription("This field should be the netbios name or IP address of you XenServer")]

public string XenServerHost 

 

[Personalizable(PersonalizationScope.Shared)]

[WebBrowsable(true)]

[System.ComponentModel.Category("XenServer Settings")]

[WebDisplayName("XenServer Host Port")]

[WebDescription("This is port or your XenServer that is listening for requests (Typically 80/443)")]

public int XenServerPort 

 

 

[Personalizable(PersonalizationScope.Shared)]

[WebBrowsable(true)]

[System.ComponentModel.Category("XenServer Settings")]

[WebDisplayName("XenServer Username")]

[WebDescription("This should be a username on your XenServer that will be used to traverse and obtaing a list of Virtual Machines.")]

public string XenServerUsername

 

[Personalizable(PersonalizationScope.Shared)]

[WebBrowsable(true)]

[System.ComponentModel.Category("XenServer Settings")]

[WebDisplayName("XenServer Password")]

[WebDescription("This should be the password to the above XenServer username.")]

public string XenServerPassword

Along with these, we also have a feature receiver, which take on the function of creating some specific directories and files to enable the WCF services and registering some http models.

Ok, that’s a brief overview of the webpart, but i am going to break each part of this post out into more detailed posts each one can be targeted at each technology.

Feel free to comment or contact be via twitter (twitter.com/johnmcbride) and through comments on this blog.

JohnMcBride on June 15th, 2009

Before we get into this post, I first want to state I fully understand that both Visual Studio 2010 and the ASP.NET MVC out of band installer are beta products, so this issue may be fixed, but i wanted to put it out there to see if anyone else has encountered a similar problem. This is an open ended post as I am searching for answers on this issue, but will continue to research this as I have time. If you have any suggestions or a fix drop me a line and we can chat.

The Problem: When creating a out of the box MVC application and adding a custom class to the model folder, trying to reference that data class within a view causes Visual Studio 2010 and the VisualStudio Web Server to crash. The same application works fine with Visual Studio 2008.

Lets show an example.

Visual Studio 2008

In Visual Studio 2008 let create a new MVC application. Create or dont create the test cases, it doesnt really matter.
image

Once the application is created, Lets add a class to our model folder, with the following definition.

   1: public class TestFolder

   2:     {

   3:         public string Name { get; set; }

   4:     }


Now, Lets go ahead and create a new controller from the VS UI. Right click on the Controllers folder and select Add->Controller. Let call this controller TestContoller so we can access the page from a new URL.

image

In this new controller class we need to create an instance of our TestFolder class so that the view can traverse it. Here is the code for the controller class.

   1: public class TestController : Controller

   2:    {

   3:        //

   4:        // GET: /Test/

   5:        List<Models.TestFolder> myFolder;

   6:        public ActionResult Index()

   7:        {

   8:            myFolder = new List<MvcApplication2.Models.TestFolder>();

   9:            myFolder.Add(new MvcApplication2.Models.TestFolder { Name="Folder one" });

  10:            myFolder.Add(new MvcApplication2.Models.TestFolder { Name = "Folder two" });

  11:            myFolder.Add(new MvcApplication2.Models.TestFolder { Name = "Folder three" });

  12:            myFolder.Add(new MvcApplication2.Models.TestFolder { Name = "Folder four" });

  13:            //Response.Write("<h1>Test Controller PAGE</h1>");

  14:            return View("Test", myFolder);

  15:        }

Now, lets add a view, right click anywhere in the controller class we have just created and AddView. We need to make sure that we select the strongly typed view (our TestFolder class ) and select the list as the view content.

Here is the View Code

   1: <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcApplication2.Models.TestFolder>>" %>

   2:  

   3: <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">

   4:     Test

   5: </asp:Content>

   6:  

   7: <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

   8:  

   9:     <h2>Test</h2>

  10:     <%foreach (var folder in Model)    { %>

  11:     <h1><%= folder.Name %></h1>

  12:     <%} %>

  13: </asp:Content>

Now, we can run the application and navigate to the http://servername/Test controller and you should see the following.

image

All is working fine, the MVC app

 

Visual Studio 2010

If we follow the exact same scenario above but ue Visual Studio 2010 with the MVC extensions and we run it in debug mode we get the following errors.

 

Visual Studio 2010 crashes and restarts.

The Visual Studio Development Web Server crashes as well, but the following screenshots.

image

In addition to this these are logged in the Windows event viewer.

image

 

This is an open ended post as I am searching for answers on this issue, but will continue to research this as I have time. If you have any suggestions or a fix drop me a line and we can chat.

JohnMcBride on June 4th, 2009

As developers, we are always looking for platforms to build upon right? Did you know that Citrix can be viewed as a developer platform? I think many enterprises still view Citrix as the infrastructure company (Although, that view has been gradually changing over the last few years) that they have come to love. I believe those enterprise and the enterprise developers in them need to start looking at Citrix as a developer platform and realize that they can start building better experiences for the end users, weather it be IT Admins or the traditional end users. Citrix can be viewed as and *is* a developer platform, specifically one that needs to start being built upon.

If we think of Microsoft, we think traditionally of a system where a developer can pretty much tap into as much stuff as he wants (in addition to the Steve Ballmer Developers Developers Developers speech! :)). They have an enormous API set for windows itself, and for the most part, every product they produce has a “Developer Story”. Some examples of this are Office has the VSTO model, Want to host Windows Workflow Designer in your custom app, no problem, Need to talk to SharePoint, use the Web Services.  This developer focus is what enables so many people to write for the windows platform.

Now, if we look at Citrix, they have a similar story, although its not promoted as much as the Microsoft Developer focus. One that I feel needs to be promoted more, and hence this article :). For example, did you know that Citrix has a total of 34 SDK’s that are available to developers? Everything from XenApp to Password Manager to NetScaler. I have tried to break them out below. To download them, you can go to the community site over here

Category Related # of SDK’s Notes
XenApp 13 This covers things like MFCOM,Password manager, WI, Virtual Channel SDK, etc
XenServer 5 XenServer Related SDK’s
XenDesktop 1 XenDesktop Related SDK’s
NetScaler 12 NetScaler Related SDK’s
Workflow Studio 1 Workflow Studio SDK’s
Citrix Online 2 These are the GotoMeeting and GotoAssist SDK’s. Now even though you have to have a GTM or GTA account to get and use these, the point is they are still there.

 

So your saying, great! I’m buying into this and now i want to start using these SDK’s to build the next great app for my enterprise, but I don’t have a datacenter or server farm running this stuff and I cant afford to purchase licenses. Well, don’t fret. If you want to start developing for XenApp (Presentation Server), then Citrix offers a developer’s version of XenApp as well as the Dev license (1 year in length). This will get you up and running for XenApp/Wi/Powershell/Access Console/etc development. No cost, no hassle (There is not one yet for the XenApp 5.0 on Windows 2008 though).

Now, for the other products like NetScaler, Password Provisioning,etc, I’m not aware of Developer versions of these, although I believe that there should be some type of scaled back, one user (maybe two), type of offering to allow more developers to code up those one of a kind applications that are just sitting there waiting to be written :). I mean Citrix is a Developer Platform so lets start to utilize all of the platform to build those apps. :)

You can download the Developer Edition of XenApp at the following location. Remember, you will need a MyCitrix Account in order to download.

Now, my point here is not to compare Citrix to Microsoft but simply to provide a reference point and to inform developers that Citrix is a platform that we can build on. There are enough  SDK’s available that we should start using them to build up some interesting experiences.

You may be saying, well how much stuff can we do, automate publishing an application? Well, what could be some interesting user experiences we could think of where the SDK’s could help. How about  a single interface for all of your apps no matter what kind they are (See my previous post here), Maybe a silverlight alternative to Web Interface (I think there is one like this already, at least there was long time ago), Maybe integrate Web Interface into you windows app (or a subset of it to facilitate some launching mechanism)? Maybe integrate MFCOM into your custom provision system to add users to an application when they get access to it or write some Workflow Activities and make them available to the community? All of these things are possible with the use of the SDK’s provided by Citrix and its time that we as developers start viewing Citrix as a Developer Platform, at least in my humble opinion :). These tools are not just for admin functions anymore, lets start to push the envelope!

Thats my .02, Tell me what you think? do you have any cool XenApp code that could benefit the community, head on over to the Citrix Community Site and participate.

If your running XenServer, you have learned to love the command line interface right? :). Well, Citrix has made available a virtual appliance for XenServer call XenCenterWeb. This ia a preconfigured virtual appliance, that enables you to do some virtual machine management from within a browser. The site itself is written in PHP, so all the code is available on the VM/Appliance. You can get the Virtual Application from this link.

I have also put together a quick screencast on setting up and configuring XenCenterWeb. Check it out below.

This div will be replaced

Tags: , ,

JohnMcBride on May 25th, 2009

As I recently have rebuilt my laptop to run Windows 7 RC, I decided to download and install the XenServer Powershell extensions (available here) to start evaluating them. I was going to start writing my own extension but then stumbled across the ones that Citrix has developed and figured instead of writing my own, I would post some videos pertaining to the Citrix distributed ones. As a side not, Citrix has also released the source code to the PowerShell extensions. A very cool move in my humble opinion. I believe more companies should contribute to the open source community, and props to Citrix for taking this step.

After the installation, I checked the readme and saw an important item

“3.  Determine the current execution policy, like this:
    PS> Get-ExecutionPolicy

    If the current policy is Restricted, then you need to set it to
    RemoteSigned, like this:
    PS> Set-ExecutionPolicy RemoteSigned
    You should understand the security implications of this change.  If you
    are unsure, see Microsoft’s documentation on the matter:
    PS> Get-Help about_signing
    If the current policy is AllSigned, then this will work, but will be
    very inconvenient.  You probably want to change this to RemoteSigned,
    as above.
    If the current policy is Unrestricted or RemoteSigned, then this is
    compatible with XS-PS, so there is nothing to do.”

After adhearing to the above documentation ;), lets go ahead and run the XenServer Powershell Snapin from the start menu.
image

The resulting output from powershell is the below screenshot. Basically Powershell is telling us that it cannot find the XenServerPSSnapIn snapin, which typically means that the xenserverpssnap dll did not get registered properly during the installation. At least that is the initial theory :)

image

Maybe we need to run the installer as administrator, sometimes I forget to do this, but I thought this might be an issue so lets make sure and reinstall as admin. Well, that didnt work in my case so on to the original theory.

To make sure that this is indeed the case, lets fire up Microsoft Orca (MSI Editor tool) and edit the XenServerPSSnapIn-5.0.0-3.msi to see if we can find a custom action or something that takes care of the registration process. After searching around within the MSI indeed there is a custom action that is supposed to register the xenserver snapin on the machine as shown below.

image

To further confirm that the snapin did not get registered during the installation process let check the registry. You can locate all registered PowerShell snapins by checking the following key
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PowerShellSnapIns

image

Side Note: If your developing PowerShell snapins using C#/VB.Net once you compile your snapin dll you will need inform PowerShell that it is installed on the the machine and you want to load it into PowerShell. This is a two step process.
Step 1: use the installutil.exe utility to register the DLL onto the system the syntax is something similar to the following
%windir%\Microsoft.Net\Framework\v2.0.50727\installutil.exe [full path to your dll]

Step 2: once you have registered your dll on the system you need to add it to Powershell. You can do this by issuing the Add-PSSnapIn command from within powershell, like the following
Add-PSSnapIn –name [Your SnapIn Name]

 

So, now we know what the problem is we can work on fixing it so we can start using the SnapIns :)

The first step in the process is to register the snapin DLL on the the machine. Check out the side note above. We can achieve this by issuing the following command from within powershell. (Note: You will need to run PowerShell as administrator, especially if you are running on Windows 7).
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\InstallUtil.exe [Path To XenServer DLL]\XenServerPSSnapIn.dll

Once issuing this command you should see something like the following screenshot.

image

Now, from here you should be able to execute the XenServer Powershell Snapin from the start menu, and you will get the resulting powershell window ,with the snapin registered and ready to go, like the following. As you can see we have connected to out test XenServer
image

To further show that the the snapin is indeed loaded, we can issue the command Get-PSSnapin and it will show that the XenServer snapin is loaded.
image

 

Now, if you want to load the snapin into a regular powershell window, you would need to issue the Add-PSSnapIn command and that will load up the snapin for use within the current powershell window, like the following
Add-PSSnapin XenServerPSSnapIn
image

This will load the snapin and make the commands available for you to use.

 

Now, at this point, I’m not sure why the install did not properly register the XenServerSnapin.Dll on my Windows 7 RC system, but I am trying to do some further research on this and as soon I find out more info I will post it here. I hope this post helps out.

As always you can reach me through comments on here, follow me on twitter (http://www.twitter.com/johnmcbride) or friend me on FaceBook.

Tags: , ,

As technology advances and we, as developers, have so many technologies to choose from when developing a system (SilverLight, Touch based interfaces, MVC, AJAX, SharePoint,etc), enterprises still face an application delivery problem, even with technologies like Citrix or VMWare, users have too many places to go to get their applications! It should be simpler!!

It is with that that I put together this article along with some downloadable content so that you can add the web part to your SharePoint environment and use the application provisioning tool for provisioning applications. This will be the first of a few articles talking about this solution.

We need a single place to get to all of our applications and in addition, a tool that will allow us to provision applications into our new utopia UI :).

So how do we get to a single place for all of our applications you say? Well, lets make a couple of assumptions. The first one is that a corporate portal will be used as the single interface in which all users will go to (They should be going to it already right? :)), and since I’m a SharePoint guy, that will of course be SharePoint :). Second, this new utopia UI will house multiple application types.

What do I mean by multiple application types? In general we can categorize applications into about 4 different buckets.

1) Locally installed applications. These are applications that get pushed out to the users local computer via some distro mechanism, such as SMS or like product. These are traditionally launched from a users start menu or desktop

2) Citrix published applications. These are applications that a hosted on a citrix presentation farm (or now called xenapp).

3) Web based applications. These are typically launched by providing link to the app somewhere on a intranet or like system.

4) Virtualized Desktop (VDI type of systems). This is a new type of applications that is creeping into large organizations, we dont really touch on this too much in this article but it is still a valid application type.

So, now with the application categories out of the way :), lets talk about where the problem lies when it come to user trying to launch applications.

The main problem when having these different categories of applications is each one typically has a different type of launching mechanism. For example, local applications will be launched from the start menu, citrix applications can either be launched through PN Agent/Program Neighborhood or through WI, virtual machines are either launched from an RDP file or from VMWare Infrastructure Client, etc. To many choices, shouldn’t they all go to the same place for their applications, it shouldn’t matter the type of application right? So now the user has something like the following to launch their apps.

Start Menu Delivered Applications Web Based Application Delivery

(Citrix)

image image

Now, being a awesome architect for your company you already have a SharePoint rig installed in your organization.:) You have a good building block to start and address the single application interface issue.

To tackle the Citrix problem, you install Citrix WISP (Web Interface for SharePoint). This gets your Citrix applications in your SharePoint rig, but they are still isolated, especially if you would like to show different applications on different SharePoint pages, but again a good start.

To tackle the web based applications, lets say you add static HTML links on your SharePoint pages, maybe a page for all application links, or maybe you put relevant links on sub category pages, for example, HR application links on the HR department page, Training application on the Training department page, etc.

To tackle the local applications…. Well, there isn’t really a good solution to add these links to the site.

So even with the above modifications you can see that we still haven’t provided our users a seamless process to users launching their applications. They should be able to launch any application from the same place, no matter what the application type is right? If you want a local application go to the start menu, if its a Citrix or web application link go the internal portal/web site.

Enter the solution!

What if we could give the user user a simpler interface that we could stick on a main portal site someplace, that would give them access to all of their applications (Citrix,Local,Web,etc), and allow for some personalization of that system as well? Maybe a custom web part to help with the application delivery and launching. Something like the following.

image

So this, is pretty cool, the users can get to all of their application in a single place. Nice clean UI. As a user i don’t have to go to to any other place in the site for applications, they will always be in the same place.

Notice that there is no distinction of the type of application that the user see’s or launches. For example, lets take the following screen shot (lets neglect the image quality for the moment.)

image

From the above UI, you have no idea what the application type is when you click on it (which is a good thing). If i click on the HEAT link (which is a Citrix application), then the ICA client fires up and all is good. If i click on the Development IDE application under the (which is a locally installed application) then that application launches and again, all is good. My point here, is that why do we force the users to understand what type of application they are trying to launch, it shouldn’t matter, it should just work!.

So, from the utopia UI, I think we are getting there. We have a good single, simple UI, with folder categorization and application listing (regardless of the application type).

So, the next question is, how do we get applications into this new utopia UI. Well, why not have a separate provisioning application that is able to provision applications into the new utopia UI.

Enter the provisioning application.

image

We will need a way to get applications and folders into the front end UI So, a little background on this provisioning application. the purpose of this application is to provide a single application distributable to admins to allow them to publish/provision applications into the UI for consumption by the end users. There where the provisioning tool comes in.

Let me give a little background on this application. When designing it I wanted to initially be able to provision 3 types of applications, Local, Citrix and Web based applications along with ability to categorize those applications into folders. Along with this each application should have a permission set selector so as not to show all applications to every person. Lets break down the application a little with the following screen shots

ProvisioningApp

As you can see, the screen consists of several panes. Below is a general description of each one of the panes from the above screenshot.

   
Application Folder Pane: Property Pane:
image image
Provisioned Applications Pane: Provisioning Actions Pane
image image

Now that we have described the basic layout of the application lets start to talk about how we provision applications into the new UI web part talked about above.

Remember we said that the provisioning application has the ability to provision 3 types of applications, Local, Citrix and Web.

Lets talk about provisioning a locally installed application into the UI. I think instead of typing all of the instructions out on how to publish a local applications, lets just check out a video.

Publishing Folder Overview: This video goes over how you would using the provision tool to publish a new folder into the application list web part and make it available to the user base.

This div will be replaced

 

Publishing Local Application Overview: This video goes over using the provisioning tool to publish a locally installed application into the application list web part.

This div will be replaced

Publishing Citrix Application Overview: This short video shows how we can use the provisioning tool to publish a citrix based application into our application listing web part.

This div will be replaced

 

So, with that I am going to call this Part 1 of this multi part blog post done. I will be posting an a few more articles focusing on the following areas

1) Launching the applications from the web part
2) Defining execution scripts for applications Both global scripts as well as application specific scripts.
3) Setting permissions on the provisioned applications.
4) Deep dive into the Citrix Web Interface SDK integration into the application list web part.
5) ICA override settings per Citrix Application.
5) Deep dive into the MFCOM integration to show how the communication to the Citrix farms/applications happens.
6) Provisioning Application configuration The provisioning application has a deep configuration model where you can define Citrix settings, permission providers etc.

Stay tuned for the upcoming videos and articles. Feel free to comment or contact me through twitter, facebook or my email at john@citrixstuff.com

PS. I am working on cleaning up the code so i can post the binaries up here so you can download and try on your sites.

JohnMcBride on March 13th, 2009

IF you have ESX Servers somewhere in your environment you are probably going to want you ESX systems to send out SNMP traps of its state. Well, by default SNMP if turned off in the ESX install, so you will have to do some manual configuration to get it up and running.

No worries though, below I have listed to steps to get a simple SNMP service up and running on the ESX box.

The first step, is you want to log into you ESX device as root. I use putty but you can  use your favorite tool here.

Next, you will need to modify the snmpd configuration file (which is located in the /etc/snmp directory. you can using the following command

vi /etc/snmp/snmpd.conf

Once you have the file opened in VI, you are going to have to add a line to it, something like

rocommunity yourpublichstring

Here, the “yourpublicstring” should be replaced with your organization’s public SNMP community string.

Finally save the file and exit out of vi.

Next, you will need to start the SNMP service on the ESX box. You can issue the following command to do this

/etc/init.d/snmpd restart

That should get you up and running with SNMP on your ESX device.

Tags: , ,

JohnMcBride on February 16th, 2009

There might be a time in which you need to strongly name the VimServer.dll that gets created from the WSDL within the SDK. If you need help with that, check out a previous  post here

I wont re-hash the previous article but will just focus on making the DLL strongly named.

The first step is to create a private/public key pair. You can do this by using the .NET SDK utility sn.exe. This will create a signing file for you, that you can now use for signing. Now, if you are going to use this is production, I would probably invest in a public cert, but for the purposes of this post, that’s not necessary :)

So lets get to creating a signing cert.

Open up a command prompt, navigate to the .NET SDK directory.
Execute the following command.

sn.exe /k c:\testcert.snk

Once you have created you signing key, you will need to add it to the VimService.cs file that was generated from the WSDL. The basic steps here are to recompile the cs into a library (dll) and add the signing key to that compilation step. That can be done with the following command

From here to create the strongly named dll we can execute the following command.

csc /t:library /keyfile:c:\testcert.snk

This will output a new dll with a strong name, that you can now use in your apps that need a strongly named assembly. As you can see from the screen all is good.

image

Hope this helps.

Tags: , ,

JohnMcBride on February 13th, 2009

“I finally was able to get the VseWSS 1.3 CTP that supports 64bit windows installed. Installation went pretty uneventful.

So I fire up VS 2008 and create a new WebPart project. All is going swimmingly so far.

Go to deploy the project KerPlunk!!! Get the “The communication object…..” error message. Shown below.

image

I seem to remember, some time ago that this message was related to WCF not being registered correctly. So after some research i came across running the following command

ServiceModelReg.exe –r” from your .NET installed directory. Mine is on 64 bit so the location was in the following location.

“C:\Windows\Microsoft.NET\Framework64\v3.0\Windows Communication Foundation

After running you should see the following screen and you should now be able to deploy a solution from VS.

image

Hope this helps

Tags: , ,

If you are writing .NET code using the VMWare SDK, you already know that the ESX host its self has the set of web services installed on it that we use in order to interact with the VMWare system.

One thing you might not know, is that if you have Virtual Center installed in your environment, that device also has the ESX Web Services installed on it. Now, what is the difference? Well, in fact there are really no differences in the web services themselves, just what actions are available to each system using the web services.

For example, if you connect to Virtual Center WEb Services, you have he ability to create folders, where as, in the ESX host folders are not supported.

So, how do we know, what type of system we are connected to? Well, its actually pretty simple.

There are two ways we can accomplish this. The fist creating an instance of the ServiceContent. Once you have that, you can then check a property called “multiHostSupported”.

This property till tell you if the host you are connected to, supports multi hosts. And only Virtual Center support multi hosts.

The second approach is to get the AboutInfo collection of the service object, and check the property of “apiType”. If this returns VirtualCenter then you are in fact connected to a VC box.

Once you have this you can then perform logic to make different API calls based on the type of system your are connect to.

Here is some sample code

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
this._vmService = new VimService();
vmService.Url = @"https://<yourserver>/sdk";
_vmService.CookieContainer = new System.Net.CookieContainer();
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCerts();
ManagedObjectReference _object = new ManagedObjectReference();
_object.type = "ServiceInstance";
_object.Value = "ServiceInstance";
this._vmServiceContent = this._vmService.RetrieveServiceContent(_object);
this._vmLoginSession = _vmService.Login(_vmServiceContent.sessionManager, "<username>", "<password>", null);
 
AboutInfo _apiAboutInfo = this._vmServiceContent.about;
if ( _apiAboutInfo.apiType.ToLower() == "virtualcenter" )
{
	Console.WritLine(“Connected to a VC API”);
}

Hope this helps.

Tags: , ,