13 January, 2015

Move page file remotely - OS

With many servers in the environment, there are inevitably a bunch of them which are old, they have small disk capacity but they are needed "just for another couple of months" until the new system is up... and a couple of years later you are still the chosen one to keep them alive.

There are many challenges with these old boxes, so let me pick one: there's not enough disk space on drive C: and there's not much more to delete anymore. Last resort: move the pagefile to another drive (if there's one in the box). Let's script it to be able to make this change on many servers remotely.

Need to check a couple of things:
  • the original page file's details
  • target drive exists
  • it has sufficient space to accommodate the page file (based on MaximumSize)
  • target drive is local and is not hosted on SAN

Create the output object and get data of the current page file:
$obj = "" | Select ComputerName,OldPageFile,OldInitSize,OldMaxSize,Result
$obj.ComputerName = $srv
$pagefiledata = gwmi -ComputerName $srv -Class Win32_PageFileSetting

Get details of the volume where we want to move the page file (check whether it exists, whether there's enough space on it - here the limit is the size of the current page file twice)
$targetvolume = gwmi -ComputerName $srv -Class Win32_LogicalDisk -Filter "name='$movetodrive'"

Create new page file:
$result = Set-WmiInstance -ComputerName $srv -Class Win32_PageFileSetting -Arguments @{name="$targetfilename";InitialSize=$obj.OldInitSize;MaximumSize=$obj.OldMaxSize;}

Sometimes - especially on Windows Server 2003 - the Set-WmiInstance can't create the page file if the InitialSize and MaximumSize are set in the same command, for that the workaround is to create the page file as system managed (without additional parameters) and set the size afterwards.
$result = Set-WmiInstance -ComputerName $srv -Class Win32_PageFileSetting -Arguments @{name="$targetfilename"}

if($result.name -eq $targetfilename){
  $newPGFile = gwmi -ComputerName $srv -Query "Select * from Win32_PageFileSetting where name '$($targetfilename.replace("\","\\"))'"
  $newPGFile.InitialSize = $obj.OldInitSize
  $newPGFile.MaximumSize = $obj.OldMaxtSize
  $FinalResult = $newPGFile.Put()
}


If we do this, the script should check all the parameters we set and the existence of the new page file as part of error handling:
$checkoutPGFile = gwmi -ComputerName $srv -Query "Select * from Win32_PageFileSetting where name '$($targetfilename.replace("\","\\"))'"
if(!($checkoutPGFile -and ($checkoutPGFile.Maximumsize -eq $obj.OldMaxSize) -and ($checkoutPGFile.Maximumsize -eq $obj.OldMaxSize))){...

If all is good with the new page file, we can get rid of the old one, of course this will require a reboot but I decided to leave it to the scheduled reboots of the servers.
$oldPageFileObject = gwmi -ComputerName $srv -Query "Select * from Win32_PageFileSetting where name = '$searchString'"
$oldPageFileObject.Delete()

The full script which can take a list of hosts from the pipe, does all the checks looks like this (obviously I stripped out all the logging and fancy stuff so the essence of it is easier to see):
   
 $hostlist = @($input)  
   
 $objColl = @()  
 $movetodrive = "D:"  
 $targetfilename = $movetodrive + "\pagefile.sys"  
   
 foreach($srv in $hostlist){  
    $obj = "" | Select ComputerName,OldPageFile,OldInitSize,OldMaxSize,Result  
    $obj.ComputerName = $srv  
   
    $pagefiledata = gwmi -ComputerName $srv -Class Win32_PageFileSetting  
      
    if($pagefiledata){  
       $obj.OldPageFile = $pagefiledata.name  
       $obj.OldInitSize = $pagefiledata.Initialsize  
       $obj.OldMaxSize = $pagefiledata.Maximumsize  
         
       $targetvolume = gwmi -ComputerName $srv -Class Win32_LogicalDisk -Filter "name='$movetodrive'"  
         
       if(!$targetvolume){  
          $obj.Result = "$movetodrive does not exist"  
          $objColl += $obj  
          Continue  
       }  
         
       if(($targetvolume.Freespace / 1MB) -lt ($obj.OldMaxSize * 2)){  
          $obj.Result = "Not enough space on $movetodrive"  
          $objColl += $obj  
          Continue  
       }  
         
       $result = Set-WmiInstance -ComputerName $srv -Class Win32_PageFileSetting -Arguments @{name="$targetfilename";InitialSize=$obj.OldInitSize;MaximumSize=$obj.OldMaxSize;}  
         
       # this is needed in case the WMI instance can't be created with all parameters in one go  
       if(!($result.name -eq $targetfilename)){  
          $result = Set-WmiInstance -ComputerName $srv -Class Win32_PageFileSetting -Arguments @{name="$targetfilename"}  
         
          if($result.name -eq $targetfilename){  
             $newPGFile = gwmi -ComputerName $srv -Query "Select * from Win32_PageFileSetting where name '$($targetfilename.replace("\","\\"))'"  
             $newPGFile.InitialSize = $obj.OldInitSize  
             $newPGFile.MaximumSize = $obj.OldMaxtSize  
             $FinalResult = $newPGFile.Put()  
          }  
            
          $checkoutPGFile = gwmi -ComputerName $srv -Query "Select * from Win32_PageFileSetting where name '$($targetfilename.replace("\","\\"))'"  
          if(!($checkoutPGFile -and ($checkoutPGFile.Maximumsize -eq $obj.OldMaxSize) -and ($checkoutPGFile.Maximumsize -eq $obj.OldMaxSize))){  
             $obj.Result = "Could not create new page file"  
             $objColl += $obj  
             Continue     
          }  
       }  
         
       if($result.name -eq $targetfilename){  
          $searchString = $obj.OldPageFile.replace("\","\\")  
          $oldPageFileObject = gwmi -ComputerName $srv -Query "Select * from Win32_PageFileSetting where name = '$searchString'"  
          $oldPageFileObject.Delete()  
       }  
         
       if((gwmi -ComputerName $srv -Class Win32_PageFileSetting).name -eq $targetfilename){  
          $obj.Result = "SUCCESS - please reboot the host"  
       }  
       else{  
          $obj.Result = "Could not move page file"  
       }  
    }  
      
    $objColl += $obj  
 }  
   
 $objColl  
   



t

No comments:

Post a Comment