Saturday, December 15, 2018

BACKUP SQL AZURE 2016 DATABASE TO BLOB STORAGE USING SAS



Starting SQL  Server 2016 we can take backups of SQL Server databases on Azure blob storage. The functionality was missing in SQL Server 2014 and it was only possible to take SQL Backups on Hot storages in Azure storage, which was more costly.

You would require Shared access signatures(SAS) to access Azure blob storage from your SQL script.
Below are the steps that needs to be performed to create a SAS token and take the backup.



  1. Powershell script given below gives you a SQL command as an output. We need to change the parameter variables at the start e.g. Subscription name, container. Remember to change the policy name, if you are executing the script in the same storage account twice. This token by default is valid for next 10 years(not practical 😆). Change the duration in script if needed.
<#  
This script uses the Azure Resource model and creates a new ARM storage account. 
Modify this script to use an existing ARM or classic storage account  
using the instructions in comments within this script 
#> 
# Define global variables for the script 
$prefixName = ''  # used as the prefix for the name for various objects 
$subscriptionName='Microsoft Azure'   # the name  of subscription name you will use 
$locationName = 'East US'  # the data center region you will use 
$storageAccountName= $prefixName + 'dbablobspecific' # the storage account name you will create or use 
$containerName= $prefixName + 'container1'  # the storage container name to which you will attach the SAS policy with its SAS token 
$policyName = $prefixName + 'backupSAS' # the name of the SAS policy 

<#  
Using Azure Resource Manager deployment model 
Comment out this entire section and use the classic storage account name to use an existing classic storage account 
#> 

# Set a variable for the name of the resource group you will create or use 
$resourceGroupName=$prefixName + 'rg'  

# adds an authenticated Azure account for use in the session  
Login-AzureRmAccount   

# set the tenant, subscription and environment for use in the rest of  
Set-AzureRmContext -SubscriptionName $subscriptionName  

# create a new resource group - comment out this line to use an existing resource group 
#New-AzureRmResourceGroup -Name $resourceGroupName -Location $locationName  
Get-AzureRmResourceGroup -Name 'dbagroup' -Location 'East US'

# Create a new ARM storage account - comment out this line to use an existing ARM storage account 
#New-AzureRmStorageAccount -Name $storageAccountName -ResourceGroupName $resourceGroupName -Type Standard_RAGRS -Location $locationName  
Get-AzureRmStorageAccount  -Name $storageAccountName

# Get the access keys for the ARM storage account 
$accountKeys = Get-AzureRmStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName 

# Create a new storage account context using an ARM storage account 
$storageContext = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $accountKeys[0].Value

<# 
Using the Classic deployment model 
Use the following four lines to use an existing classic storage account 
#> 
#Classic storage account name 
#Add-AzureAccount 
#Select-AzureSubscription -SubscriptionName $subscriptionName #provide an existing classic storage account 
#$accountKeys = Get-AzureStorageKey -StorageAccountName $storageAccountName 
#$storageContext = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $accountKeys.Primary 

# The remainder of this script works with either the ARM or classic sections of code above 

# Creates a new container in blob storage 
$container = New-AzureStorageContainer -Context $storageContext -Name $containerName 


$cbc = $container.CloudBlobContainer 

# Sets up a Stored Access Policy and a Shared Access Signature for the new container 
$permissions = $cbc.GetPermissions(); 
$policyName = $policyName 
$policy = new-object 'Microsoft.WindowsAzure.Storage.Blob.SharedAccessBlobPolicy' 
$policy.SharedAccessStartTime = $(Get-Date).ToUniversalTime().AddMinutes(-5) 
$policy.SharedAccessExpiryTime = $(Get-Date).ToUniversalTime().AddYears(10) 
$policy.Permissions = "Read,Write,List,Delete" 
$permissions.SharedAccessPolicies.Add($policyName, $policy) 
$cbc.SetPermissions($permissions); 

# Gets the Shared Access Signature for the policy 
$policy = new-object 'Microsoft.WindowsAzure.Storage.Blob.SharedAccessBlobPolicy' 
$sas = $cbc.GetSharedAccessSignature($policy, $policyName) 
Write-Host 'Shared Access Signature= '$($sas.Substring(1))'' 

