Azure Backup. Wait Only Until Snapshot Is Taken, Not Until It's Transferred to Vault - azure-powershell

I'm writing a PowerShell script for starting MySQL Server process, initiating backups from Azure Recovery Services, then starting MySQL Server process again.
For my purposes Wait-AzRecoveryServicesBackupJob cmdlet is not suitable, as Azure Backup always takes 10 minutes to take a snapshot and takes 3-24 hours to transfer that snapshot to Vault. How can I wait only until snapshot is taken?

You will need to set up your own polling loop, but unfortunately the Get-AzRecoveryServicesBackupJob doesn't have the properties you need. There are two options available to you in Powershell-- the REST API or the CLI.
Once you've gotten the job info, you can find the individual tasks under properties.extendedInfo.tasksList
Implementing this under the CLI would look something like this:
$resourceGroup = "resourceGroup"
$vaultName = "vaultName"
$jobs = az backup job list --resource-group $resourceGroup --vault-name $vaultName --start-date 28-8-2020 | convertfrom-json
$jobName = $jobs[0].name
$jobStatus = az backup job show --name $jobName --resource-group $resourceGroup --vault-name $vaultName
$taskStatus = $jobStatus.properties.extendedInfo.tasksList | Where-Object { $_.taskId -eq "Take Snapshot"}
While ( $taskStatus.status -ne Completed ) {
Write-Host -Object "Waiting for completion..."
Start-Sleep -minutes 1
$jobStatus = az backup job show --name $jobName --resource-group $resourceGroup --vault-name $vaultName
$taskStatus = $jobStatus.properties.extendedInfo.tasksList | Where-Object { $_.taskId -eq "Take Snapshot"}
}
Write-Host -Object "Done!"

Related

Azure Monitoring Database performance

I need to compile the following information: "a scheduled report that shows the DB environment state. From free space to performance, failed jobs and anything else that can cause a DB not to function correctly."
I keep getting referred to the same learn.microsoft links but for some reason i just get progressively more confused.
Can someone please help me with a step by step instruction on how to achieve the above mentioned?
All our DBs are on Azure VMs.
I tried Chat GPT for the disk sizes and it gave me a Power Shell code. <
# Connect to your Azure account
Connect-AzAccount
# Get a list of all virtual machines in your subscription
$vms = Get-AzVM
# Loop through the list of virtual machines
foreach ($vm in $vms) {
# Get the details of each virtual machine
$vmName = $vm.Name
$vmSize = $vm.HardwareProfile.VmSize
# Get a list of all disks attached to the virtual machine
$disks = Get-AzDisk | Where-Object { $_.ManagedBy -eq $vm.Id }
# Loop through the list of disks
foreach ($disk in $disks) {
# Get the details of each disk
$diskName = $disk.Name
$diskSize = $disk.DiskSizeGB
$diskType = $disk.StorageAccountType
# Print the virtual machine, disk, and disk size information
Write-Output "VM Name: $vmName"
Write-Output "VM Size: $vmSize"
Write-Output "Disk Name: $diskName"
Write-Output "Disk Size: $diskSize GB"
Write-Output "Disk Type: $diskType"
Write-Output ""
}
}
\>
I could not get free space information or Database information this way.
Your script is working but you are retrieving information about the VMs, not about the SQL Server that is stored within the VMs.
You need to login into the SQL Server inside the VM and run the query that you want:
# Load the Azure RM module
Import-Module AzureRM
# Login to Azure
Login-AzureRmAccount
# Get a list of all Azure VMs
$vms = Get-AzureRmVM
# Loop through each VM
foreach ($vm in $vms) {
# Get the VM's IP address
$ipAddress = (Get-AzureRmPublicIpAddress -ResourceGroupName $vm.ResourceGroupName -Name ($vm.Name + '-ip')).IpAddress
# Connect to SQL Server on the VM
$connectionString = "Server=$ipAddress;Database=master;User ID=<username>;Password=<password>"
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
$connection.Open()
# Execute the SELECT ##VERSION query
$command = $connection.CreateCommand()
$command.CommandText = "SELECT ##VERSION"
$reader = $command.ExecuteReader()
# Display the result
while ($reader.Read()) {
Write-Output $reader.GetValue(0)
}
# Close the connection
$connection.Close()
}
Note that you will need to replace <username> and <password> with the actual SQL Server login credentials for each VM.
Replace the "SELECT ##VERSION" with the query that investigates:
DB environment state
free space
performance
failed jobs
anything else...

Failed to setup Custom Domain for APIM using PowerShell script

