PowerShell: Move SnapMirror Destinations to a New Aggregate (7-Mode)

We got some new disk shelves in to replace some old ones on our NetApp filer. The old disks had a lot of SnapMirror destination volumes.All these needed migrating to the new disks. Initially we were planning on creating a new set of SnapMirrors from the source volumes to the destinations, and once these were complete, remove the original mirrors. This seemed like a long winded wasteful process – we did not particularly want 30Tb of data re-transmitted over the network, especially as an fully internal transfer would run at a significantly higher speed.

Also, we wanted to automate this process as much as possible, as this provided the smallest scope for error.

Hence the following script was born.

It runs through quite a simple process:

  • Load the DataONTAP PowerShell module if it is not available
  • Connect to the specified filer
  • Check that the source volume and the destination aggregate exist
  • Get details of the NFS exports on the volume and remove all NFS exports
  • Break the current SnapMirror relationship
  • Perform a Volume Move of the now writeable SnapMirror destination
  • Re-create the NFS exports
  • Re-sync the SnapMirror

The NFS exports have to be removed, as volume moves are not supported on volumes that have any exports configured. As long as the script runs to the end, the exports will be recreated once everything has completed.

# ----------------------------------------------------------------------------------------------------------
# PURPOSE:    Moves a SnapMirror Destination to a new aggregate, without re-initializing the SnapMirror from scratch. 
#
# VERSION     DATE         USER                DETAILS
# 1           27/10/2014   Craig Tolley        First version
# 1.1         14/11/2014   Craig Tolley        Added new parameter to pass in credentials, so that scripting multiple moves is easier and without prompts
#
# ----------------------------------------------------------------------------------------------------------

<#
.Synopsis
   Moves the specified volume to a new aggregate.

.EXAMPLE
   Move-SnapmirrorDestination -VolumeToMove Volume1 -DestinationAggr Aggr2 -FilerName Filer1