# Outputs the Transact SQL to the clipboard and to the screen to create the credential using the Shared Access Signature 
Write-Host 'Credential T-SQL' 
$tSql = "CREATE CREDENTIAL [{0}] WITH IDENTITY='Shared Access Signature', SECRET='{1}'" -f $cbc.Uri,$sas.Substring(1)  
$tSql | clip 
Write-Host $tSql 


     2. Upon execution of above script you will receive a TSQL command as an output –


This gives you the shared access signature and a T-SQL  statement which you can execute to create a credential on your SQL server 2016 instance. Copy this statement in a new query window and execute to create the credential –


 Once credential is created, you can start your SQL backups to Azure blob storage using it.



Now go back to your storage account container and verify that backup is completed successfully.


 Hope you find the post helpful.

Thursday, December 6, 2018

Migration path from on premise VM to Azure IAS VM

Hello Everyone,

In today's post we are going to elaborate on the ways, we can migrate the On-premise servers running SQL server to Azure VMs. The path basically depends on following few factors


  1. The on-premise SQL version you are using.
  2. The destination SQL version your application is targeting for.
  3. The amount of downtime you can have during migration.
  4. The size of the databases you have on-premises to migrate to Azure.
  5. The license type you are going to use after migration.
  6. The current HA/DR solution in place for On-premise databases.
Below excel file should help you figure out the best path for your migration. Let me know in comments if it is helpful or you would like some additions.

https://drive.google.com/open?id=14YKAlY98Az2-SsNiQ0zx4EfChET6Vld89LxaXulNE8s

Thanks and keep exploring 😊

Monday, November 12, 2018

Azure Managed Instances Procuring & Connecting




Azure Managed Instances
Procuring & Connecting





Below steps help you creating a new Azure Managed Instance from Azure portal and shows how to connect to it.

  1. Create a new managed instance in Azure portal. Click on “Create a resource” and search for “Azure SQL Managed Instance”. In the result that appears. Click Create.





    2. Provide Instance Name, Login information, resource group, location and  Virtual Network to host managed instance. We are using below settings.

Resource Group - NaviDemoDBAInstance
Instance Name - navidemodbainstance
User Name - NaviSQLAdmin
Password - "Your Password"

Once all information is provided click create.

Create Managed Instance


           3. You will get a warning while creating a new VNet that First instance in the VNet could take upto 6 hours to complete.



       4.  Once the creation is in progress, you can click on the notification bell icon and choose to view the progress of the operation. Ours took 3 Hours and 37 Mins to complete.




               5. Create a new Virtual network for the VM you will connect your instance through. We are creating it in the same region “East US”.





               6. Create a new VM in the same resource group. Use the VNet “MyJumpVMVNet” for this Virtual machine. We opened the RDP ports to this machine.



Machine Name – MgdInstJumpVM
User Name – NaviSQLAdmin
Password - "Your password"

Below is the configurations of the VM created.



             7. Once done create a peering between the VM Vnet and Managed Instance VNet. Below are the 2 networks we will peer.


             8. Go to “Peerings” section of one of the network and click “Add”.


         9. On the blade that opens up, specify a name for peering and select the other Virtual network. In our case it is the Managed instance network selected.


               10. Once created you should have the peering visible on your VM Network


               11. Now go to the Managed instance Virtual network and create peering towards your VM Virtual network as we did before in other direction.




               12. Now Connect to your VM created earlier. You can download the RDP file from the portal for connection. Use the credentials provided while creation of VM.



          13. Once logged in Open Internet explorer and download the latest version of SQL Server Management Studio. We will use this for testing connectivity between VM and our Managed Instance.


                14. Once downloaded Start the setup and install it on your Azure VM


                15. Now go to you managed instance on azure portal and copy the complete Instance name. Instance name should be like “MyInstancename.3ed349523e65.database.windows.net”



                16. Go to your VM, Open SQL Server Management Studio and paste the server name and login information as below


                17. You should be able to connect to your instance now. By default the version you will receive would be SQL Server 2014 RTM (12.0.2000.8).


Hope you find the steps helpful and easy to follow.

