Moving Azure Scheduler Jobs

Due to some poor prior planning, my company has a bunch of different Azure subscriptions used for different things, and billing is kinda tough.  Months ago, we chose to merge those subscriptions into just two:  one for real stuff that we want to administer and maintain, and another for folks to use for PoCs and so on.

After moving the VMs in IaaS to the new subscription, I now get to move the table storage, queues, scheduler jobs, and the other PaaS systems to the new subscription.   I have decided to start with the queues and Scheduler Jobs, which kind of go together, since the jobs are write to queue storage.

Problem is, I can’t find a way to migrate the jobs anywhere.  The cmdlet “Get-AzureSchedulerJob” retrieves all of the settings for the jobs there, but not the messages that the jobs write.  The solution is to figure out how to get this using the REST API.

Using the hard work from this guy, I was able to piece together a script that would download the current job definitions using the REST API.  The following two functions create the HTTPClient that is needed to get into a subscription and get the scheduler jobs from the given job collection.

# this function gets the azure management certificate for the given subscription and returns the full httpClient connection
function get-azuremanagementhttpclient($xMsVersionHeader=’2013-08-01′, $sub) {
$cert = Get-AzureSubscription -SubscriptionName $sub -ExtendedDetails | select -ExpandProperty Certificate
add-type -AssemblyName System.Net.Http
add-type -AssemblyName System.Net.Http.WebRequest
$handler = New-Object System.Net.Http.WebRequestHandler
$handler.ClientCertificates.Add($cert) | out-null
$httpClient = new-object System.Net.Http.HttpClient($handler)
$httpClient.DefaultRequestHeaders.Add(‘x-ms-version’, $xMsVersionHeader)
$mediaType = new-object System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(‘application/xml’)

# this function gets the jobs from the httpClient at the srcURI
function get-jobs($httpClient,$Uri)
$task = $httpClient.GetAsync($Uri)
if($task.Result.IsSuccessStatusCode -eq “True”)
$jobs = $task.Result.Content.ReadAsStringAsync().Result # $srcSched becomes the JSON definition of the source jobs
} else {
$errorInfo = $task.Result.Content.ReadAsStringAsync().Result
$errorStatus = $task.Result.StatusCode
Write-Error “Call to GET $Uri failed with HTTP code $errorStatus and message $errorInfo”
return $jobs

Now that I have the jobs defined in text, I replaced the old storage account and queue names with the ones for my target location.   Finally, I used “ConvertFrom-JSON” to convert the $jobs output to a PowerShell object, and used New-AzureSchedulerStorageQueueJob to create the new jobs.

New-AzureSchedulerStorageQueueJob -Location $destLocation -JobCollectionName $destJobCollectionName -JobName $ -StorageQueueAccount $destStorageAccountName `
-StorageQueueName $destStorageAccountName -SASToken $obj.Action.QueueMessage.sasToken -StorageQueueMessage $obj.Action.QueueMessage.Message `
-Interval $obj.recurrence.interval -Frequency $freq -JobState Enabled

This wasn’t as pretty as I wanted it to be and it took a lot longer than it would have if ”
Get-AzureSchedulerStorageQueueJob” had simply given me the message to begin with.   Oh well….works now.

As a to-do, I have to still manually change the Start Times on the new jobs, as they just go into the system with the current time as the start.   If you want to run something daily or weekly, though, you probably want to configure the times.    You can automate this with the Set-AzureSchedulerStorageQueueJob cmdlet or you can just do it in the portal.