Thursday, 22 September 2016

Veeam Endpoint USB Seeding Method

Veeam Endpoint USB Seeding Method  

Pre-Checks  
  • If there is a Veeam config on the Endpoint client, clear it with the following registry edit  

1. Stop the Veeam Endpoint Backup service.  
2. Run regedit.exe and locate the "HKEY_LOCAL_MACHINE\SOFTWARE\Veeam\Veeam Endpoint Backup" key. Create or modify the following value under this key:  
Name = Recreatedatabase   
Type = DWORD   
Value = 1   
3. Start Veeam Endpoint Backup service  
4. Check Veeam Endpoint to see that DB has been recreated. Once the DB is recreated, the registry entry should be reset back to 0  

  • If there is a backup on USB delete it completely  
  • Remove ALL config for that server from Veeam B&R server  
  • You must have created an Endpoint backup on the repository server in order to create the folder structure. 
   
Seed Method - All steps may not be necessary but this is what I did  

1. Create USB local backup on the Veeam Endpoint client 
2. Run the backup  
3. Immediately run an incremental  
4. Run another incremental for good measure – this specific step may not be required. 
5. Copy files into EXISTING "X:\Backup\DOMAIN_UserAccount\" folder (Replace X:\Backups with your endpoint repository location) 
6. The full path should then be "X:\Backup\DOMAIN_UserAccount\Backup Job for SERVER\" (Replace X:\Backups with your endpoint repository location) 
7. in Veeam B&R, rescan the repository and check you can see imported restore points  
8. Go back to Endpoint client machine and open Veeam endpoint  
9. Click on "Configure Job" 
10. Reconfigure the backup job and select Veeam B&R Repository for the destination 
11. Make sure to user the same account as the backup repository folder above "DOMAIN_UserAccount" 
12. Make sure to select the same repository server that you copied the backup to. 
13. Leave everything else exactly as it was and complete the wizard.  
14. The next backup should be incremental. 
  

Store a credential to a file in Powershell

Store a credential to a file in Powershell

In Powershell you can use SecureString to store a password for a user account. Once saved, the encrypted password can be decrypted by the same Windows user for later use.

This is handy if you need to supply a PSCredential object to a cmdlet in a scheduled script.

To store the credential, enter the username and password into a PSCredential object while logged into the user account which will be used to execute the script.

$credential = Get-Credential

Once you have the object, convert the password from a secure string and output to a file

$credential.Password | ConvertFrom-SecureString | Out-File .\credentialpw.bin -enc ASCII

Once the password is in the file, you can re-import the password to a credential object as follows.

$userName = "myuser"
$secPassword = Get-Content .\credentialpw.bin | ConvertTo-SecureString
$newCredential = New-Object System.Management.Automation.PsCredential($userName,$secPassword)

The $newCredential object can now be used to pass to a cmdlet.

If you try to use the password file as a different Windows user, the password file cannot be converted to a SecureString:


Keep in mind that the password as a securestring object can be reversed back to plain text, so this should not be used to keep the password safe from the user account it is stored by.

$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secPassword)
$PlainText = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

The above commands will allow you to recover the plain text password - but only as the user that originally saved the credential.


Tuesday, 20 September 2016

Convert Classic Azure VM to Azure Resource Manager with Powershell

Problem


I have a classic VM which I want to move into an Azure Resource Manager machine. The only way this is currently possible is to recreate a new machine using an existing VHD. Unfortunately this doesn’t work if you just try to create an RM machine using the existing classic storage VHD.

You can get the VHD location for the powershell code from Azure Portal, click on the stroage account and in through blobs, vhds etc.

Powershell Code

Login-AzureRMAccount

#New VM Information
$rgName="ServersUS"
$netrgName="ServersUS"
$vnetName="NetworkUS"
$subnetIndex=0

$locName="Central US"
$vmName="newvm"
$vmSize="Basic_A2"

#Old VM Information
$osDiskUri="https://classicalstorageaccount.blob.core.windows.net/vhds/classic.vhd"
$diskName=$osDiskUri.Split("/")[-1] #This should just be the filename of the vhd

$vnet=Get-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $netrgname
$nicName="$($vmName)-nic"
$nic=New-AzureRmNetworkInterface -Name $nicName -ResourceGroupName $netrgName `
    -Location $locName -SubnetId $vnet.Subnets[$subnetIndex].Id
$vm=New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize
$vm=Add-AzureRmVMNetworkInterface -VM $vm -Id $nic.Id
$osDiskCaching = 'ReadWrite'
$vm=Set-AzureRmVMOSDisk -VM $vm -VhdUri $osDiskUri -name $DiskName `
    -CreateOption attach -Windows -Caching $osDiskCaching

New-AzureRmVM -ResourceGroupName $rgName -Location $locName -VM $vm

Error while using classic storage