#>
function Move-SnapmirrorDestination
{
    [CmdletBinding()]
    Param
    (
        # The volume that we want to move
        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$false,
                   Position=0)]
        [String]$VolumeToMove,

        # The destination aggregate for the new volume
        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$false,
                   Position=1)]
        [String]$DestinationAggr,

        # The filer name to connect to 
        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$false,
                   Position=2)]
        [String]$FilerName,

        [Parameter(Position=3)]
        [System.Management.Automation.PSCredential]$FilerCredentials

    )

    #Check that that DataOnTap Module is available, check it is loaded. 
    Write-Host "Checking for DataONTAP Module..."
    if ((Get-Module -ListAvailable | Where {$_.Name -eq "DataONTAP"}).Count -ne 1) {
        Write-Error "DataONTAP not installed on targeted machine"
        Exit 1
        }
    if ((Get-Module | Where {$_.Name -eq "DataONTAP"}).Count -ne 1) {
        Write-Host "Importing DataONTAP Module..."
        Import-Module -Name "DataONTAP" | Out-Null
        }

    #If we have not been passed credentials, then prompt for them. 
    If ($FilerCredentials -eq $null)
        {$FilerCredentials = Get-Credential -Message "Please supply credentials for $FilerName"}

    #Connect to the Filer.
    Write-Host "Connecting to $FilerName" -BackgroundColor Yellow -ForegroundColor Black
    $Error.Clear()
    Connect-NaController -Name $FilerName -Credential $FilerCredentials
    If ($Error.Count -gt 0)
        {
        Write-Host "There was an error connecting to the filer. Please check your credentials and try again."
        Break
        }
    Write-Host ""

    #Get the Source Volume
    Write-Host "Getting details of Volume: $VolumeToMove" -BackgroundColor Yellow -ForegroundColor Black
    $SrcVolume = Get-NaVol $VolumeToMove
    If ($Error.Count -gt 0)
        {
        Write-Host "There was an error getting the details of the Volume. Please check that the volume name is correct and the volume is online."
        Break
        }
    $SrcVolume | ft
  
    #Get the Destination Aggregate
    Write-Host "Getting details of the destination aggregate: $DestinationAggr" -BackgroundColor Yellow -ForegroundColor Black
    $DestAggr = Get-NaAggr $DestinationAggr
    If ($Error.Count -gt 0)
        {
        Write-Host "There was an error getting the details of the Volume. Please check that the volume name is correct and the volume is online."
        Break
        }
    $DestAggr | ft

    #Get the NFS Exports for the Volume and Remove them
    Write-Host "Getting details of the NFS Exports" -BackgroundColor Yellow -ForegroundColor Black
    $NFSExports = Get-NaNfsExport | Where {$_.Pathname -like "*$($SrcVolume.Name)"}
    If (($NFSExports).Count -gt 0)
        {
        ForEach ($Exp in $NFSExports)
            {Remove-NaNfsExport $Exp}
        }
    Else 
        {Write-Host "No NFS Exports are configured for this volume"}
    Write-Host ""

    #Break all of the snapmirrors which are configured
    Write-Host "Breaking existing Snapmirrors" -BackgroundColor Yellow -ForegroundColor Black
    $SrcSnapMirrors = Get-NaSnapmirror $SrcVolume
    $SrcSnapMirrors | ft
    If (($SrcSnapMirrors).Count -gt 0)
        {
        ForEach ($Snapmirror in $SrcSnapMirrors)
            {Get-NASnapMirror $Snapmirror.Destination | Invoke-NaSnapmirrorBreak -Confirm:$false | Out-Null}
        }
    Else 
        {Write-Host "No Snapmirrors are configured for this volume"}
    Write-Host ""

    #Start the actual volume move. 
    Write-Host "Starting the Vol Move (Update every 15 seconds)" -BackgroundColor Yellow -ForegroundColor Black
    Start-NaVolMove -Volume $SrcVolume -DestAggr $DestAggr

    #Keep Running Until the Vol Move completes
    Get-NaVolMove | Where {$_.SourceVolumeName -eq $SrcVolume.Name} | ft
    Do
        {
        Get-NaVolMove | Where {$_.SourceVolumeName -eq $SrcVolume.Name} | ft -HideTableHeaders
        Start-Sleep 15
        }
    Until ((Get-NaVolMove | Where {$_.SourceVolumeName -eq $SrcVolume.Name}).Count -eq 0)

    #Recreate the NFS Exports
    Write-Host "Recreating the NFS Exports" -BackgroundColor Yellow -ForegroundColor Black
    ForEach ($Exp in $NFSExports)
        {Add-NaNfsExport $Exp}
    Write-Host ""

    #Resync all of the snapmirrors which are configured
    Write-Host "Re-synching all SnapMirrors" -BackgroundColor Yellow -ForegroundColor Black
    If (($SrcSnapMirrors).Count -gt 0)
        {
        ForEach ($Snapmirror in $SrcSnapMirrors)
            {Get-NASnapMirror $Snapmirror.Destination | Invoke-NaSnapmirrorResync -Confirm:$false | Out-Null}
        }

    #Complete
    Write-Host "  --  Completed Volume Move  -- "
}

If you wanted to use this to move a bunch of destinations to a new volume, then a short snippet like this does the job for you:

$VolsToMove = "volA", "volB"
$FilerLogin = Get-Credential
ForEach($v in $VolsToMove)
    {Move-SnapmirrorDestination -VolumeToMove $v -DestinationAggr newAggr -FilerName Filer1 -FilerCredentials $FilerLogin}

Be the first to like.
Posted in NetApp, Storage | Leave a comment

Assigning Permissions to Assign Networks to VM in vSphere

If you need to allow a specific user or group the permission to change the connected network on a virtual machine in vSphere, then permissions have to be given in a couple of places. This provides very granular control about the machines and the networks that a person can use, however may not be totally apparent when you are trying to get it working (it wasn’t apparent to me until I thought about the problem for a while).

