Microsoft MVP Award 2018-2019

I received the Microsoft MVP Award 2018-2019

While on vacation I received some excellent news. I received the Microsoft MVP Award 2018-2019. I’m an Microsoft Most Valuable Professional in the Cloud & Datacenter expertise for another year!

Dear Didier Van Hoye,
We’re once again pleased to present you with the 2018-2019 Microsoft Most Valuable Professional (MVP) award in recognition of your exceptional technical community leadership. We appreciate your outstanding contributions in the following technical communities during the past year:

  • Cloud and Datacenter Management

Image result for microsoft mvp award

It’s a moment of appreciation of our work in the global community. I feel both proud an humble to be part of this select group of experts chosen to be recognized by Microsoft and be awarded the Microsoft MVP Award 2018-2019. Basically it puts a smile on my face.

What does this mean?

I have another year to look forward to as a Microsoft MVP. I’ll be sharing, teaching, discussing, designing and implementing the best possible solutions. I blog, write articles, engage in webinars and speak at conferences. I also help out fellow IT professionals and MVPs when and where possible. The community exist because we contribute, not just take. But I do know I can ask for help when I need it. A big thank you to all Microsoft employees I engage with. Your patience and willingness to listen to us, even when it might be “constructive feedback” and not always praise, helps us all. I appreciate the opportunity. One very nice success this year of such collaboration was to get ReFS support extended to many more use cases.

Every year I try to make it too some of the best and most interesting conferences to learn, exchange experiences, discuss and share knowledge as both a presenter and attendee. That take a bite out of my personal time budget and sometimes even my financial budget. Both of those have limits. But that is the investment I make in myself and the community. You cannot solely depend on your employer or job for your professional advancement. They have different agendas that don’t always align.  To broaden you horizon, prevent tunnel vision and (deadly) echo chambers you need to step out of your workplace cocoon. Luckily I’m blessed with the opportunity to attend & speak at conferences where travel and expenses get paid by the organizers.  That helps a lot.

Thank you for reading, for attending my sessions, for listening to the webinars I join as a subject matter expert. You help me be a better me. Being an MVP allows me to interact with very smart people around the globe. It lets me contribute to and learn from very interesting challenges and  projects. That exposure helps me grow as I help others. It allows me to provide even more well founded feedback to Microsoft. This mutual beneficial relationship is the core of community and what being a MVP is all about.

 

 

Upgrading MySQL 5.7.21 to 8.0.11

Upgrading MySQL 5.7.21 to 8.0.11 for WordPress 4.9.6

The process of Upgrading MySQL 5.7.21 to 8.0.11 for WordPress 4.9.6 is actually quite easy (official MySQL documentation). And as I maintain my WordPress version, plugins regularly that’s not big of a deal for me.

Prepare the upgrade

  1. Backup your VM
  2. Backup your MySQL database
  3. Verify the restores work
  4. I also copy the data folder (in my case C:\MySQLDataFolder\Data) which I keep separate from the MySQL installation files as it helps me with upgrades. The only things that are in the C:\Program Files\MySQL\MySQL Server X.Y folder (I use the x64 bits) are the MySQL application files and the my.ini file.
  5. Create the C:\Program Files\MySQL\MySQL Server 8.0 (x64 bit version of MySQL, otherwise use the C:\Program Files (x86) folder). Copy the content of the  zip file with MySQL files and folders in there.

Upgrading MySQL 5.7.21 to 8.0.11 for WordPress 4.9.5

