Monthly Archives: September 2014

Poor Man’s vCPU & vRAM Right Size Recommendation Tool

VMware vCenter Operations Management Suite can be expensive. If you are like me and there is no budget for vCOPs, this script will give you a vCPU & vRAM recommendations based off of past virtual machine usage. The following script will connect to your vCenter, grab historical performance data and provide recommendations that were designed around two vKernel whitepapers. The following whitepapers are:


The script is simple to use only requiring the vCenter parameter to start with all defaults:

PoorMansRecommendations.ps1 -vCenter site1.local.domain


Specifies additional authentication information. Grabbing 60 days of past performance instead of the default 30 days:

PoorManRecommendations.ps1 -vCenter site1.local.domain -Username fred -Password root -PastDays 60


Specifies more samples for accuracy and using a larger ‘building block’ for memory recommendations:

PoorMansRecommendations.ps1 -vCenter site1.local.domain -PastDays 60 -MaxSamples 25000 -MemoryBuildingBlockMB 1024


When running the script interactively, a progress bar be displayed as it calculates recommendations per virtual machine:
Poor Man's Right Sizing

The results:

Poor Man's Recommendations Results

This should only be used as a guidance, point of reference, a conversation point or just a rough estimate. Each environment and workload characteristics are unique, please use your logic along with this data to come to a solution that is right for your environment.

Download the script: PoorMansRecommendations.ps1

Thanks for looking. Please leave any questions or comments below and have a great day!

Tagged , , , , , , ,

Oracle Database Queries in PowerShell, Script Examples

Below are some code examples to help get your data out of an Oracle database into a PowerShell object quickly! The logic to manipulate data is the same regardless of vendor: load any required libraries, define the connection string, setup the connection object, use that connection object for subsequent queries and finally close the connection.

Oracle Data Access Components (ODAC) allows you to run an Oracle complied binary within the .NET framework including PowerShell. When you are working with Oracle queries in PowerShell, it is required to download and install the Oracle Data Access Components prior to accessing a database. Download the components here, Select the appropriate architecture (x86/x86-64) and ensure the correct PowerShell program architecture is being executed with the corresponding Oracle component’s architecture. Failure to do so will lead to binary related errors while loading the assembly in PowerShell.

Load the System.Data.OracleClient Assembly:

### try to load assembly, fail otherwise ###
$Assembly = [System.Reflection.Assembly]::LoadWithPartialName("System.Data.OracleClient")