Two distinct permissions are required:

Against the Virtual Machine that they want to edit

  • Virtual Machine –> Configuration –> Modify Device Settings
  • Virtual Machine –> Configuration –> Settings

Against the Network objects that they can assign

  • Network –> Assign Network

If the user or group in question does not have the Assign Network permission applied to the network object, then the object does not appear in the list of networks selectable. If there are no networks that the user has the Assign Network permission on, then the option to change the network assigned to a VM will not be available to that user.

Be the first to like.
Posted in VMWare | Leave a comment

IISCrypto – Making SSL/TLS Configuration Easier

Following the recent Poodle vulnerability, and the general best practice that you should always use the most secure protocols available, I have been spending some time reconfiguring servers.

Setting the order of ciphers, and enabling Forward Secrecy in Windows requires editing the registry – a lot. This is susceptible to errors, as the process is manual. Also, it doesn’t really give you a holistic picture of the before and after settings.

I stumbled across this tool from Nartac Software – IISCrypto. A free tool that shows you the current settings that you have for SSL/TLS, and a quick and easy way to change the active protocols and re-order the ciphers.

It is speedy and accurate. Perfect for updating a number of servers/systems manually.

Get it here: https://www.nartac.com/Products/IISCrypto/Default.aspx

Be the first to like.
Posted in Internet Security, Server 2003, Server 2008, Server 2012 | Leave a comment

Automating pfSense Backups

Just found a fantastic tool which is so simple and just works.

https://knowledge.zomers.eu/pfsense/Pages/How-to-automate-pfSense-backup.aspx

Downloaded, tested, in place and working within 15 minutes. Perfect!

Be the first to like.
Posted in Internet Security | Leave a comment

SQL Server Reporting Services – Rebuild Performance Counters

Got a lot (20+) of this sort of error in my event log.

SQL Reporting Services Performance Counter ErrorsThere is a guide on the Microsoft Wiki abou this here: http://social.technet.microsoft.com/wiki/contents/articles/1916.how-to-rebuild-the-report-server-performance-counters-ssrs.aspx, however, this alone is not enough to fix the issue.

The commands that I ran in order to get mine back up and running, from an elevated command prompt were:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe /u C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer\bin/ReportingServiceLibrary.dll
c:\windows\system32\lodctr.exe /r
C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer\bin/ReportingServiceLibrary.dll
net stop ReportServer
net start ReportServer

The errors no longer occurred when rebooting the server after this point.

Be the first to like.
Posted in SQL Server | Leave a comment

SharePoint 2013: Renaming the Database Server

There are a number of posts on this online, but none of them exactly described the steps that I needed to take in order to rename the server that was hosting the SQL databases for our SharePoint installation.

I was in the fortunate position that the system had not yet gone live, so rebooting and changing configuration was easy, however it had all been configured, so blowing it away and starting again was not an option.

Our setup is simple. 2 servers, In-SharePoint is the SharePoint 2013 server and was running the websites, and In-SharePointSQL the database server, running SQL Server.

Unfortunately we found that In-SharePointSQL was too long name, so the SQL instance actually was truncated to In-SharepointSQ <– note the missing L. This caused some issues with NetApp SnapManager for SQL, so for clarity and correctness I decided it would be better if this was called In-SharePointDB.

Our environment is virtualised, so before starting I took a snapshot and a backup. I dont need to tell you to be taking a backup before you make any changes :-)

1. We dont want the SharePoint site to be accessible, so first off, stop all the SharePoint services on the SharePoint server. Using PowerShell:

Get-Service -DisplayName SharePoint* | Stop-Service
Get-Service IISAdmin, W3SVC | Stop-Service

2. On the database server, perform the rename of server to the desired new name. Reboot when prompted.

3. Open up SQL Server Manager and run the following query, substituting in your server names:

sp_dropserver IN-SHAREPOINTSQL
go
sp_addserver IN-SHAREPOINTDB, local
go

