Distribute files to servers with PowerShell

Our streaming platform has 10 edge servers but most of them are on standby. They will only be in service when there is a high demand. Most of the time they are shutdown.

At this point when there is a new costumer or we need to change a setting for an existing customer we have to do this by hand on every server. This is very time consuming of course and there is a risk of making a mistake on one of the edge servers.

The problem is that not all the edge servers are in the same network. So it was not possible to make a script that does a simple file copy. Of course all the servers have an internet connection. So I thought what if I put the configuration files on a web server. And let the edge servers download the files and put them in the right directory.  It sounds like something that could work.

But how do the edge servers know what files to download and where to put them. The last thing I wanted is to have to update the download script on every edge server when I have placed a new configuration file on the web server.

I solved this by placing an xml file on the web server, I called it manifest.xml. In the manifest file I did put the download url for the file and the destination directory on the edge server. The download script now first downloads the manifest.xml file. Parses the xml file and one by one gets the file from the url and places it in the  destination directory. So now I only have to make a change in one place.

You could schedule the script on the server. For example when the server starts.

The current version of the script is not very smart, but it is functional.

Script:

## Version: 0.2
## Date: 31-12-2012
#Change $VerbosePreference to Continue to see verbose messages
#Change $VerbosePreference to SilentlyContinue to hide verbose messages
$VerbosePreference = "Continue"

Function Get-FilesDistributionManifest {
 param ([string]$url=$(Throw "ERROR: URL is missing"))

$downloadstring = $url
 $webclient = new-Object System.Net.WebClient

try {
 Write-Verbose "Trying to download file $url"
 [xml]$manifest = $webclient.DownloadString($downloadstring)
 }
 catch [System.Net.WebException]{
 Write-Error "ERROR: Unable to download manifest $url. Check the url!"
 }
 finally {
 Write-Verbose "Succesfully downloaded manifest $url$filename."
 }
Return $manifest
}

Function Get-FilesDistributionFile {
 param ([ValidateNotNullorEmpty()][string]$url,
 [ValidateNotNullorEmpty()][string]$filename,
 [ValidateNotNullorEmpty()][string]$destination)
 $webclient = new-Object System.Net.WebClient

try {
 Write-Verbose "Trying to download file $url$filename"
 $webclient.DownloadFile("$url$filename","$destination$filename")
 }
 catch [System.Net.WebException] {
 Write-Error "ERROR: Unable to download $url$filename. Check the url!"
 }
 finally {
 Write-Verbose "Succesfully downloaded $url$filename to $destination$filename"
 }
}
$xml = Get-FilesDistributionManifest -url "http://webserver/manifest/manifest.xml"

foreach ($file in $xml.files.file) {
 Get-FilesDistributionFile -url $($file.url) -filename $($file.filename) -destination $($file.destination)
}

The manifest.xml file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<files>
 <Version>1</Version>
 <file>
 <url>http://webserver/manifest/</url>
 <filename>file.txt</filename>
 <destination>c:\test\</destination>
 </file>
 <file>
 <url>http://webserver/manifest/</url>
 <filename>file2.txt</filename>
 <destination>c:\test\</destination>
 </file>
 <file>
 <url>http://webserver/manifest/</url>
 <filename>file3.txt</filename>
 <destination>c:\test\</destination>
 </file>
</files>

There are some improvements to make to the script.

  1. Authentication on the webserver.
  2. Only download the files when they are changed.
  3. Make a backup of the old file, if it exists, before downloading and replacing.
  4. Better error handling

Feel free to use the script in anyway you like!

 

Advertisements