I am trying to setup custom domain for my APIM instance using below script
[CmdletBinding()]
param (
[String]
$ResourceGroupName,
[String]
$Hostname,
[String]
$ApimServiceName,
[string]
$KeyVaultId
)
$ProxyHostnameConf = New-AzApiManagementCustomHostnameConfiguration -Hostname $Hostname -HostnameType "Proxy" -KeyVaultId $KeyVaultId -DefaultSslBinding
$apim = Get-AzApiManagement -ResourceGroupName $ResourceGroupName -Name $ApimServiceName
$apim.ProxyCustomHostnameConfiguration = $ProxyHostnameConf
Set-AzApiManagement -InputObject $apim
But the script is failing with below error
Line |
15 | Set-AzApiManagement -InputObject $apim
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| 'SubnetResourceId' does not match expected pattern
| '^/subscriptions/[^/]*/resourceGroups/[^/]*/providers/Microsoft.(ClassicNetwork|Network)/virtualNetworks/[^/]*/subnets/[^/]*$'.
I am getting this error both in my local machine as well as from the devops Microsoft hosted agent
I was able to fix this using azure cli command mentioned in the below ink
Azure CLI - Bash script to set up API Management custom domain
[CmdletBinding()]
param (
[String]
$ResourceGroupName,
[String]
$HostName,
[String]
$KeyVaultId,
[String]
$ApimServiceName
)
$config ='[{\"hostName\":\"'+$HostName+'\",\"type\":\"Proxy\",\"keyVaultId\":\"'+$KeyVaultId+'\",\"defaultSslBinding\":true,\"negotiateClientCertificate\":false}]'
Write-Host $config
az apim update --resource-group $ResourceGroupName --name $ApimServiceName --set hostnameConfigurations=$config

How can I transfer a subscription in API Management from one user to another in Azure PowerShell?

I want to transfer control on API Management subscriptions from one user to another in case the original user e.g. left the company or changed job roles.
Have email address of source and target user prepared, adapt and use these Azure PowerShell commands:
$ctx = New-AzApiManagementContext -ResourceGroupName {your-resource-group} -ServiceName {your-APIM-service-name}
$from = Get-AzApiManagementUser -Context $ctx -Email "from.user#my-company.com"
$to = Get-AzApiManagementUser -Context $ctx -Email "to.user#my-company.com"
Get-AzApiManagementSubscription -Context $ctx -UserId $from.UserId | ConvertTo-Json | Set-Content ./SubscriptionDump.json
Get-Content .\SubscriptionDump.json | ConvertFrom-Json | %{Set-AzApiManagementSubscription -Context $ctx -SubscriptionId $_.SubscriptionId -UserId $to.UserId}

Setup Alert when SQL Agent Down using Task Scheduler

I am looking something to setup alert notification when SQL agent is down, sometimes when windows patch apply or server get rebooted SQL Agent is not restarting even though we have set up SQL Agent properties Auto Restart SQL Server if it stops unexpectedly
Auto Restart SQL Server Agent if it stops unexpectedly.
I have also tried to setup services on Component service on server to at Recovery tab, First Failure Restart the service and also restarted service rebooted but didn't work.
Is it any way I can get the alert so I can restart service manually when it's Agent is down it it will trigger to restart the job when Agent it's down.
$AgentStatus = (Get-Service -ComputerName <CompName> -Name <SqlServerAgentName> | Where-Object {$_.Status -eq "Stopped"} | Measure-Object).Count
If($AgentStatus -eq 1){
Start-Service -Name SqlServerAgentName
$SMPTPort = <Specify port number>
$From = "email1#domain.com"
$To = "email2#domain.com"
$Subject = "The SQL Server Agent Service in $env:ComputerName has been restarted."
$Body = "The SQL Server Agent Service <SqlServerAgentName> was in a Stopped state and has been restarted."
$SMTPServer = "SMTP SERVER"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, $SMPTPort)
$SMTPClient.EnableSsl = $false
$SMTPClient.Send($From, $To, $Subject, $Body)}
You can try creating a batch file below which checks for service status. This sends an SMTP mail (using powershell) along with restarting service again.
for /F "tokens=3 delims=: " %%H in ('sc query "MyServiceName" ^| findstr " STATE"') do (
if /I "%%H" NEQ "RUNNING" (
powershell -ExecutionPolicy ByPass -Command Send-MailMessage -SmtpServer SMTPSERVER -To someone#domain.com -From noreply#domain.com -Subject Testing -Body Service_Not_Running
net start "MyServiceName"
)
)
Once you have the script ready, create a task scheduler to call the batch file. Run the scheduler every 1 hr or so.

Using Powershell to create user in RabbitMQ via API