4. Restart SQL Server on the database server

5. Verify that SQL is now returning the correct server name using this query:

Select @@SERVERNAME As 'ServerName

6. We now need to correct the SQL Server Reporting Server configuration. On the SQL Server, opne up SQL Server Reporting Services Configuration. Connect to the Report Server using the new SQL Server name.

7. Select Database Configuration on the left, then click Change Database. Choose the Existing Report Server Database option, and ollow through the wizard specifying your new SQL Server name and choosing the existing Report Server database.

8. Open the file %ProgramFiles%\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer\rsreportserver.config in Notepad. Search for tags called URLRoot and ReportServerURL and update if they are defined. In my case URLRoot was present and defined, requiring updating. The ReportServerURL tag was just blank though, in which case it can be left.

9. Restart the SQL Server Reporting Services service on the SQL Server.

10. Go to your SharePoint 2013 Web Server. Open cliconfg.exe. On the Alias tab click Add. Type in the old server name at the top, select TCP/IP on the left and then enter new server name on the right. It should look like this:

SQLAlias11. Restart the SharePoint Services

Get-Service IISAdmin, W3SVC | Start-Service
Get-Service -DisplayName SharePoint* | Start-Service

12. Open the SharePoint Management Shell and run the following command to update all of the databases to the new SQL instance.

Get-SPDatabase | ForEach {$_.ChangeDatabaseInstance("IN-SHAREPOINTDB")}

13. As a personal belt and braces, I then restarted the SharePoint server.

14. On the SharePoint server, open cliconfg.exe, go to the Alias tab and remove the alias that you created.

Complete!

Everything should now be working using the new server name for the SQL Server.

 

Be the first to like.
Posted in Server 2012, SharePoint, SQL Server | Leave a comment

Modifying GPO Printer Deployment using PowerShell

We use the Deployed Printers feature in the Print Management console to deploy printers to users. As part of the printer migration that I have been working on, I needed to modify all of these GPOs so that all of the policies directed all of the users to the new print server.

There are over 200 policies in existence. That would be a lot of manual work, that would be prone to errors.

Also, I needed to be able to change over print servers in around an hour. Editing 200 policies in an hour would be impossible.

This is what the result of this conundrum is. The script below goes out to find all of the deployed printers in all GPOs in the domain. It then looks for the name of the old print server, and replaces it with the name of the new print server.

The script fully supports the -WhatIf switch, and also an output of all of the printers that were found and what changes were made is output at the end of the process. I suggest that the output is piped to a variable, which can then be formatted as a table or exported into something more readable. I just provide the raw data here, you can do with it as you wish.

You will need the ActiveDirectory module loaded in your Powershell session, and you will also need to be running this script as a user that has sufficient permissions to modify GPO in your domain.

As always, test on a lab before running this on your production servers!

# ----------------------------------------------------------------------------------------------------------
# PURPOSE:    Modify all GPO's which have Pushed Printer Connections to a new print server name.
#
# VERSION     DATE         USER                DETAILS
# 1           22/08/2014   Craig Tolley        First version
#
#
# ----------------------------------------------------------------------------------------------------------

