I recently needed to configure a number of NSX Controller nodes to forward their logs using syslog to a vRealize Log Insight cluster.  Unlike the NSX manager (and most other components of a VMware SDDC), NSX controllers don’t provide a graphical way of configuring syslog.  In fact, they don’t even offer a CLI command for syslog configuration.  Instead, you need to use the NSX REST API.

Now, if you take a look at the official documentation for performing this configuration (including the NSX 6.3 documentation centre, or the VMware Validated Design for SDDC 4.0 documentation), you’ll find instructions which involve installing REST plug-ins into your firefox or chrome browser.  This can be a headache if you are running these commands from a jump host which only has internet access through a tightly controlled proxy.  Luckily, there is a powerful automation tool that comes pre-installed on the vast majority of jump hosts in the world: PowerShell!

I wrote a PowerShell script to configure syslog on my NSX controller nodes using the Invoke-RestMethod cmdlet, which I’ve made public below:

I hope that most of the code is fairly self-explanatory, but there are a few things I’ll mention.

Firstly, take note of the actual NSX controller ID’s which are being used in your environment.   Although the example in the script assumes NSX controllers 1, 2, and 3, remember that NSX controller ID persist forever, even after a controller node has been decommissioned (or failed to deploy in the first place).

Secondly, I spent a bit of time trying to work out how to best handle the credentials required to authenticate to the NSX managers.  Originally, I needed a quick solution so I simply provided the password as an unsecured string.  This is not ideal, especially since I intended to make this script publicly available for reuse by other people, and after a bit of investigation it turns out you can extract a password in plain text from a PSCredential object. Thus, you don’t need to provide your password in plain text (like by saving it in the script or typing it into the console via Read-Host), as the script will extract the password from the PSCredential to generate the header which is used to authenticate to the NSX Manager.  The script will also wipe the $Credentials variable after it has finished running.

Thirdly, you can edit the $body variable to change things like the port, protocol, or logging level, as required by your environment.

Lastly, it seems that all NSX controllers identify in their syslog messages as “NSX-Controller”.  This is less than ideal, especially when you might have 10-20 NSX controllers in your environment.  It’s possible to change the hostname of the NSX controller at the command line, but this step isn’t covered in any of the official documentation which makes me wonder if it’s the right approach (as maybe it causes some unintended side effects).  I’m looking into this and will report back when I have a solution.

If anyone wants to recommend some changes, feel free.  One thing I’d like to do is make the script handle multiple NSX Managers, and self-discover the valid NSX controller ID’s, but that’s a a job for another day.  Until then, I hope this helps some people out there!

 

I got this error message when trying to run the Invoke-Sqlcmd powershell cmdlet against a server remotely using HP Server Automation (HPSA).  The full error message is:

Invoke-Sqlcmd : Mixed mode assembly is built against version 'v2.0.50727' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information.

If you search the error message online, you’ll discover some solutions like this, which involve editing XML configuration files.  As HPSA doesn’t use the regular powershell configuration files, I got stuck for a while trying to figure out which configuration file it does use.

As it turns out, the configuration file that HPSA uses is stored (by default) at the following location: C:\Program Files\Opsware\agent\bin\PsSasHost.exe.config.  The solution is to edit the configuration file to include the bolded section:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <startup useLegacyV2RuntimeActivationPolicy="true">

    <supportedRuntime version="v4.0"/>

    <supportedRuntime version="v2.0.50727"/>

  </startup>

</configuration>

You can also add the following code to a powershell script, which will make the necessary edits to the config file on the server.  This script will have to be run prior to the script which runs the Invoke-Sqlcmd commands.

$ConfigFile = "C:\Program Files\Opsware\agent\bin\PsSasHost.exe.config"
$Xml = [xml](Get-Content -Path $ConfigFile)
$Xml.configuration.startup.SetAttribute("useLegacyV2RuntimeActivationPolicy","true")
$Xml.Save($ConfigFile)

Problem solved!

N.B. The problem with the SQLPS module which causes this error to pop up is fixed in SQL 2016.  However, the 2016 SQLPS module comes with its own issues.  As has been documented in official bug reports (1, 2), installing the SQL 2016 version of the SQLPS module will break backwards compatibility with SQL 2014 instances even if you don’t load the 2016 SQLPS module.  Apparently, the 2014 SQLPS module exhibits the same behaviour when trying to manage SQL 2012 instances.  Well done Microsoft!

One of the annoying things about installing new builds of Windows 10 is that the installation process resets a number of settings to default.  When you’re on the insider preview “fast ring”, new builds come every 1-2 weeks, and changing those handful of things back to their previous setting gets old pretty fast.  After installing a new build today I finally decided to try automating these things using Powershell.

For me, there are 3 main things that I keep changing back after every build:

  1. Removing unwanted language packs.
  2. Installing the en-AU speech pack so that Cortana works properly. Edit: as of an insider build delivered sometime in May 2016, this now happens automatically.
  3. Disabling devices from waking my computer from sleep.

Unfortunately, I haven’t been able to figure out how to achieve the second one through Powershell (If I do, I’ll update the article), but the first one and last ones weren’t too tricky.

Removing unwanted language packs

Every time I install a new insider build, it automatically re-installs the en-US language.  I’m in Australia and only want en-AU installed.  The following Powershell code removes all language packs except the one you specify:

The only tricky part about that was figuring out how to remove an installed language. My first thought was trying to use Get-WinUserLanguageList en-US and then piping it to Remove-WinUserLanguageList… but that cmdlet doesn’t exist. It turns out that Set-WinUserLanguageList will remove all language packs except the one(s) you’re specifying.

Disabling devices from waking my computer from sleep

Every time I install a new insider build, it re-enables the option that allows my keyboard, mouse, and NIC to wake the computer from sleep.  This often means that I will put the computer to sleep, and it will then wake up later on because I bumped the mouse or because something tried to ping it over the network.  Since I have configured my power management options to never automatically put the computer to sleep, this typically means the computer will wake up and run for hours before I notice.

Thankfully, there is a command-line utility called powercfg that can be used to query all devices which are allowed to wake the PC. This is basically all devices in the device manager which have the “Allow this device to wake the computer” box checked under the power management tab. We can then use Powershell to disable that option for each device which has been detected as wake armed.

Note that the powershell script will have to be run in administrative mode to have the necessary permission to disable the wake-armed devices.

Now that’s all scripted I’ve saved myself about 30 seconds every 1-2 weeks when a new insider build gets installed. I’ll have to install about 120 insider builds to break even on the time spent working out this script and writing this blog post. Hooray.