Backup HP ProCurve Switches via SSH, TFTP and PowerShell

15. February 2017

blog.feldmann.io

PowerShell Version: >4 
Modules: Posh-SSH

So, this is a pretty specific one! I have been tasked to backup old and new ProCurve Switches and of course I am using PowerShell for this 😉 I found a script about doing this via SFTP where you enable ip ssh filetransfer on the switches and get the files from there but unfortunately two of the 2610’s in the environment do a reboot on every sftp connection…so…that is not an option here 😉 The only good alternative I came up with was to SSH on the client and use TFTP to copy the configs where you want them. The tftp client is enabled on the ProCurve’s by default so what you need to do this is PowerShell with Posh-SSH, and a TFTP Server:

#import posh-ssh
Import-Module -name posh-ssh

# globals
$today = Get-Date -Format "ddMMyyy"
$month = Get-Date -Format MMMM
$year = Get-Date -Format "yyyy"
$tftp_server = "IP OF YOUR TFTP SERVER"

# create a folder for every year
Get-Item "C:\switch_backup\$year\" -ErrorAction SilentlyContinue
if (!$?)
    {
    New-Item "C:\switch_backup\$year\" -ItemType Directory
    }

# create a folder for every month
Get-Item "C:\switch_backup\$year\$month\" -ErrorAction SilentlyContinue
if (!$?)
    {
    New-Item "C:\switch_backup\$year\$month\" -ItemType Directory
    }

# create a folder for every day
Get-Item "C:\switch_backup\$year\$month\$today\" -ErrorAction SilentlyContinue
if (!$?)
    {
    New-Item "C:\switch_backup\$year\$month\$today\" -ItemType Directory
    }

# simple credential handling
$username = "manager"
$pwfile = "C:\tmp\cred.txt"
$Credentials=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, (Get-Content $pwfile | ConvertTo-SecureString)

# put all the devices in this array
$switches_array = @()
$switches_array = "SWITCHIP","SWITCHIP","SWITCHIP"

foreach ($switch in $switches_array)
    {
    # create a folder for every device
    Get-Item "C:\switch_backup\$year\$month\$today\$switch" -ErrorAction SilentlyContinue
    if (!$?)
        {
        New-Item "C:\switch_backup\$year\$month\$today\$switch" -ItemType Directory
        }
    # start the SSH Session
    New-SSHSession -ComputerName $switch -Credential $Credentials -AcceptKey:$true
    $session = Get-SSHSession -Index 0
    # usual SSH won't work, we need a shell stream for the procurve
    $stream = $session.Session.CreateShellStream("dumb", 0, 0, 0, 0, 1000)
    # send a "space" for the "Press any key to continue" and wait before you issue the next command
    $stream.Write("`n")
    Sleep 5
    # copy startup-config and wait before you issue the next command
    $stream.Write("copy startup-config tftp $tftp_server \$year\$month\$today\$switch\startup-config`n")
    Sleep 10
    # copy running-config and wait before you issue the next command
    $stream.Write("copy running-config tftp $tftp_server \$year\$month\$today\$switch\running-config`n")
    Sleep 10
    # disconnect from host
    Remove-SSHSession -SessionId 0
    # compare running and startup config and remove running-config if equal
    $running_config = Get-Content C:\switch_backup\$year\$month\$today\$switch\running-config -ErrorAction SilentlyContinue
    $startup_config = Get-Content C:\switch_backup\$year\$month\$today\$switch\startup-config -ErrorAction SilentlyContinue
    $comparison = Compare-Object -ReferenceObject $startup_config -DifferenceObject $running_config
    if (!$comparison)
        {
        Remove-Item C:\switch_backup\$year\$month\$today\$switch\running-config -Force
        }
    }

As for the creds I chose a password file as secure-string – not the safest but fairly easy to work with:

Read-Host "Enter Password:" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "C:\tmp\cred.txt"

 

#PowerShell
6 Comments
Matthias
17. February 2017 @ 14:30

Hi,

nice script.

Is it possible to check via stream.read() the result/end of the copy commands instead of waiting/hoping for finishing with sleep(10)?

Reply
admin
17. February 2017 @ 15:33

As soon as you get too many lines as feedback from the ssh session the connection will cut off so I would not recommend $stream.read() in this case 😉

Reply
Yano
1. June 2017 @ 16:46

Hi there, thank you for the script.

I got trouble using it, there isn’t any comment about the TFTP server.

How do you handle this point ? I’ve try to install TFTP on a Windows Server 2016 but it doesn’t work.

Reply
    Sebastian
    1. June 2017 @ 16:58

    You can use any kind of freeware TFTP server that works with your OS, I used tftp64 on 2008R2.

    Reply
      Yanover
      2. June 2017 @ 10:13

      I’ve installed tftp64 on my WSRV2016

      I’ve launch it and changed the Current Directory as “C:\tftp\”. I’ve choose the right network interface.

      When I run a copy running-config tftp IP_ADDR_TFTP_SRV, it says “000M Transport error” ..

      Of course the firewall is disable and tftp transport is enable as client server on my switch.

      Thank you

      Reply
majkundo
26. September 2019 @ 16:31

Hi i don’t know if this is still relevant but instead of using to type all de ip adresses in the array you can get it to take it out of a file with for example
[string[]]$switches_array = (Get-Content -Path “C:\temp\hostnames.txt”)

i have a script that gets all the hostnames of my switches from my dns and then puts them in a .txt file so when a new switch is put in production it automaticly gets backed-up

$username = “yourusername”
#the first time you want to run this script first make a password with the following line. after that you can delete it
“password” | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString > C:\temp\credentials.txt
$pw = get-content C:\temp\credentials.txt | convertto-securestring
$Credentials=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$pw

$session = New-PSSession -ComputerName “yourdomaincontroller” -Credential $Credentials

Invoke-Command $session -Scriptblock { Import-Module dnsserver }

Import-PSSession -Session $session -module dnsserver
#all my switches hostnames start with sw but i wanted to exclude the core and storage switches
Get-DnsServerResourceRecord -ZoneName “example.local” -RRType “A” | Where-Object -filter {($_.Hostname -Match “sw*”) -and ($_.hostname -notmatch “swcore*”) -and ($_.hostname -notmatch “swstorage*”)} | Format-Table -Property “Hostname” > C:\temp\hostnames.txt

Exit-PSSession

Get-PSSession | Remove-PSSession
#this cleans the textfile
(gc C:\Temp\hostnames.txt) -notmatch “hostname” | Out-File C:\Temp\hostnames.txt
(gc C:\Temp\hostnames.txt) | Foreach {$_ -replace “-“, “”} | ? {$_.trim() -ne “” } | Foreach {$_ -replace “`t”, “”} | ForEach {$_.TrimEnd()} | Set-Content C:\Temp\hostnames.txt

enjoy

Reply

Leave a Reply

Your email address will not be published. Required fields are marked *


*