#Define the print server names. Should include the leading \\ to ensure it only matches at the start.
Function Modify-PushedPrinterConnections
{
[cmdletbinding(SupportsShouldProcess=$True)]

Param
    (
        #The name of the Old Print Server. This string will be searched for in order to be replaced.
        [Parameter(Mandatory=$true)]
        [string]$OldPrintServerName,

        #The name of the New Print Server. This will replace the Old Print Server value.
        [Parameter(Mandatory=$true)]
        [string]$NewPrintServerName
    )

#Collection detailing all of the work
$GPOPrinterDetails = @()

#Get all of the GPO objects in the domain.
$GPOs = Get-GPO -All
Write-Host "GPOs Retrieved: $($GPOs.Count)"


ForEach ($GPO in $GPOs)
{
    $PrintObjects = Get-ADObject -SearchBase "CN={$($GPO.Id)},CN=Policies,CN=System,DC=medlan,DC=cam,DC=ac,DC=uk" -Filter {objectClass -eq "msPrint-ConnectionPolicy"} -SearchScope Subtree
    
    ForEach ($PCO in $PrintObjects)
    {
        #Get the properties of the Print Connection Object that we actually need.
        $PrintConnection = Get-ADObject $PCO.DistinguishedName -Properties printerName, serverName, uNCName
    
        #Log details of the policy that we have found    
        $GPOPrinterDetail = @{
                    GPOId = $GPO.Id
                    GPOName = $GPO.DisplayName
                    PrintConnectionID = $PrintConnection.ObjectGUID
                    PrinterName = $PrintConnection.printerName
                    OriginalPrintServer = $PrintConnection.serverName
                    OriginalUNCName = $PrintConnection.uNCName
                    NewPrintServer = $null
                    NewUNCName = $null
                    ChangeStatus = "NotEvaluated"
                    }
        
        #Find out if we need to make a change or not.
        If ($PrintConnection.serverName.ToLower() -eq $OldPrintServerName.ToLower())
        {
            #Change the local instance
            $PrintConnection.serverName = $NewPrintServerName
            $PrintConnection.uNCName = $PrintConnection.uNCName.Replace($OldPrintServerName,$NewPrintServerName)
            
            #Update our reporting collection
            $GPOPrinterDetail.NewPrintServer = $PrintConnection.serverName
            $GPOPrinterDetail.NewUNCName = $PrintConnection.uNCName
            $GPOPrinterDetail.ChangeStatus = "ChangePending"
                        
            #Write the changes and catch any errors
            Try
                {Set-ADObject -Instance $PrintConnection -Verbose
                $GPOPrinterDetail.ChangeStatus = "ChangeSuccess"}
            Catch
                {$GPOPrinterDetail.ChangeStatus = "ChangeFailed"}
                
        }
        Else
        {
            $GPOPrinterDetail.ChangeStatus = "NoChange"
        }

        #Update the table
        $GPOPrinterDetails += New-Object PSObject -Property $GPOPrinterDetail
    }
 
}

#Finally write out the changes
Write-Output $GPOPrinterDetails

}

Be the first to like.
Posted in Active Directory, Powershell, Server 2012 | Leave a comment

Windows 2012: PrintService EventID 812 Error 0x5

Been working on a print server migration, and with the cutover we started noticing a lot of these errors in the PrintService Operational Log. This log has to be enabled before you will get these errors if you have not done so already.

 Event ID 812: Print Spool 0x5 ErrorAs part of the setup of this print server, a dedicated disk was attached to the system for the print spool in order to ensure that disk was not a bottleneck in print performance. Windows was left to create the new folder in the new location after changing the path in the Print Management console.

It turns out however that the permissions that Windows by default applies to the newly created folder aren’t actually enough.

Despite this particular error directly stating that the spooler failed to delete the file, the issue actually is that the spooler was failing to create the file first. Therefore once the job had completed the file was not there to delete.

I never found out where the spooler service was putting the files instead, assuming here that it continued to use the spool files. They were not being stored in the default C:\windows\system32\spool folder.

Our solution, was to add in the Authenticated Users group with Full Control permissions to the newly created spool folder.

Monitoring the folder after making this change, which then cleared the error, shows that the spool files are created. The files are created with the Owner being set to SYSTEM. The SYSTEM user had Full Control of the folder anyway. The delete file command seemed to be being run in the context of the user that printed the job. As that user was not the owner, the CREATOR OWNER permission did not suffice for removing the file.

Be the first to like.
Posted in Server 2012 | Leave a comment

Clean Up Unused Printer Drivers

Working on a printer migration project, and one of the first steps was to clean up the existing print servers so that when running the migration. I wanted a way to contact remote print servers too. This script, once imported allows cleanup of remote print servers.