I then copy the my.ini file form the current installation (C:\Program Files\MySQL\MySQL Server 5.7. into the C:\Program Files\MySQL\MySQL Server 8.0 as well. It might be necessary to edit this file a bit more later but I start out with and exact copy and one change to point to the new basedir:  5.7 becomes 8.0 in this case.

As you notice, I don’t keep the MySQL Data and the ini file in the ProgramData folder on windows. It’s fine to leave it all there, if you prefer that.

# Path to installation directory. All paths are usually resolved relative to this.
basedir=”C:/Program Files/MySQL/MySQL Server 8.0/”

Perform the upgrade

  • Stop the MySQL Service:NET STOP MYSQL
  • I the remove the service form the OS:
    mysqld –remove
  • Install the MySQL service again, now with the new version path. As you see I explicity specify the default name of the service as MySQL and point it to where my ini file lives so I know which ini files this service uses.
    “C:\Program Files\MySQL\MySQL Server 8.0\bin\mysqld.exe” –install MySQL –defaults-file=”C:\Program Files\MySQL\MySQL Server 8.0\my.ini”
  • Start the MySQL Service
    NET START MYSQL

If all goes well that’s it, your new MySQL version is running. If so we, can jump to the part where you run the upgrade command to upgrade the system and user databases.  You can verify all went well in the error log. The name (mine is called WORKINGHARDINIT.err) as defined in the my.ini and is to be found under the data folder. Any problems will be logged there as well. This approach makes it easy to go back if the service won’t start as all files of the previous MySQL install are still there and you just have to install it as a service again.

Most common issues I have seen

My.ini file mistakes

The things that go wrong the most often and cause the MySQL service not to start -based on some of the support I have given to some people (including myself) are the following: certain options in your ini file are not compatible with the MySQL version you just installed.

Specifically for MySQL 8.0 make sure you comment out query_cache_size=0 (put a # in front of it) or remove the entry from the my.ini file.
#query_cache_size=0

If not the MySQL service won’t start. The error logged is:
[ERROR] [MY-011071] [Server] unknown variable ‘query_cache_size=0’

Next to that if you have the sql-mode entry in there this some times causes issues, so comment out that line as well. at least remove the offending entry, which might take some trial and error.
# sql-mode=”STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION”

As you can see the error log is the pointer to many issues with the MySQL service failing to start so do look there, that’s how you find what to do.

Data file ibdata1 is not writable

Sometimes you can see an error like this:
ERROR] [MY-012271] [InnoDB, InnoDB: The innodb_system data file ‘ibdata1’ must be writable

The 2 most common reasons are that the file is locked because you started mysqld.exe manually as you didn’t close a process you don’t know about/ cannot find that accesses it will also cause this error. A restart is then normally the easiest solution.

Sometimes people run into this due to permission problems (but with an upgrade this should not really happen). The MySQL service account (the default or the one you created and assigned) the need full control over the data folder. Check that.

Thinking you lost your blog

Another issue might be that MySQL is running but WordPress can’t find your blog. This might be 1 or more missing files such as ibdata1in the data folder root (hence I always make a copy of the entire data folder before I start an upgrade for safe keeping). The service might start but WordPress might not find your blog. In that case you’ll see a lot o warning similar to this in the error log:

Warning] InnoDB: Cannot open table wordpress592/wp_options from the internal data dictionary of InnoDB though the .frm file for the table exists.

So if these files are gone or corrupted, place them back from your spare copy or grab them from a backup. Most often these files are gone because some bad advise to delete these to fix a permission issue or a mistake. If they are not there they are recreated with the correct permissions but that causes the above issue.

Once you know the basics and you are careful, an upgrade process is mostly straightforward for most IT enthusiasts. Once MySQL is up and running and you can access your wordpress database again it’s time for the last step. Upgrade the databases.

Perform the MySQL upgrade run

Finally whenever you have done an upgrade don’t forget to run the mysql_upgrade.exe. This will take care of any upgrades needed to you system and user databases. Until you do you’ll see in the error log. If you don’t look there you might not even notice much but it pays to complete the complete upgrade process.

To do so, from an elevated command prompt navigate to C:\Program Files\MySQL\MySQL Server 8.0\Bin and run mysql_upgrade.exe-u root –p
Then enter the password and the upgrade process will kick off. This takes a while and it also depends on the amount of work the script has to do.

It 1st deals with the system database, when it finds out of date issues it will take care of those like in this case the sys schema.

Upgrading MySQL 5.7.21 to 8.0.11 for WordPress 4.9.5

Next it checks the user databases (in my case the word press database),

Upgrading MySQL 5.7.21 to 8.0.11 for WordPress 4.9.5

…  not much work to do here clearly.

Upgrading MySQL 5.7.21 to 8.0.11 for WordPress 4.9.5

That’s it. You’re all up to date. I normally do this about once or twice per year to make sure the blog server is up to date (performance, security, capabilities) & I don’t introduce tech debt and potentially more involved and risky upgrade scenarios. With a free community edition, that’s a zero cost game,bar a little effort on your part.

As a final note, when everything has proven to be up and running as it should do some housekeeping and clean up the old files / folders you no longer need of previous MySQL version installs.

Collect cluster nodes with HBA WWN info

Introduction

Below is a script that I use to collect cluster nodes with HBA WWN info. It grabs the cluster nodes and their HBA (virtual ports) WWN information form an existing cluster. In this example the nodes have Fibre Channel (FC) HBAs. It works equally well for iSCSI HBA or other cards. You can use the collected info in real time. As an example I also demonstrate writing and reading the info to and from a CSV.

This script comes in handy when you are replacing the storage arrays. You’ll need that info to do the FC zoning for example.  And to create the cluster en server object with the correct HBA on the new storage arrays if it allows for automation. As a Hyper-V cluster admin you can grab all that info from your cluster nodes without the need to have access to the SAN or FC fabrics. You can use it yourself and hand it over to those handling them, who can use if to cross check the info they see on the switch or the old storage arrays.

image

Script to collect cluster nodes with HBA WWN info

The script demos a single cluster but you could use it for many. It collects the cluster name, the cluster nodes and their Emulex HBAs. It writes that information to a CSV files you can read easily in an editor or Excel.

image

The scripts demonstrates reading that CSV file and parsing the info. That info can be used in PowerShell to script the creation of the cluster and server objects on your SAN and add the HBAs to the server objects. I recently used it to move a bunch of Hyper-V and File clusters to a new DELLEMC SC Series storage arrays. That has the DELL Storage PowerShell SDK. You might find it useful as an example and to to adapt for your own needs (iSCSI, brand, model of HBA etc.).

#region Supporting Functions
Function Convert-OutputForCSV {
    <#
        .SYNOPSIS
            Provides a way to expand collections in an object property prior
            to being sent to Export-Csv.

        .DESCRIPTION
            Provides a way to expand collections in an object property prior
            to being sent to Export-Csv. This helps to avoid the object type
            from being shown such as system.object[] in a spreadsheet.

        .PARAMETER InputObject
            The object that will be sent to Export-Csv

        .PARAMETER OutPropertyType
            This determines whether the property that has the collection will be
            shown in the CSV as a comma delimmited string or as a stacked string.

            Possible values:
            Stack
            Comma

            Default value is: Stack

        .NOTES
            Name: Convert-OutputForCSV
            Author: Boe Prox
            Created: 24 Jan 2014
            Version History:
                1.1 - 02 Feb 2014
                    -Removed OutputOrder parameter as it is no longer needed; inputobject order is now respected 
                    in the output object
                1.0 - 24 Jan 2014
                    -Initial Creation

        .EXAMPLE
            $Output = 'PSComputername','IPAddress','DNSServerSearchOrder'

            Get-WMIObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled='True'" |
            Select-Object $Output | Convert-OutputForCSV | 
            Export-Csv -NoTypeInformation -Path NIC.csv    
            
            Description
            -----------
            Using a predefined set of properties to display ($Output), data is collected from the 
            Win32_NetworkAdapterConfiguration class and then passed to the Convert-OutputForCSV
            funtion which expands any property with a collection so it can be read properly prior
            to being sent to Export-Csv. Properties that had a collection will be viewed as a stack
            in the spreadsheet.        
            
    #>
    #Requires -Version 3.0
    [cmdletbinding()]
    Param (
        [parameter(ValueFromPipeline)]
        [psobject]$InputObject,
        [parameter()]
        [ValidateSet('Stack', 'Comma')]
        [string]$OutputPropertyType = 'Stack'
    )
    Begin {
        $PSBoundParameters.GetEnumerator() | ForEach {
            Write-Verbose "$($_)"
        }
        $FirstRun = $True
    }
    Process {
        If ($FirstRun) {
            $OutputOrder = $InputObject.psobject.properties.name
            Write-Verbose "Output Order:`n $($OutputOrder -join ', ' )"
            $FirstRun = $False
            #Get properties to process
            $Properties = Get-Member -InputObject $InputObject -MemberType *Property
            #Get properties that hold a collection
            $Properties_Collection = @(($Properties | Where-Object {
                        $_.Definition -match "Collection|\[\]"
                    }).Name)
            #Get properties that do not hold a collection
            $Properties_NoCollection = @(($Properties | Where-Object {
                        $_.Definition -notmatch "Collection|\[\]"
                    }).Name)
            Write-Verbose "Properties Found that have collections:`n $(($Properties_Collection) -join ', ')"
            Write-Verbose "Properties Found that have no collections:`n $(($Properties_NoCollection) -join ', ')"
        }
 
        $InputObject | ForEach {
            $Line = $_
            $stringBuilder = New-Object Text.StringBuilder
            $Null = $stringBuilder.AppendLine("[pscustomobject] @{")

            $OutputOrder | ForEach {
                If ($OutputPropertyType -eq 'Stack') {
                    $Null = $stringBuilder.AppendLine("`"$($_)`" = `"$(($line.$($_) | Out-String).Trim())`"")
                }
                ElseIf ($OutputPropertyType -eq "Comma") {
                    $Null = $stringBuilder.AppendLine("`"$($_)`" = `"$($line.$($_) -join ', ')`"")                   
                }
            }
            $Null = $stringBuilder.AppendLine("}")
 
            Invoke-Expression $stringBuilder.ToString()
        }
    }
    End {}
}
function Get-WinOSHBAInfo {
<#
Basically add 3 nicely formated properties to the HBA info we get via WMI
These are the NodeWWW, the PortWWN and the FabricName. The raw attributes
from WMI are not readily consumable. WWNs are given with a ":" delimiter.
This can easiliy be replaced or removed depending on the need.
#>

param ($ComputerName = "localhost")
 
# Get HBA Information
$Port = Get-WmiObject -ComputerName $ComputerName -Class MSFC_FibrePortHBAAttributes -Namespace "root\WMI"
$HBAs = Get-WmiObject -ComputerName $ComputerName -Class MSFC_FCAdapterHBAAttributes  -Namespace "root\WMI"
 
$HBAProperties = $HBAs | Get-Member -MemberType Property, AliasProperty | Select -ExpandProperty name | ? {$_ -notlike "__*"}
$HBAs = $HBAs | Select-Object $HBAProperties
$HBAs | % { $_.NodeWWN = ((($_.NodeWWN) | % {"{0:x2}" -f $_}) -join ":").ToUpper() }
 
ForEach ($HBA in $HBAs) {
 
    # Get Port WWN
    $PortWWN = (($Port |? { $_.instancename -eq $HBA.instancename }).attributes).PortWWN
    $PortWWN = (($PortWWN | % {"{0:x2}" -f $_}) -join ":").ToUpper()
    Add-Member -MemberType NoteProperty -InputObject $HBA -Name PortWWN -Value $PortWWN
    # Get Fabric WWN
    $FabricWWN = (($Port |? { $_.instancename -eq $HBA.instancename }).attributes).FabricName
    $FabricWWN = (($FabricWWN | % {"{0:x2}" -f $_}) -join ":").ToUpper()
    Add-Member -MemberType NoteProperty -InputObject $HBA -Name FabricWWN -Value $FabricWWN
 
    # Output
    $HBA
}
}
#endregion 

#Grab the cluster nane in a variable. Adapt thiscode to loop through all your clusters.
$ClusterName = "DEMOLABCLUSTER"
#Grab all cluster node 
$ClusterNodes = Get-Cluster -name $ClusterName | Get-ClusterNode
#Create array of custom object to store ClusterName, the cluster nodes and the HBAs
$ServerWWNArray = @()

ForEach ($ClusterNode in $ClusterNodes) {
    #We loop through the cluster nodes the cluster and for each one we grab the HBAs that are relevant.
    #My lab nodes have different types installed up and off, so I specify the manufacturer to get the relevant ones.
    #Adapt to your needs. You ca also use modeldescription to filter out FCoE vers FC HBAs etc.
    $AllHBAPorts = Get-WinOSHBAInfo -ComputerName $ClusterNode.Name | Where-Object {$_.Manufacturer -eq "Emulex Corporation"} 

    #The SC Series SAN PowerShell takes the WWNs without any delimiters, so we dump the ":" for this use case.
    $WWNs = $AllHBAPorts.PortWWN -replace ":", ""
    $NodeName = $ClusterNode.Name

    #Build a nice node object with the info and add it to the $ServerWWNArray 
    $ServerWWNObject = New-Object psobject -Property @{
        WWN         = $WWNs
        ServerName  = $NodeName 
        ClusterName = $ClusterName         
    }
    $ServerWWNArray += $ServerWWNObject
}

#Show our array
$ServerWWNArray

#just a demo to list what's in the array
ForEach ($ServerNode in $ServerWWNArray) {    
    $Servernode.ServerName
    
    ForEach ($WWN in $Servernode.WWN)
    {$WWN}

}

#Show the results
$Export = $ServerWWNArray | Convert-OutputForCSV
#region write to CSV and read from CSV

#You can dump this in a file
$Export | export-csv -Path "c:\SysAdmin\$ClusterName.csv" -Delimiter ";"

#and get it back from a file
Get-Content -Path "c:\SysAdmin\$ClusterName.csv"
$ClusterInfoFile = Import-CSV -Path "c:\SysAdmin\$ClusterName.csv" -Delimiter ";"
$ClusterInfoFile | Format-List

#just a demo to list what's in the array
$MyClusterName = $ClusterInfoFile.clustername | get-unique
$MyClusterName
ForEach ($ClusterNode in $ClusterInfoFile) {  

    $ClusterNode.ServerName
    
    ForEach ($WWN in $ClusterNode.WWN) {
        $WWN
    }

}

Add HBAs to SC Series Servers with Add-DellScPhysicalServerHba

Introduction

Before I dump the script to add HBAs to SC Series Servers with Add-DellScPhysicalServerHba on you, first some context. I have been quite busy with multiple SAN migrations. A bunch of older DELLEMC SC Series (Compellent) to newer All Flash Arrays (see My first Dell SC7020(F) Array Solution)  When I find the time I’ll share some more PowerShell snippets I use to make such efforts a bit easier. It’s quite addictive and it allows you migrate effectively and efficiently.

In the SC Series we create cluster objects in which we place server objects. That make life easier on the SAN end.image

Those server objects are connected to the SAN via FC or iSCSI. For this we need to add the HBAs to the servers after we have set up the zoning correctly. That’s a whole different subject.

image

This is tedious work in the user interface, especially when there are many WWN entries visible that need to be assigned. Mistakes can happen. This is where automation comes in handy and a real time saver when you have many clusters/nodes and multiple SANs. So well show you how to grab the WWN info your need from the cluster nodes to add HBAs to SC Series Servers with Add-DellScPhysicalServerHba.

Below you see a script that loops through all the nodes of a cluster and gets the HBA WWNs we need. I than adds those WWNs to the SC Series server object. In another blog post I’ll share so snippets to gather the cluster info needed to create the cluster objects and server objects on the Compellent SC Series SAN. In this blog post we’ll assume the server have objects has been created.

We leverage the Dell Storage Manager – 2016 R3.20 Release (Public PowerShell SDK for Dell Storage API). I hope it helps.

Add HBAs to SC Series Servers with Add-DellScPhysicalServerHba

function Get-WinOSHBAInfo
#Basically add 3 nicely formated properties to the HBA info we get via WMI
#These are the NodeWWW, the PortWWN and the FabricName. The raw attributes
#from WMI are not readily consumable. WWNs are given with a ":" delimiter.
#This can easiliy be replaced or removed depending on the need. 
{ 
param ($ComputerName = "localhost")
 
# Get HBA Information
$Port = Get-WmiObject -ComputerName $ComputerName -Class MSFC_FibrePortHBAAttributes -Namespace "root\WMI"
$HBAs = Get-WmiObject -ComputerName $ComputerName -Class MSFC_FCAdapterHBAAttributes  -Namespace "root\WMI"
 
$HBAProperties = $HBAs | Get-Member -MemberType Property, AliasProperty | Select -ExpandProperty name | ? {$_ -notlike "__*"}
$HBAs = $HBAs | Select-Object $HBAProperties
$HBAs | % { $_.NodeWWN = ((($_.NodeWWN) | % {"{0:x2}" -f $_}) -join ":").ToUpper() }
 
ForEach ($HBA in $HBAs) {
 
    # Get Port WWN
    $PortWWN = (($Port |? { $_.instancename -eq $HBA.instancename }).attributes).PortWWN
    $PortWWN = (($PortWWN | % {"{0:x2}" -f $_}) -join ":").ToUpper()
    Add-Member -MemberType NoteProperty -InputObject $HBA -Name PortWWN -Value $PortWWN
    # Get Fabric WWN
    $FabricWWN = (($Port |? { $_.instancename -eq $HBA.instancename }).attributes).FabricName
    $FabricWWN = (($FabricWWN | % {"{0:x2}" -f $_}) -join ":").ToUpper()
    Add-Member -MemberType NoteProperty -InputObject $HBA -Name FabricWWN -Value $FabricWWN
 
    # Output
    $HBA
}
}
#Grab the cluster nane in a variable. Adapt thiscode to loop through all your clusters.
$ClusterName = "DEMOLABCLUSTER"
#Grab all cluster node 
$ClusterNodes = Get-Cluster -name $ClusterName | Get-ClusterNode

#Create array of custom object to store ClusterName, the cluster nodes and the HBAs
$ServerWWNArray = @()

ForEach ($ClusterNode in $ClusterNodes) {
    #We loop through the cluster nodes the cluster and for each one we grab the HBAs that are relevant.
    #My lab nodes have different types installed up and off, so I specify the manufacturer to get the relevant ones.
    #Adapt to your needs. You ca also use modeldescription to filter out FCoE vers FC HBAs etc.
    $AllHBAPorts = Get-WinOSHBAInfo -ComputerName $ClusterNode.Name | Where-Object {$_.Manufacturer -eq "Emulex Corporation"} 

    #The SC Series SAN PowerShell takes the WWNs without any delimiters, so we dump the ":" for this use case.
    $WWNs = $AllHBAPorts.PortWWN -replace ":", ""
    $NodeName = $ClusterNode.Name

    #Build a nice node object with the info and add it to the $ServerWWNArray 
    $ServerWWNObject = New-Object psobject -Property @{
        WWN         = $WWNs
        ServerName  = $NodeName 
        ClusterName = $ClusterName         
    }
    $ServerWWNArray += $ServerWWNObject
}

#Show our array
($ServerWWNArray).WWN

#just a demo to list what's in the array
ForEach ($ServerNode in $ServerWWNArray) {
    
    $Servernode.ServerName
    $Servernode.WWN
}

#Now add the HBA to the servers in the cluster.
#This is part of a bigger script that gathers all HBA/WWN infor for all clusters
#and creates the Compellent SC Series Cluster Object, the Servers, add the HBA's
#I'll post more snippets in futire blog post to show how to do that and give you
#some ideas for your own environment.

import-module "C:\SysAdmin\Tools\DellStoragePowerShellSDK\DellStorage.ApiCommandSet.dll"

#region SetUpDSMAccess Variable & credentials
Get-DellScController
$DsmHostName = "MyDSMHost.domain.local"
$DsmUserName = "MyUserName"
# Prompt for the password
$DsmPassword = Read-Host -AsSecureString -Prompt "Please enter the password for $DsmUserName"

# Create the connection
Connect-DellApiConnection -HostName $DsmHostName -User $DsmUserName -Password $DsmPassword -Save MyConnection 

#Assign variables
$ConnName = "MyConnection "
$ScName = "MySCName"

# Get the Storage Center
$StorageCenter = Get-DellStorageCenter -ConnectionName $ConnName -Name $ScName


ForEach ( $ClusterNodeWWNInfo in  $ServerWWNArray ) {
    # Get the server
    $Server = Get-DellScPhysicalServer -StorageCenter $StorageCenter -Name $ClusterNodeWWNInfo.ServerName
    $PortType = [DellStorage.Api.Enums.FrontEndTransportTypeEnum] "FibreChannel"
  
    ForEach ($WWN in $ClusterNodeWWNInfo.WWN)
    {
     # Add the array of WWNs for the cluster node and add them to the SC Compellent server
      Add-DellScPhysicalServerHba -ConnectionName $ConnName `
     -Instance $Server `
     -HbaPortType $PortType `
     -WwnOrIscsiName $WWN  -Confirm:$false
     }
}