Network Automation with Powershell
icons8.com

Network Automation with Powershell

Dude, you're late to the party!

Network automation has become extremely popular over recent years and for good reason. With the rise of Software Defined Networking, Containerization, and Hybrid Cloud operation models, Network Engineers need a way to speed up or eliminate time spent on the tedious but necessary tasks that can consume their day to day.

As a Network Engineer for the past ten years, I've learned a lot about many different technologies but as we all know in this profession, the learning never stops. Recently I've found myself in a new role where I have the freedom to come up with creative solutions for issues and the time to execute them. With new doors open to things like Azure, AWS, GCP, and a large private and public cloud infrastructure it made more sense to become serious about automation.

The purpose of this article is to begin a narration into what will hopefully be a successful journey into learning about network automation and successes and failures I'll surely have along the way. If even one of these articles helps someone else find an answer to a question that they have or cuts down on some of the leg-work needed to solve an issue, it is worth it to me.

My current interests lie within Ansible, Terraform, Linux Shell Scripting, Powershell, Containerization, Security, Virtualization, and of course many of our favorite networking hardware vendors. If any of this looks interesting to you as well, please join me!

Let's get started

The first issue that I've come across in this new role was one dealing with something we are all familiar with - network equipment OS upgrades. This task can take weeks, months, or even years depending on your fleet and generally, once you've finished it is time to start over again from the beginning. This is a great opportunity to begin with automation and a little extra effort on the front end may save us hours in the long run!

Now my challenge was exacerbated by new (to me) hardware and software as well as the lack of what I originally scoped as the ideal tool for the job which was a Linux workstation.

No alt text provided for this image

The switches that I would be upgrading were Arista and, as many other vendors, I found that they run a Linux kernel underneath their EOS. To me this meant that possibly a simple Bash script could get what I needed done. However, my organization does not allow Linux workstations for auditing purposes and that option is off the table.

This brings me to what was my second, but should have been my first question: What are the sub-tasks that need to be accomplished to get my objective complete? I found that breaking the workflow into manageable chunks made it easier for me to understand what my script or code needed to accomplish. For this, I came up with the following list:

  1. Code/Script must be run from a Windows workstation
  2. Remotely authenticate to the switch(es)
  3. Perform a check for older images
  4. Remove older images to preserve disk space
  5. Push my intended target image to the switch

Now I could have taken this list further and even automated the boot configuration change and reload of the switch. However, for my use-case I chose to have manual control over the actual upgrade trigger to allow for maintenance window scheduling and downtime control.

With this list in mind, I now knew that Ansible was off the table as well which was a bummer because I'd found a playbook which fit my needs perfectly! I thought this one in particular was interesting among many others using Ansible: https://www.wandynamics.com/blog/eos-upgrade-with-ansible

Luckily, my current mentor offered an alternative solution with Powershell and was even nice enough to share a snippet of what would eventually be my first automation script!

The nuts and bolts (AKA nerd knobs): ENTER POWERSHELL

With a little bit of guidance and direction, I've found that I can make just about anything happen. I was able to re-purpose part of an existing Powershell script used previously for F5 Loadbalancers to give myself a head start! Below is what I was able to pull out and reuse:

if (Get-Module -ListAvailable -Name "WinSCP") 
    Import-Module WinSCP
} else {
    Write-Host "WinSCP Module is not installed, please install module and try agian." -ForegroundColor Red
    Break
}


$credentials = Get-Credential


    $sessionOption = New-WinSCPSessionOption -Credential $credentials -Hostname $switch -Protocol Scp
    $hostkey = Get-WinSCPHostKeyFingerprint -SessionOption $sessionOption -Algorithm SHA-256
    $sessionOption = New-WinSCPSessionOption -Credential $credentials -Hostname $switch -Protocol Sftp -SshHostKeyFingerprint $hostkey
    New-WinSCPSession -SessionOption $sessionOption > $null         

This may seem simple to some but to me, this was the jumping block that I needed and gave me a starting point to both logically and physically build the remainder of my script. Essentially for those that don't understand what the above snippet means, we're calling a module which needs to be installed within Powershell to utilize WinSCP commands and creating an SSH session!

Get-Module -ListAvailable -Name "WinSCP" = We're going to use WinSCP to connect and modify files.

$sessionOption = A dynamic variable that we're building to set ports, protocols, and keys to foster that connection.

I realize that I may have skipped over my selection of WinSCP as a tool which could be used for this objective. I've used the WinSCP GUI many times to push or pull files from one machine to another so I knew it was an option. In fact, my backup plan was to use this again to get these files uploaded manually. But now we get to use it automagically via CLI!

No alt text provided for this image


The rest of the Powershell script, I literally just made up. I had no idea what other commands were at my disposal but I knew in order to make progress, I had to put something else in the script. So, I made it up with the help of Powershell. I started typing and my new friend helped me with auto-complete to make sense of my scrambled thoughts. For instance, to meet my sub-task goals I knew I needed to have something like "if a file with name like EOS-4.24.x.swi exists within the directory, remove it!" This turned into the following:

$switchpath = "/mnt/flash/"
$switchfullpath = $switchpath + $oldeos   
.
.
.
  if (Get-WinSCPItem $switchfullpath) 
          Write-Host "Removing old EOS file from $switch" -ForegroundColor Green    
          Remove-WinSCPItem -Path $switchfullpath -Confirm:$false
      }        

Here, the statement I've made is the same. I've just had to define other variables elsewhere in the script which help my script interpret where these files should be and what their name should be to match the criteria.

Ok, how about "Sequentially, after space has been freed for the new EOS, push this file to the switch and into the correct directory". That ended up looking something like this:

$localpath = (Get-Location).Path + "\" + $neweos
$remotepath = $switchpath + $neweos
.
.
.
if (-not (Get-WinSCPchilditem -Path $switchpath -Filter $oldeos)) 
        Write-Host "Uploading new EOS file to $switch" -ForegroundColor Green
        Send-WinSCPItem -Path $localpath -RemotePath $remotepath
    }        

Now I'd like to say a quick something about Powershell ISE because I was not aware of this when I started this project and it became very helpful to me. This tool is fantastic because it allows you as the engineer to create your script internally and debug it simultaneously as you write. You can literally test any variable, line, statement, or the script as a whole from within the same tool which is very powerful and efficient in my opinion.

This is the only reason that my script eventually ended up working! I was able to use resources from online to find the Cmdlet's needed and examples and then test them in real time against test switches to validate them. Below are some of the resource that I found to be very useful for your reference as well.

The Final Product

So after all this, what does it look like and most importantly, does it work?! Below is my full script (redacted) so that anyone can use it if it helps them do something similar. I was not able to find a Powershell script that did this specifically for Arista like I was with Ansible to hopefully the next person can spend less time on it!

This script works fantastically and does exactly what I intended. Can it be further refined? Yes. Can more features or functionality be included? You bet. Just because this works for me, doesn't mean it will work for you out of the box but hopefully it will provide someone with the jump start that they need to tailor it to their situation.

Here you go!

# This script will do the following
# Login to switches defined and check for old EOS version
# Remove n-1 version to free space for new EOS
# Push new EOS with SCP


if (Get-Module -ListAvailable -Name "WinSCP") {
    Import-Module WinSCP
} else {
    Write-Host "WinSCP Module is not installed, please install module and try agian." -ForegroundColor Red
    Break
}


$swlist = @("X.X.X.X","X.X.X.X")
$neweos = "EOS-X.X.X.swi"
$oldeos = "EOS-X.X.X.swi"
$switchpath = "/mnt/flash/"
$switchfullpath = $switchpath + $oldeos
$credentials = Get-Credential
$localpath = (Get-Location).Path + "\" + $neweos
$remotepath = $switchpath + $neweos


foreach ($switch in $swlist) {
    Write-Host "Connecting to switch $switch" -ForegroundColor Green
    $sessionOption = New-WinSCPSessionOption -Credential $credentials -Hostname $switch -Protocol Scp
    $hostkey = Get-WinSCPHostKeyFingerprint -SessionOption $sessionOption -Algorithm SHA-256
    $sessionOption = New-WinSCPSessionOption -Credential $credentials -Hostname $switch -Protocol Sftp -SshHostKeyFingerprint $hostkey
    New-WinSCPSession -SessionOption $sessionOption > $null 


    if (Get-WinSCPItem $switchfullpath) {
        Write-Host "Removing old EOS file from $switch" -ForegroundColor Green    
        Remove-WinSCPItem -Path $switchfullpath -Confirm:$false
    }



    if (-not (Get-WinSCPchilditem -Path $switchpath -Filter $oldeos)) {
        Write-Host "Uploading new EOS file to $switch" -ForegroundColor Green
        Send-WinSCPItem -Path $localpath -RemotePath $remotepath
    }
    Remove-WinSCPSession
}        

There are some things to point out from my script above that might be useful. I've used some "advanced" objects that I found as well which allow the script to run through a list of switches as defined with the variable $swlist. Note that "@" which denotes an array. If you print this variable, the output is an IP address per line.

Also I've used a "foreach" loop where I've nested the meat and potatoes of my commands to cycle through each $switch within $swlist array.

Finally, I've chose to add some pizzazz by printing within the Powershell console what stage of the script it is running to provide some sense of success/progress to those running it with the "Write-Host" line items.

That concludes this installment for now. I intend to keep myself very busy with projects such as these as I come across them and will keep uploading these articles as time allows. Thank you for those that found this helpful!

No alt text provided for this image







When your resources are limited you have to become creative to achieve the results you crave. Maybe one day you'll get that Linux server after they see the benefits.

Like
Reply

To view or add a comment, sign in

Others also viewed

Explore content categories