Requires Powershell 4, so run off a Windows 8/Windows Server 2012.

If targeting a Windows 2003 print server, it cannot perform the actual removal and will just list a number of errors. It does atleast highlight all of the drivers which are not in use though.

# ----------------------------------------------------------------------------------------------------------
# PURPOSE: Remove Printer Drivers which do not have any printers
#
# VERSION DATE USER DETAILS
# 1 28/08/2014 Craig Tolley First version
# 1.1 29/08/2014 Craig Tolley Moved getting printers into variable to improve performance.
#
# ----------------------------------------------------------------------------------------------------------

#Define the print server names.
Function Remove-UnusedPrinterDrivers
{

Param
(
#The name of the print server to clean up.
[Parameter(Mandatory=$true)]
[string]$PrintServerName
)

#Get all of the printer drivers
$Drivers = Get-PrinterDriver -ComputerName $PrintServerName
$Printers = Get-Printer -ComputerName $PrintServerName

ForEach($Driver in $Drivers)
{
$PrintersUsingDriver = ($Printers | Where {$_.DriverName -eq $Driver.Name} | Measure).Count
Write-Host "Driver: $($Driver.Name) has $PrintersUsingDriver printers using it."

If ($PrintersUsingDriver -eq 0)
{
Try
{
Remove-PrinterDriver -Name $Driver.Name -ComputerName $PrintServerName -ErrorAction Stop
Write-Host " $($Driver.Name) has been removed." -ForegroundColor Green
}
Catch
{
Write-Host " Failed to remove driver: $($Driver.Name)" -ForegroundColor Red
}
}
Write-Host ""
}
}

Be the first to like.
Posted in Powershell, Server 2003, Server 2008, Server 2012 | Leave a comment

WhatsUp Gold Raspberry Pi Monitor

I have worked out a way to get a full screen display of a specific dashboard for use with a digital signage display using a Raspberry Pi, using only a web browser.

The Dashboard client was ok, but required a Windows machine, and although we could use the existing web page with automatic login (http://community.whatsupgold.com/forums/whatsupgoldeditionsstandardandpremiumeditions/automatic-login-by-url) too much space was lost using the menu and title bars.

So, here it is:

  1. On your WUG server, browse to the installation directory: C:\Program Files (x86)\Ipswitch\WhatsUp\HTML\NmConsole\Workspace\HomeWorkspace
  2. Take a copy of HomeWorkspace.asp and call it HomeWorkspaceMonitor.asp
  3. Open the file in your favourite editor and remove the following sections:
    1. AddNavigation();
    2.  <% AddWorkspaceViewTabs(WT_UNIVERSAL); %>
    3.  <div id=”titlebar”>
      ‘ <h2><%= $.tr(“Home”) %></h2>
      ‘ <% AddWorkspaceToolbarButtons($.tr(“Home Dashboard”), WT_UNIVERSAL) %>
      </div>
  4. Save the file.
  5. Open up your browser and enter the URL, substituting your server name, the ID of the workspace you want to view and a valid username and password: http://localhost/NmConsole/Workspace/HomeWorkspace/HomeWorkspaceMonitor.asp?HomeWorkspace.nWorkspaceID=10025&sUsername=DisplayRead&sPassword=DisplayRead

This gave us a page with only the actual content of the dashboard. We set the user account to have very limited access, and then set a Raspberry Pi to autoload Firefox, full screen and browse to this page.

WUG.png

Hopefully this will be useful to others

Be the first to like.
Posted in Monitoring, Raspberry Pi | Leave a comment
  • Tags

  • Categories

  • My LinkedIn Profile

    To see my LinkedIn profile, click here:

    Craig Tolley
  • November 2014
    M T W T F S S
    « Oct    
     12
    3456789
    10111213141516
    17181920212223
    24252627282930
  • Meta

  • Top Liked Posts

    Powered by WP Likes

Swedish Greys - a WordPress theme from Nordic Themepark.