Migrate On premise physical machines to Azure using Azure Site Recovery

Hello Everyone,

Below video shows the detailed step by step method to migrate an On-premise Physical server to Azure using Azure site recovery.

I have used 2 physical servers: 1 as Configuration server and other one as the Source server for migration. You will see detailed steps to configure everything from start till end. It also shows a test fail over to Azure and how to connect to the migrated server.

Due to some technical difficulties, the video doesn't has audio. But I hope you will find this useful as it is a complete step by step from start till end.



Wednesday, April 25, 2018

Reporting Service Key Backup Script

A lot of us have gone through the scenario where a Reporting Service account gets changed/deleted and then we don't have a way to get our reports working as all the encrypted content is lost.

Our organization needed an automated way to backup the Reporting Service key. Here is a simple script which will create a job on your SQL Instance. This job will run once a day taking RS Key backup with a random password. It will put the Key file and the Random password in the folder specified in the script and retain these for last 7 days. Go ahead and give it a try.

Please replace the value for variables $KeyPath(Location where key backup will be placed), $PwdFilePath(Location where password file will be placed) and $Daysback (Number of days to retain the key in the destination folder. Default is 7).


--******Start of Script*******
USE [msdb]
GO

/****** Object:  Job [Navi_SSRS_Key_Backup]    Script Date: 25/04/2018 08:23:09 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [[Uncategorized (Local)]]    Script Date: 25/04/2018 08:23:09 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'SSRS_Key_Backup', 
@enabled=1, 
@notify_level_eventlog=0, 
@notify_level_email=0, 
@notify_level_netsend=0, 
@notify_level_page=0, 
@delete_level=0, 
@description=N'No description available.', 
@category_name=N'[Uncategorized (Local)]', 
@owner_login_name=N'sa', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [SSRS Key Backup]    Script Date: 25/04/2018 08:23:09 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'SSRS Key Backup', 
@step_id=1, 
@cmdexec_success_code=0, 
@on_success_action=1, 
@on_success_step_id=0, 
@on_fail_action=2, 
@on_fail_step_id=0, 
@retry_attempts=0, 
@retry_interval=0, 
@os_run_priority=0, @subsystem=N'PowerShell', 
@command=N'Function GET-Temppassword() {

Param(

[int]$length=10,

[string[]]$sourcedata

)



For ($loop=1; $loop –le $length; $loop++) {

            $TempPassword+=($sourcedata | GET-RANDOM)

            }

return $TempPassword

}

$ascii=$NULL
For ($a=33;$a –le 126;$a++) {$ascii+=,[char][byte]$a }
$password = GET-Temppassword –length 19 –sourcedata $ascii

$postfix = Get-Date -format "yyyyMMddhhmm"
$KeyPath = ''C:\MSSQL11.MSSQLSERVER\MSSQL\SSRSEncBackup\''
$PwdFilePath = ''C:\MSSQL11.MSSQLSERVER\MSSQL\SSRSEncBackup\KeyPwd''+$postfix+''.txt''
$KeyFileName = ''SSRSDBkey'' + $postfix + ''.snk''
$KeyFile = $KeyPath + $KeyFileName
echo y | rskeymgmt -e -f $KeyFile -p $password

$file = $PwdFilePath + $FileName

(get-date).ToString() + " | " + $password | Out-File -FilePath $PwdFilePath

$Daysback = “-7”
$CurrentDate = Get-Date
$DatetoDelete = $CurrentDate.AddDays($Daysback)
Get-ChildItem $KeyPath -Recurse | Where-Object { $_.LastWriteTime -lt $DatetoDelete } | Remove-Item', 
@database_name=N'master', 
@flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'SSRSKeyBackup', 
@enabled=1, 
@freq_type=4, 
@freq_interval=1, 
@freq_subday_type=1, 
@freq_subday_interval=0, 
@freq_relative_interval=0, 
@freq_recurrence_factor=0, 
@active_start_date=20171118, 
@active_end_date=99991231, 
@active_start_time=233000, 
@active_end_time=235959, 
@schedule_uid=N'4fb8bbee-b128-4c0e-9005-2e966b872544'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:

GO
--******End of Script*******

Hope it helps.