if ( $Assembly ) {
    Write-Host "System.Data.OracleClient Loaded!"
else {
    Write-Host "System.Data.OracleClient could not be loaded! Exiting..."
    Exit 1

Setup the connection string and open a database connection:

### connection string ###
$OracleConnectionString = "SERVER=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(;uid=user;pwd=password;"

### open up oracle connection to database ###
$OracleConnection = New-Object System.Data.OracleClient.OracleConnection($OracleConnectionString);

Stored procedure example with parameters example:

try {

    ### create object ###
    $GetHostIDCommand = New-Object System.Data.OracleClient.OracleCommand;
    $GetHostIDCommand.Connection = $OracleConnection
    $GetHostIDCommand.CommandText = "GET_HOST_ID"
    $GetHostIDCommand.CommandType = [System.Data.CommandType]::StoredProcedure

    ### add storeprocedure paramaters ###
    $GetHostIDCommand.Parameters.Add("p_hostname", [System.Data.OracleClient.OracleType]::VarChar).Value = $Computer.ToUpper();
    $GetHostIDCommand.Parameters.Add("p_host_id", [System.Data.OracleClient.OracleType]::Number).Direction = [System.Data.ParameterDirection]::Output

    ### execute storedprocedure ###
    $GetHostIDCommand.ExecuteNonQuery() | Out-Null

    ### get the data from output defined by the storedprocedure ###
    $HostID = $GetHostIDCommand.Parameters["p_host_id"].Value

    ### dispose of object ###

catch { Write-Host "$Computer : Failed to GET_HOST_ID" }

SQL select query text example:

try {

    ### sql query command ###
    $OracleSQLQuery = "SELECT * FROM HOSTS"

    ### create object ###
    $SelectCommand = New-Object System.Data.OracleClient.OracleCommand;
    $SelectCommand.Connection = $OracleConnection
    $SelectCommand.CommandText = $OracleSQLQuery
    $SelectCommand.CommandType = [System.Data.CommandType]::Text

    ### create datatable and load results into datatable ###
    $SelectDataTable = New-Object System.Data.DataTable

catch {

    Write-Host "Error while retrieving data!"


SQL update command text example:
(same would be for an insert command with no expected output)

try {

    ### sql update command query ###
    $HostUpdateHostSQL = "UPDATE HOSTS h SET h.PHYSICAL = '$(Convert-Boolean($HW_PHYSICAL))' WHERE h.ID = '$HostID'"

    $HostUpdateCommand = New-Object System.Data.OracleClient.OracleCommand;
    $HostUpdateCommand.Connection = $OracleConnection
    $HostUpdateCommand.CommandType = [System.Data.CommandType]::Text
    $HostUpdateCommand.CommandText = $HostUpdateHostSQL

    ### execute update command query ###
    $HostUpdateCommand.ExecuteNonQuery() | Out-Null

catch {

    ### output exception to screen ###
    Write-Host "$Hostname : ERROR! $HostUpdateHostSQL"
    Write-Host "Dump : $($_.Exception.ToString())"

### dispose regardless ###
finally { $HostUpdateCommand.Dispose() }
Tagged , , , , ,

Raspberry Pi, Edimax Wifi, DYMO Printer VMUG Check-in Process Tutorial

This article is out-of-date. It should only be used for historical reference. A new article will be published to reflect the updated code located at

Project Summary

At the Cleveland VMUG events we will be using a new check-in system. The system consists of a Raspberry Pi, Edimax Wifi adapter and a DYMO thermal label printer to perform wireless iPad check-ins. The setup will sign-in preregistered individuals and capture data from walk-on attendees. Finally, producing a name tag label which is printed wireless to the DYMO LabelWriter 330. This is how it was accomplished!



Hardware Layout


The diagram is simple and straight forward but to give you a visual how things are related.


Most important some sort of already existing Linux knowledge is highly recommended! This (updating + installing) will require a great amount of time since the Rasberry Pi’s processor is low in computational power and low IO through output since the Secure Digital memory card is generally slow. I started with a fresh image of Raspbian. At the time of writing, this tutorial is using version, 2014-09-09-wheezy-raspbian.

Let’s start by installing all the prerequisites libraries and binaries. Please complete the apt-get commands in order to prevent php5 installing apache2 since we are leveraging lighttpd.

sudo apt-get update -y
sudo apt-get install dnsmasq lighttpd cups libcups2 libcups2-dev libcupsimage2 libcupsimage2-dev build-essential g++ p7zip-full -y
sudo apt-get install php5-common php5-cgi php5-sqlite php5 -y

CUPS Installation & DYMO Driver

If you are using the pi user, add the pi user to the lpadmin (CUPS Admin) group:

sudo usermod -a -G lpadmin pi

After the installation of CUPS we will need to modify the following sections in /etc/cups/cupsd.conf to look like the following below. This will allow remote access to the CUPS Administration page and the CUPS web server will operate on all interfaces not just the localhost.

# Allow remote access
Port 631
Listen /var/run/cups/cups.sock


# Restrict access to the server...
<Location />
  # Allow remote access...
  Order allow,deny
  Allow all

# Restrict access to the admin pages...
<Location /admin>
  Order allow,deny
  Allow all

Here we will download the Dymo CUPS drivers and compile them on the Raspberry Pi. Again, this step will take a little bit of time to complete.

cd ~
tar -xzvf dymo-cups-drivers-1.4.0.tar.gz
cd dymo-cups-drivers-
sudo ./configure
sudo make
sudo make install

After these changes have been made to /etc/cups/cupsd.conf, cycling the service is required and to ensure the new Dymo driver is found.

sudo service cups restart

Proceed over to the CUPS web interface to setup the Dymo printer at https://host:631/admin

Once you get to the login page and you are authenticated, proceed to add a printer by selecting Add Printer under the Administration tab.
Dymo LabelWriter 330 CUPS Setup - Step Start

Select your DYMO LabelWriter printer and press Continue.
Dymo LabelWriter 330 CUPS Setup - Step 1

Specify a Name for your printer, I’de recommend keeping it short in name.
Dymo LabelWriter 330 CUPS Setup - Step 2

Select the Model of the printer or choose the PPD file from compiling if it was not automatically detected. Press Add Printer!
Dymo LabelWriter 330 CUPS Setup - Step 3

After the printer is added, ensure the proper defaults are set for the printer such as Print Quality, Print Density and Media Size by going to Set Default Options under the Administration tab.
Dymo LabelWriter 330 CUPS Setup - Step 4

Finally, ensure the DYMO LabelWriter is set to the System Default printer which is located in the dropdown menu of the printer under the Printers tab.
Dymo LabelWriter 330 CUPS Setup - Step 6

lighttpd Setup

Add the pi user to the www-data group so that the default lightttp path can be written to by the pi user:

sudo chown www-data:www-data /var/www
sudo chmod 775 /var/www
sudo usermod -a -G www-data pi

To enable the server to handle php scripts the fastcgi-php module should be enabled and lighttpd reloaded:

sudo lighty-enable-mod fastcgi-php
sudo service lighttpd force-reload

wlan0 Setup

During this section, we will give wlan0 a static ip address and ensure the interface is brought up at boot. Note this section and the dnsmasq sections are almost verbatim taken from, These sections are placed here for linear order of operations and recap the article link above.

Edit /etc/network/interfaces, remove anything related to wlan0 then add this lines:

iface wlan0 inet static

To make sure, add ifup wlan0 inside /etc/rc.local file before exit 0 so it will look like this:

ifup wlan0
exit 0

dnsmasq Setup

Stop dnsmasq before working on it:

sudo service dnsmasq stop
sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
sudo touch /etc/dnsmasq.conf

Edit the newly create /etc/dnsmasq.conf and make it reflect the following contents:


Add the following to the /etc/hosts file to reflect the hostname of the Raspberry Pi for easy typing in the tablet web browser:        checkin checkin.local

hostapd Setup

The EW-7811Un features a Realtek RTL8192C depending on the revision. Since it uses a Realtek chipset you must use the Realtek’s version of hostapd. The majority of this following section was taken from, Proper credits goes to the author.

cd ~
tar -zxvf v1.1.tar.gz
cd RTL8188-hostapd-1.1/hostapd
sudo make
sudo make install

Create the following file /etc/hostapd/hostapd.conf and tailor the following setting:

# Basic configuration

# WPA and WPA2 configuration

# Hardware configuration

Edit the following file to point to the newly created conf file above. Open up /etc/default/hostapd and make it reflect the following:


Enable the access point by restarting the hostapd service after all the changes:

sudo service hostapd restart

PHP Application

After everything, download the PHP binary bits included and extract everything to /var/www and follow the directions included in the 7z archive or download the complete Raspberry Pi below which includes all the work above including the application.

Download and extract the 7z archive:

wget <oldurl>
7z x -y -o/var/www VMUGWirelessCheckin_v103.7z

Ensure correct permissions:

sudo chown www-data:www-data /var/www/ -R
sudo find /var/www/ -type d -exec chmod 755 {} ;
sudo find /var/www/ -type f -exec chmod 644 {} ;
sudo chmod 664 /var/www/Checkin.*

For good house keeping delete the old landing page:

sudo rm -f /var/www/index.lighttpd.html

Be sure to set 664 Unix permissions on the *.db (SQLite database) and modify variables as needed in settings.php. Replace the background.png and logo.png under the images directory.

You should now be complete!

Application links are http://<host>/admin.php for the Administrative Functions page and http://<host>/reprint.php for the Reprint Page.


This give you everything you need to setup the hardware portion of this project. The software portion is simple, extract and deploy. Please post any questions or comments below.

Download / Git Repository

The Git repository for this project can be found here at GitHub, for the latest version.

Tagged , , , , , , , , , , , , , ,

Amazon AWS Route 53 DNS Review

Amazon, Google, YouTube and Facebook have scaled their websites and networks better than anyone in the world. Amazon has a hosted DNS product offering which is priced by the number of queries. Amazon’s DNS records are replicated globally and domain name servers reflect a global presence.

The numbers really speak for them selves and these are the cold hard facts. I will describe the three test scenarios which are:

  1. Response query time with records hosted on the hosting provider DNS servers
  2. Response query time with records hosted on the domain registrar’s DNS servers
  3. Response query time with records hosted on the Amazon AWS Route 53 DNS servers

Check out the data your self! Does it really require further explanation? If so, drop a comment.


Hosting Provider DNS Response Report


NameCheap DNS Response Report


Amazon AWS Route 53 DNS Response Report