Author: Chris

Resolve ESXi NFS Mounting Issue

I changed my network configuration at home a while back and when I went to create a new Chef Server VM in ESXi I was unable to find my software datastore with my Ubuntu 16.04 ISO. I tried mounting my NFS volume through vCenter and it failed. I then went directly to the ESXi web client and it failed as well. I’ve seen inconsistencies in the GUI versus the CLI so I SSH into my server. I try mounting my NFS volume and it fails:

esxcli storage nfs add --host=<myhost> --share=<myshare> --volume-name=<myvolume>

Unable to add new NAS, volume with the label software already exists

As any other IT person would do I google the response and found this super helpful post: https://www.bussink.ch/?p=1640

It alerted me to the issue and resolution but needed to be updated for ESXi 6.5 instances. So, now you remove the hidden volume with this command:

esxcli storage nfs remove --volume-name=<myvolume>

Then you are free to remount and carry on about your business.

 

Debugging Packer Azure-Arm Builder

Getting a Packer build run to complete successfully can be challenging. Getting the write combination of template configuration and scripts is always a challenge. If you stuck trying to get here are a few tips.

Turn on Logging

Enable Packer logging by setting a few environment variables. Set PACKER_LOG = 1 and enter a file path for PACKER_LOG_PATH.

Prevent Cleanup on Error

Inform Packer that it should ask you what to do when it encounters an error instead of just immediately cleaning up all the resources it created.

packer build -on-error=ask mytemplate.json

Log into VM

If examining the log file isn’t enough to resolve the issue, you can leverage our ability to prevent cleanup and log into the VM. So, what is the password? Well the password is not dumped into the console output, which is just fine. You need to open the file at the path you specified for PACKER_LOG_PATH. Once you have that open you can search for “adminPassword” and grab the value that immediately follows it.

\"parameters\":{\"adminPassword\":{\"value\":\"THIS_IS_THE_PASSWORD\"}

Download blob from Azure in PowerShell without AzureRM

This is an edge case, but not edge enough where people aren’t posting about it. Sometimes you don’t want to take an additional dependency and jump through hoops to get AzureRM installed on a machine and functional. This could entail getting the right version of PowerShell, setting permissions to access the PowerShell Gallery, etc. In my scenario, I’m using Packer to create images for Azure and needed to get a third-party installer on my image. So, I uploaded my assets to Azure and only needed to pull them down. I could have hosted my own web server and accessed the files over HTTP/HTTPS, but this was the path of least resistance. When I started down this path, I came across this page:

https://docs.microsoft.com/en-us/rest/api/storageservices/authentication-for-the-azure-storage-services

This page is more specification than how-to document, so there are plenty of comments saying they didn’t understand and other helpful visitors posted their examples. I also came across this page, that does a great job of outlining the process in various language but not PowerShell:

https://tsmatz.wordpress.com/2016/07/06/how-to-get-azure-storage-rest-api-authorization-header/

Taking their lead, I decided to put everything together in a nice and clean PowerShell function that you can use in your own scripts or modules. Enjoy.

function Get-BlobFromAzure {
    [CmdLetBinding()]
    param (
        [Parameter(Mandatory)]
        [string]$StorageAccountName,

        [Parameter(Mandatory)]
        [string]$StorageAccountKey,

        [Parameter(Mandatory)]
        [string]$ContainerName,

        [Parameter(Mandatory)]
        [string]$BlobName,

        [Parameter(Mandatory)]
        [string]$TargetFolderPath
    )

    $verb = "GET"
    $url = "https://$($StorageAccountName).blob.core.windows.net/$($ContainerName)/$($BlobName)"
    $xMsVersion = "2015-02-21"
    $xMsDate = [DateTime]::UtcNow.ToString('r')
    $targetFilePath = Join-Path -Path $TargetFolderPath -ChildPath $BlobName

    $canonicalizedHeaders = "x-ms-date:$($xMsDate)`n" + `
        "x-ms-version:$($xMsVersion)"

    $canonicalizedResource = "/$($StorageAccountName)/$($ContainerName)/$($BlobName)"

    $stringToSign = $verb + "`n" + `
        $contentEncoding + "`n" + `
        $contentLanguage + "`n" + `
        $contentLength + "`n" + `
        $contentMD5 + "`n" + `
        $contentType + "`n" + `
        $date + "`n" + `
        $ifModifiedSince + "`n" + `
        $ifMatch + "`n" + `
        $ifNoneMatch + "`n" + `
        $ifUnmodifiedSince + "`n" + `
        $range + "`n" + `
        $canonicalizedHeaders + "`n" + `
        $canonicalizedResource

    $hmac = new-object System.Security.Cryptography.HMACSHA256
    $hmac.Key = [System.Convert]::FromBase64String($storageAccountKey)
    $dataToMac = [System.Text.Encoding]::UTF8.GetBytes($stringToSign)
    $sigByte = $hmac.ComputeHash($dataToMac)
    $signature = [System.Convert]::ToBase64String($sigByte)

    $headers = @{
        "x-ms-version" = $xMsVersion
        "x-ms-date" = $xMsDate
        "Authorization" = "SharedKey $($storageAccountName):$($signature)"
    }

    Invoke-RestMethod -Uri $url -Method $verb -Headers $headers -OutFile $targetFilePath
}

Simple HTTP file hosting with NGINX

I am doing a lot of Packer lately building images for deployment in Azure. Rather than copy content or worry about accessing SMB or NFS shares, I decided to expose my file server to make downloading original ISO files easy. However, I struggled a bit to find the right NGINX configuration to make this happen. So, if you ever find yourself in need of hosting files to download with NGINX you can use this configuration as a starting point:

server {
    listen 80;
    listen [::]:80;

    location /software {
        autoindex on;
        alias /storage/standard/software;
        types { application/octet-stream; }
        default_type application/octet-stream;
    }
}

This is good for ngnix/1.12.1 (Ubuntu) on Ubuntu 17.10 (Artful Aardvark)

ConEmu Tiling

I’m constantly on the command line for Git, PowerShell, NodeJs, SSH, etc. I’ve been using ConEmu for a while to consolidate all my terminals into a single window with tabs, which is great. However, sometimes you want to see multiple terminals at the same time. ConEmu has a great feature for that. One thing, I am constantly doing is using a bash shell for ssh and copying information from a PowerShell session.

conemu

To get your setup in a similar fashion, add a Startup Task in ConEmu and specify the following commands:

powershell -new_console:d:C:\Git
bash -new_console:sH
powershell -new_console:d:C:\Git -new_console:sV

workspace

 

Recent Issues in Google Chrome

I use Google Chrome on 4 machines daily: my personal desktop (Win10), my personal laptop (MacOS), my work laptop (Win10), and a work VM (Win10). On all but my personal desktop, I experienced different display issues in Chrome in the past week:

  1. Black borders on the left, bottom, and right sides.
  2. Missing tabs.

Searching the Internet suggests disabling extensions, but the problem must be related to border styles. The easy solution is changing the theme in Chrome.

For the missing tabs, it comes down to a drawing issue. Disabling hardware acceleration resolves that issue.

The world is peaceful now and I can work.