Philip Lippard

Please say it ain't so

ESXi Server–Thin Provisioning

Thin-provisioning1Thin provisioning has been a feature within VMWare Workstation and VMWare ESXi Server for quite some while.   To manage the growth of space use/reuse within a VMWare VMDK for VMWare Workstation, one usually periodically compresses the VMDK.  Of course, such compression requires a shutdown of the virtual machine.

With ESXi Server based VMDKs, what I have found is that I have a preference for using Thin Provisioning, because when I take a snapshot, I follow taking such a snapshot by copying the VMDK to either another local or remote storage media, and of course such copying takes much less time with thinly provisioned VMDKs.   The copy of the VMDK is a logical copy, not a physical copy; meaning only the in-use data blocks get copied, with one noted exception.  This exception happens to be how free space is identified and re-used.  If a utility like SDELETE is used periodically to zero out the free space within the VMDK then such free space is not copied to the destination location.  For example; if after executing SDELETE used space is 25% of the VMDK, then the destination VMDK will occupy only 25% of the VMDK provisioned size.  Also, the source thinly provisioned VMDK may have grown to the full thinly provisioned size.

I generally allow my ESXi Server thinly provisioned VMDKs to grow to the full thinly provisioned size, and of course this requires that the production VMDKs will require the provisioned size, however there is tremendous advantage during the copying/backup process, as noted above.

CRUD, OData & WCF Data Services

As of late I have been working with WCF Data Services to evaluate its fitness when used with client based Javascript/jQuery applications.   I have been quite pleased at the results.  WCF Data Services exposes a CRUD OData (Open Data Protocol) interface which can be accessed and utilized from not only jQuery client based applications but also desktop WPF or Silverlight apps, console apps, Winform apps and practically any application capable of communicating with WCF REST services.  Early in my evaluation I did encounter the need to uninstall WebDAV, which caused a Bad Method status code 405 to be returned, however after uninstalling WebDAV and utilizing many Internet articles on OData and WCF, I concluded that the following examples are good working examples on using OData and CRUD.

Microsoft does have a higher level Javascript/AJAX based interface implemented in the Sys.components.openDataContextnamespace, however I choose to use the jQuery API to issue Http requests directly, as illustrated in the examples below…

The examples below are also referencing one important constant; my WCF Data Service URL prefix…

   1:  var dataService = "/jCredentials.svc";

 

CRUD – “C” is for Create

   1:  function InsertCredentialsPIN(selectedTreeNode, PINObj) {
   2:   
   3:      var url = dataService + "/Credentials_PINs";
   4:   
   5:      var json = JSON.stringify(PINObj);
   6:   
   7:      $.ajax({
   8:          url: url,
   9:          data: json,
  10:          type: "POST",
  11:          contentType: "application/json; charset=utf-8",
  12:          dataType: "json",
  13:          success: function (result) {
  14:              // Do something
  15:          },
  16:          error: function (result) {
  17:              alert("PIN Insert Failure - Status Code=" + 
  18:                  result.status + ", Status=" + result.statusText);
  19:          }
  20:      });
  21:  }

CRUD – “R” is for Read

   1:  function GetPINTree(orderBy) {
   2:   
   3:      var url = null;
   4:      if (orderBy == null) {
   5:          url = dataService + "/Credentials_PINTree";
   6:      }
   7:      else {
   8:          url = dataService + "/Credentials_PINTree?$orderby=" + orderBy;
   9:      }
  10:   
  11:      $.ajax({
  12:          url: url,
  13:          type: "GET",
  14:          contentType: "application/json; charset=utf-8",
  15:          dataType: "json",
  16:          success: function (result) {
  17:              // Do something
  18:          },
  19:          error: function (result) {
  20:              alert("PINTree Get Failure - Status Code=" + 
  21:                      result.status + ", Status=" + result.statusText);
  22:          }
  23:      });
  24:  }

CRUD – “U” is for Update

   1:  function UpdatePINTree(selectedTreeNode, PINTreeObj) {
   2:   
   3:      var url = dataService + "/Credentials_PINTree(guid'" + 
   4:                          selectedTreeNode.get_value() + "')";
   5:   
   6:      var json = JSON.stringify(PINTreeObj);
   7:   
   8:      $.ajax({
   9:          url: url,
  10:          data: json,
  11:          type: "PUT",
  12:          contentType: "application/json; charset=utf-8",
  13:          dataType: "json",
  14:          success: function (result) {
  15:              // Do something
  16:          },
  17:          error: function (result) {
  18:              alert("PIN Tree Update Failure - Status Code=" + 
  19:                  result.status + ", Status=" + result.statusText);
  20:          }
  21:      });
  22:  }

CRUD – “D” is for Delete

   1:  function DeletePIN(selectedTreeNode) {
   2:   
   3:      var url = dataService + "/Credentials_PINs(guid'" + 
   4:                              selectedTreeNode.get_value() + "')";
   5:   
   6:      $.ajax({
   7:          url: url,
   8:          type: "DELETE",
   9:          contentType: "application/json; charset=utf-8",
  10:          dataType: "json",
  11:          success: function (result) { 
  12:              // Do something
  13:          },
  14:          error: function (result) {
  15:              alert("PIN Delete Failure - Status Code=" + 
  16:                      result.status + ", Status=" + result.statusText);
  17:          }
  18:      });
  19:  }