WARNING: Error occurred when getting storage account, classicalstorageaccount, for boot diagnostics: Sequence contains no matching element
WARNING: Since the VM is created using premium storage, existing standard storage account, rmstorageaccount, is used for boot diagnostics.
New-AzureRmVM : Long running operation failed with status 'Failed'.
StartTime: 20/09/2016 14:48:55
EndTime: 20/09/2016 14:48:56
OperationID: f49d21d3-b3e5-44c0-85d7-72bba687b371
Status: Failed
ErrorCode: AcquireDiskLeaseFailed
ErrorMessage: Failed to acquire lease while creating disk 'classic.vhd' using blob with URI https://classicalstorageaccount.blob.core.windows.net/vhds/classic.vhd. Blob is already in use.
At line:29 char:1
+ New-AzureRmVM -ResourceGroupName $rgName -Location $locName -VM $vm
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (:) [New-AzureRmVM], ComputeCloudExcep
   tion
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.Compute.NewAzureVMCommand

Resolution

Copy the vhd to a new storage account using the Azure Storage Explorer or Powershell. You will need to change the access policy on the vhd to Blob or Container in order to copy using the Storage Explorer. There is a powershell method (linked above) which allows you to copy the file using authentication.


Changing the access policy for the vhd file in Azure Portal

File copy took about 20 mins going from central US classic to Central US Resource Manager. Once completed the powershell code above can be used to create a new virtual machine with an existing VHD

Friday, 16 September 2016

Backup or Migrate VMs to Azure IaaS with Veeam Direct Restore for Microsoft Azure

Backup or Migrate VMs to Azure IaaS with Veeam Direct Restore for Microsoft Azure

Getting backups to Azure

The Veeam Direct Restore for Microsoft Azure virtual machine is available in the Azure Marketplace and is a handy tool for restoring VMs into Azure IaaS. This method works for both VMware and Hyper-V virtual machine backups. 

Getting your .vbk backups into Azure is the first challenge. I have found the simplest method for regular backups is to use Azure Files / MAFS and mapped drives in Windows.

If you just want to do a one-off backup/restore into Azure you can simply mount and Azure MAFS file system on both your on-premise server and your Veeam DR server using the regular Azure Files method:

net use Q: \\storageaccountname.file.core.windows.net /u: storageaccountname <KEY>

The next method is to use the MAFS share as a repository in your Veeam B&R setup. To do this simply set up the repository as a CIFS repository and use the storage account name as the username and the key as the password.



Remember this method will be more read/write intensive than simply copying the files you need onto the share as it will need to do backup rollups and other B&R repository functions on the file share. 

Performance of this method isn't bad and on our 200 Mbit internet connection we were reaching 17 MB/sec sustained throughput when we seeded the backup share.

Over the next few days I will be testing the IO impact of running this as a repository. There are also speed limits and quota limits on each file share and storage account which will need to be taken into account if this needs to be used at scale.

Restoring your backups as a Classic Azure VM

The first step to restoring your VM as a classic Azure VM / Cloud Service is to deploy the  Veeam Direct Restore for Microsoft Azure virtual machine from the Azure Marketplace.


Once your machine is deployed and you have connected via RDP you will be presented with the Veeam Direct Restore UI.



Minimise the UI and map your MAFS drive using the regular net use command

Back in the Veeam UI, click the configuration button and complete the wizard by logging into your azure account, downloading the credential file and pointing to it in the wizard.

Once you have completed the configuration, you should then be able to perform a restore using the restore button in the UI.

When you select the file from the MAFS share, the wizard will ask for credentials, enter the storage account name as the username and the access key as the password. You should then be presented with a list of VMs in the backup, ready to restore.



Select your VM, click restore and the backup will be imported. You will now be shown the Restore to Azure wizard. You will need a pre-created classic storage account in the region you want to restore your VM to.


Once the restore is completed, the VM is automatically started in Azure.


Thoughts

  • It's not fast. If you're used to dedicated backup hardware and fast disk based restores, you could be in for a shock. The restore performance I got from this was around 7 MB/sec or 25 GB/Hr. This could be because I was running the software on a D1_v2 Azure VM which has a NIC limited to 100 Mbps. I was also copying from North Europe to Central US DC since I can only make classic VMs in certain regions. I'll do some benchmarks on a larger machine at a later stage.
  • It doesn't scale well. Azure file shares are limited to 5 TB per share. You could have multiple shares but that could quickly get difficult to manage.
  • Only parts of this can be automated. The restore process is quite hands on so I wouldn't want to rely on this as my only DR solution.
  • If you're an EA customer with Microsoft it may be best to investigate the StorSimple cloud appliance solution which should scale much better and provide much better performance.


















Sysprep already exists when trying to deploy machines with New-QVWComputer

Sysprep already exists when trying to deploy machines with New-QVWComputer