I'm trying to create a powershell script that setups user "George" after installing RabbitMQ on a new machine.
I can't figure out why this script doesn't work.
The last step gives me a 404 {"error":"Object Not Found","reason":"\"Not Found\"\n"}
$secpasswd = ConvertTo-SecureString 'guest' -AsPlainText -Force
$credGuest = New-Object System.Management.Automation.PSCredential ('guest', $secpasswd)
$secpasswd2 = ConvertTo-SecureString 'george' -AsPlainText -Force
$credAdmin2 = New-Object System.Management.Automation.PSCredential ('george', $secpasswd2)
$body = #{
'password' = 'george'
'tags' = 'administrator'
} | ConvertTo-Json
$vhosts1 = ''
$vhosts1 = Invoke-RestMethod 'http://localhost:15672/api/users/george' -credential $credGuest -Method Put -ContentType "application/json" -Body $body
write '1:' $vhosts1
$vhosts2 = Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/' -Method get -credential $credAdmin2
write '2:' $vhosts2
$body2 = #{
'username' = 'george'
'vhost' = '/'
'configure' = '.*'
'write' = '.*'
'read' = '.*'
} | ConvertTo-Json
write '3:' $body2
$vhosts3 = Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/george' -credential $credGuest -Method Put -ContentType "application/json" -Body $body2
write '4:' $vhosts3
I've also tried formatting the last step like this:
http://localhost:15672/api/permissions/george
Same 404 error.
I've tried about 20,000 different ways of sending the command in. From matching other examples perfectly to trying some abstract art and voodoo magic. While watching the managment tool for RabbitMQ I can see George is created. And he has an empty vhost. So the first 3 steps work perfectly.
Alright man, you know that I love you, because I'd never heard of RabbitMQ before tonight. In the last hour, I've installed it on my Windows machine, and now have used this awesome guide here to the API and kind of learned about how it works.
So, when I run your same process step by step , I see everything happen as you state:
George gets created:
Since your second step is listing the current permissions of the user running the API call, I next see output of the guest account, which has full perms. Then onto step 3, which builds the target permissions for George.
username : george
write : .*
read : .*
configure : .*
vhost : /
From here, Step 4. When I run this step manually after the previous step...it works! However, if I run this too quickly, if I run the whole script at once, I will get a 404 error. It seems that behind the scenes in RabbitMQ a slight pause is needed for the files to be updated with the new user. When I deleted the user and tried the whole script again too quickly, I got 404's for every step, pretty much.
However, if I add a little Start-Sleep 5 to pause 5 seconds...
The whole process completed. The key place to add a pause is after Step 1 and it seems to need about four or five seconds.
Making it pretty
Now of course, I couldn't stop there, so I decided to add a few more minor pauses to improve output readability and also ensure that each operation completes. I added some purty looking "OK" messages after the step completes, and then added a finishing confirmation of permissions by doing one last API call for the current user.
Here's the completed output
Completed Script
$secpasswd = ConvertTo-SecureString 'guest' -AsPlainText -Force
$credGuest = New-Object System.Management.Automation.PSCredential ('guest', $secpasswd)
$secpasswd2 = ConvertTo-SecureString 'stephen' -AsPlainText -Force
$credAdmin2 = New-Object System.Management.Automation.PSCredential ('stephen', $secpasswd2)
$body = #{
'password' = 'stephen'
'tags' = 'administrator'
} | ConvertTo-Json
Write-host "About to create new user $(($body | ConvertFrom-Json).Password)..." -NoNewline
$vhosts1 = Invoke-RestMethod 'http://localhost:15672/api/users/stephen' -credential $credGuest -Method Put -ContentType "application/json" -Body $body
start-sleep 5
Write-host "OK" -ForegroundColor Green
Start-Sleep -Milliseconds 400
Write-Host '1: Results:' $vhosts1
$body2 = #{
'username' = 'stephen'
'vhost' = '/'
'configure' = '.*'
'write' = '.*'
'read' = '.*'
} | ConvertTo-Json
Write-Output "Desired perms for new user $(($body | ConvertFrom-Json).Password)" $body2
Write-host "Setting perms for new user..." -NoNewline
$vhosts3 = Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/stephen' -credential $credGuest -Method Put -ContentType "application/json" -Body $body2
Start-sleep 5
Write-host "OK" -ForegroundColor Green
Start-Sleep -Milliseconds 400
write '4:' $vhosts3
'Retrieiving perms for new user to confirm...'
Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/stephen' -Method get -credential $credAdmin2
Now I just hope I'll get a chance to use RabbitMQ ever again...
finally stumpled upon a powershell library someone else wrote for interacting with the RabbitMQ api.
https://github.com/mariuszwojcik/RabbitMQTools/blob/master/en-US/about_UnEsapingDotsAndSlashes.help.txt
I found out that certain versions of powershell replace %2f with the / before sending it to rabbit. If you use this guys functions found here:
https://github.com/mariuszwojcik/RabbitMQTools
Everything runs beautifully. Really great library he put together.
I'm late to this question. I love Powershell too, but I used a .bat file to run the native RabbitMQ commands as shown below. I needed to add a user, a vhost, and hook those two up. I wanted a script so any new developer could run it.
cd /D c:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.14\sbin
echo cd completed
call rabbitmqctl add_user bts mypass
call rabbitmqctl set_user_tags bts administrator
call rabbitmqctl add_vhost base
call rabbitmqctl set_permissions -p base bts ".*" ".*" ".*"
Echo ----List Command to confirm results --------
call rabbitmqctl list_vhosts
call rabbitmqctl list_user_permissions bts
I suppose you could call these from Powershell too. I guess downside of this is that you have to be on the machine running RabbitMQ.