Using PowerShell to Pause CenturyLink Cloud Virtual Servers

Summary

The following script will pause all servers in the specified group for the account alias ‘SXSW’. You can discover your Group ID by querying an existing server (see example towards the end of this blog post). Pausing your Virtual Servers in the CenturyLink Cloud merely saves their state (memory and disk) and can easily be resumed by Starting them (unlike shutting them down or turning them off which does not save the state of their memory). Pausing servers is similar to ‘sleep’ mode supported by most computers. This can be useful for reducing your CLC costs when virtual servers are not being used. This script reads the necessary BearerToken credentials from a text file (bearerToken.txt) that is created by the following script (keep in mind that this token has a life of only 2 weeks and will then need to be regenerated):

Note: All of these script samples are using PowerShell v4 (required)

Example: Save-BearerToken.ps1
if (!($psversiontable.PSVersion.Major -ge 4)) {
 Write-Host -ForegroundColor Red "Requires PowerShell v.4 or greater. Please install the Windows Management Framework 4 or above."
 exit
}

$psCreds = Get-Credential -Message "Use CLC Web Portal Credentials"
$creds = @{
 username = $psCreds.username
 password = $psCreds.GetNetworkCredential().Password
}
$creds = $creds | ConvertTo-Json

Write-Host -ForegroundColor "green" "Getting authentication 'bearerToken'..."
$logonUri = "https://api.ctl.io/v2/authentication/login"
$logonResponse = Invoke-RestMethod -Method Post -Uri $logonUri -Body $creds -ContentType "application/json"

Write-Host -ForegroundColor "green" "Account Summary:"
$logonResponse

Write-Host -ForegroundColor "green" "Bearer Token (2 week TTL):"
$logonResponse.bearerToken
$logonResponse.bearerToken | Set-Content "bearerToken.txt"
Example: Pause-Servers.ps1
$bearerTokenInput = Get-Content ".\bearerToken.txt"
$groupId = "7c3a1aee32241223a1aee32241979a28"
$accountAlias = "SXSW"
$bearerToken = " Bearer " + $bearerTokenInput
$header = @{}
$header["Authorization"] = $bearerToken

# Discover all servers in the specified group
$requestUri = "https://api.ctl.io/v2/groups/$accountAlias/$groupId"
$groupOutput = Invoke-RestMethod -Method GET -Headers $header -Uri $requestUri -ContentType "application/json" -SessionVariable "theSession"

$serverArray = @()
$serverPause = @()
foreach ($item in $groupOutput.links) {
  if ($item.rel -eq "server") {
    $serverName = $item.href.split("/")[($item.href.split("/").count - 1)]
    $serverArray = $serverArray + ($serverName)
  }
}

# Gather server status
$serverList = ""
foreach ($serverName in $serverArray) {
  Write-Host -ForegroundColor Green "Getting server properties for $serverName..."
  $requestUri = "https://api.ctl.io/v2/servers/$accountAlias/$serverName"
  $serverProperties = Invoke-RestMethod -Method GET -Headers $header -Uri $requestUri -ContentType "application/json" -SessionVariable "theSession"
  $powerState = $serverProperties.details.powerState
  Write-Host -ForegroundColor Green "  PowerState: $powerState"
  if ($serverProperties.details.powerState -eq "started") {
    Write-Host -ForegroundColor Yellow "  Pausing $serverName"
    $serverPause = $serverPause + ($serverName)
    $serverList = "$serverList, $serverName"
  }
}

$serverList = $serverList.TrimStart(", ")
if ($serverPause.Count -eq 1) {
  $servers = "[ ""$serverPause"" ]"
} else {
  $servers = $serverPause | ConvertTo-Json
}

Write-Host -ForegroundColor Green "Sending Server pause request for $serverList"
Write-Host "servers: $servers"
Write-Host "serverPause: $serverPause"
$requestUri = "https://api.ctl.io/v2/operations/$accountAlias/servers/pause"
$pauseRequest = Invoke-RestMethod -Method POST -Headers $header -Uri $requestUri -Body $servers -ContentType "application/json" -SessionVariable "theSession"

Write-Host "Request Output: $pauseRequest"

Getting Your Group ID From Your Server

The following sample script will retrieve your Group ID from an existing server. You will need to incorporate your specific server name in this script (we use ‘CA3TESTTEST01’).

Example: List-ServerGroup.ps1
if (!($psversiontable.PSVersion.Major -ge 4)) {
  Write-Host -ForegroundColor Red "Requires PowerShell v.4 or greater. Please install the Windows Management Framework 4 or above."
  exit
}
$dataCenter = "CA3"
$serverName = "CA3TESTTEST01"
$psCreds = Get-Credential -Message "Use CLC Web Portal Credentials"
$creds = @{
 username = $psCreds.username
 password = $psCreds.GetNetworkCredential().Password
}
$creds = $creds | ConvertTo-Json

$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"

Write-Host -ForegroundColor "green" "Getting authentication 'bearerToken'..."
$logonUri = "https://api.ctl.io/v2/authentication/login"
$logonResponse = Invoke-RestMethod -Method Post -Headers $headers -Uri $logonUri -Body $creds -ContentType "application/json" -SessionVariable "theSession"

$bearerToken = " Bearer " + $logonResponse.bearerToken
$accountAlias = $logonResponse.accountAlias

$headers.Add("Authorization",$bearerToken)

Write-Host -ForegroundColor "green" "Getting datacenter capabilities for $dataCenter..."
$RequestUri = "https://api.ctl.io/v2/datacenters/$accountAlias/CA3/deploymentCapabilities"
$deployCapabilities = Invoke-RestMethod -Method GET -Headers $headers -Uri $RequestUri -ContentType "application/json" -SessionVariable "theSession"

Write-Host -ForegroundColor "green" "This datacenter supports the following platform templates:"
$deployCapabilities.templates
Output:

CLC Output 3

Extra: Task Scheduler Rule

The following is a rule that can be imported into Task Scheduler to run the above script on a regular basis.

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2015-06-19T10:56:50.2629119</Date>
<Author>CA3SXSWTEST01\Administrator</Author>
</RegistrationInfo>
<Triggers>
<CalendarTrigger>
<StartBoundary>2015-06-19T19:00:00</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByDay>
<DaysInterval>1</DaysInterval>
</ScheduleByDay>
</CalendarTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>CA3SXSWTEST01\Administrator</UserId>
<LogonType>Password</LogonType>
<RunLevel>LeastPrivilege</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>P3D</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>powershell.exe</Command>
<Arguments>.\Pause-Servers.ps1</Arguments>
<WorkingDirectory>C:\Users\Administrator\Documents\Scripts</WorkingDirectory>
</Exec>
</Actions>
</Task>

Enjoy!