New-QVWComputer : A SysPrep customization with the name [SERVERNAME] already exists.
At C:\Scripts\MyScript.ps1:78 char:12
+ $NewVMs += New-QVWComputer -ComputerGroup $InactiveGroup -Farm $Farms `
+            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-QVWComputer], ValidationRuleException`1
    + FullyQualifiedErrorId : Quest.vWorkspace.BusinessLayer.Infrastructure.Actions.ValidationRuleException`1[[Quest.vWorkspace.BusinessLayer.Infrastructure.SysPrep.Sys
   PrepRecord, Quest.vWorkspace.BusinessLayer, Version=8.6.308.2000, Culture=neutral, PublicKeyToken=76d0ba9347d138d6]],Quest.vWorkspace.PowerShell.Infrastructure.NewQ 
  vwComputerCommand

●      Run SQL Server Management Studio on your database server
●      Find the vWorkspace database
●      Find the dbo.DmSyspreps table
●      Right Click on the table > Edit Top 200 Rows
●      Right Click in the right hand pane > Pane > SQL
●      Add “WHERE        (SysprepName = 'SERVERNAME')” to the end of the query
●      Right click > Execute SQL


Change the sysprep name of the machine which wasn’t fully deleted. I cancelled the provisioning task which meant it wasn’t cleaned up from the DB. It should be safe to delete the line, but I wanted to make sure all was OK when doing it.


SQL datatype conversion error when trying to deploy machines with New-QVWComputer

SQL datatype conversion error when trying to deploy machines with New-QVWComputer

New-QVWComputer : The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
At C:\MyScript.ps1:78 char:12
+ $NewVMs += New-QVWComputer -ComputerGroup $InactiveGroup -Farm $Farms `
+            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-QVWComputer], SqlException
    + FullyQualifiedErrorId : System.Data.SqlClient.SqlException,Quest.vWorkspace.PowerShell.Infrastructure.NewQvwComputerCommand

The command works when using a different template. Template dates have been screwy in vWorkspace when deploying using the powershell commandlets and I think this is the same root cause.

I’m assuming that the error is because the SQL back end is trying to parse a UK date string as a US datetime object and failing to do so correctly.

Hopefully changing the modified date will allow the SQL back end to parse the date (incorrectly) and will allow the deployment to work. I intend to change to a date which will parse as a US format date ie. Not greater than day 12 of any month.

This Dell link hints at a similar problem https://support.software.dell.com/vworkspace/kb/142232 and suggests a workaround on the broker machines.

$file = get-item TEMPLATENAME.vhdx
$file.LastWriteTime = $newDate.AddDays(-5) #Works out as 10/09/2016
$file.LastWriteTime

Once the date is updated, import the template



 After updating the template the New-QVWComputer command will now deploy from the template.



Sunday, 24 April 2016

Implementing Android KeyChain to utilise stored user certificates.

Implementing Android KeyChain to utilise stored user certificates.

A friend of mine recently asked me to set up a proof of concept application in order to connect to an HTTPS web service and provide a user certificate from Android. After some searching, I found I could quite easily provide a user certificate from a PFX file using the Android KeyStore class. The stumbling block here was that I needed to use a certificate that had been pre-installed on the device.

The KeyChain class allows you to do just this. My initial implementation took advantage of the AOSP SSLUtils class from the ICS email application.

Essentially you need to do 3 things:

Ask the user to select a certificate

 KeyChain.choosePrivateKeyAlias(this, this,  
     new String[]{}, null, null, -1, null);  


Display the integrated Android certificate picker dialog.

Implement the KeyChainAliasCallback in your activity and override the alias method. inside this method you will be given an alias to the certificate that the user selected. It's possible to save this alias so that you don't need to ask the user every time. The SSLUtils.KeyChainKeyManager class is in the above SSLUtils class from the ICS email application.

This must be done on a background thread.

 KeyManager keyManager = SSLUtils.KeyChainKeyManager.    
   fromAlias(getApplicationContext(), alias);  
 mSslContext = SSLContext.getInstance("TLS");   
 mSslContext.init(new KeyManager[]{keyManager}, null, null);   


Once you have the certificate keys in the SSLContext object, you can then pass this to an HTTPS connection which should then use the user selected client certificate.

 URL requestedUrl = new URL(url);  
 urlConnection = (HttpURLConnection) requestedUrl.openConnection();  
 if(urlConnection instanceof HttpsURLConnection) {  
   ((HttpsURLConnection)urlConnection)  
       .setSSLSocketFactory(mSslContext.getSocketFactory());  
 }  
 urlConnection.setRequestMethod("GET");  
 urlConnection.setConnectTimeout(1500);  
 urlConnection.setReadTimeout(1500);  
 int lastResponseCode = urlConnection.getResponseCode();  
 result = "HTTP:" + lastResponseCode + ", "  
     + streamToString(urlConnection.getInputStream());  

Again the above needs to be done on a different thread to the UI. I'll upload the whole code when I've had chance to clean it up and just implement the KeyChain part.

For completeness, here is my streamToString function


   private String streamToString(InputStream is) throws IOException {  
     StringBuilder sb = new StringBuilder();  
     BufferedReader rd = new BufferedReader(new InputStreamReader(is));  
     String line;  
     while ((line = rd.readLine()) != null) {  
       sb.append(line);  
     }  
     return sb.toString();  
   }  


Nutanix CE 2.0 on ESXi AOS Upgrade Hangs

AOS Upgrade on ESXi from 6.5.2 to 6.5.3.6 hangs. Issue I have tried to upgrade my Nutanix CE 2.0 based on ESXi to a newer AOS version for ...