When trying to create a Virtual Machine from PS it's ending up with the error (this it of Zscaler log collector in Azure): Cannot attach an existing OS disk if the VM is created from a platform, user or a shared galley image Azure
#Test if the azure powershell modules are present on the system $scmd="Connect-AzAccount" $cmdout=Get-Command $scmd -eA SilentlyContinue -EV $serr -OV $sout if(!$cmdout.CommandType) { echo "Required powershell modules are missing. Please install the azure modules and retry" exit }
#Sign in for this session Connect-AzAccount
#Fetch the config file to be loaded if( $args[0] -ne $null ){ $filename=$args[0] } else { $filename="./config.txt" }
$SubSelect = 'n' Set-Item Env:\SuppressAzurePowerShellBreakingChangeWarnings "true" Do { $subs=Get-AzSubscription
echo "Listing available subscriptions in your account" $subid=0 $ProvisionSub=99999 foreach ($sub in $subs) { echo "Subscription $subid :" echo $sub $subid++ }
if($subid -ge 1) { $ProvisionSub=Read-Host -Prompt "Select one of the above for provisioning" } else { $ProvisionSub=0 }
echo "Selected subscription for provisioning :" echo $subs[$ProvisionSub] $SubSelect=Read-Host -Prompt "Enter
"y
" to continue with this subscription or"n
" to choose again" While($SubSelect -eq 'n' -or $SubSelect -eq 'N')if($SubSelect -ne 'y' -and $SubSelect -ne 'Y') { echo "You did not choose a subscription to deploy in, script will exit now" exit }
$subscription=$subs[$ProvisionSub] echo "Script will continue to provision in the selected subscription $subscription " Set-AzContext -SubscriptionId $subscription.Id echo "Azure Subscription for current session set to the following" Get-AzContext $select=Read-Host -Prompt "Do you wish to continue(y/n):" if($select -ne 'y' -or $select -ne 'Y')
{ echo "Script terminating per user input" exit } echo "Provisioning will continue with the selected subscription"if ( -not (Test-Path $filename)) { echo "Config file not found at $filename" exit } else { echo "Found the configuration file, populating deployment variables from $filename" }
#Sanity run, set this to n when running actual creation $sanityrun='n'
#Initialize config entries from the configuration file provided $name='' $rgname='' $niccount=1 $rgcreate="n" $storename='' $mgmtsubnetname='' $svcsubnetname='' $vnetname='' $vnetprefix='' $mgmtsnetprefix='' $svcsubnetprefix='' $vmsize='' $location='' $osimage='' $dstStorageURI='' $datadisk="Copy" $datadisksize=0 $datadisksrcURI='' $osdisksrcURI='' $dataimageURI='' $dstContainer='' $vnetrgname='' $avsetname='' $avcheck="No"
#Parse the config file provided and load the values
foreach ($line in Get-Content $filename) { if($line -match "^#.*") { #Commented continue } if( [string]::IsNullOrWhitespace($line)) { #Empty line continue } $entries=$line.split("=",2,[StringSplitOptions]'RemoveEmptyEntries') #$entries=$line.split("=") $e1=$entries[0] $e2=$entries[1] Write-Host $e1 $e2 -Separator "," $key=$e1.Trim() $value=$e2.Trim() #echo "Got entries" $entries[0] "->" $entries[1] if($key -eq "name") { $name=$value continue } if($key -eq "avset") { $avsetname=$value continue } if($key -eq "rgname") { $rgname=$value continue } if($key -eq "vnetrg") { $vnetrgname=$value continue } if($key -eq "createrg") { $rgcreate=$value continue } if($key -eq "storename") { $storename=$value continue } if($key -eq "createstorage") { $storecreate=$value continue } if($key -eq "mgmtsubnetname") { $mgmtsubnetname=$value continue } if($key -eq "svcsubnetname") { $svcsubnetname=$value continue } if($key -eq "vnetname") { $vnetname=$value continue
if($key -eq "niccount") { $niccount=$value continue } if($key -eq "vnetprefix") { $vnetprefix=$value continue } if($key -eq "mgmtsubnetprefix") { $mgmtsnetprefix=$value continue } if($key -eq "svcsubnetprefix") { $svcsubnetprefix=$value continue } if($key -eq "vmsize") { $vmsize=$value continue } if($key -eq "location") { $location=$value continue } if($key -eq "dstStorageURI") { $dstStorageURI=$value continue } if($key -eq "srcOsURI") { $osimage=$value continue
if($key -eq "osuri") { $osdisksrcURI=$value continue
if($key -eq "sastok") { $sastok=$value continue } if($key -eq "attach") { $attachdisk=$value continue } if($key -eq "dstContainer") { $dstContainer=$value continue }
}
echo "Name=$name Rgname=$rgname Location=$location" if($vnetrgname -eq '') { $vnetrgname=$rgname }
$loclist=Get-AzLocation $loccheck=0
foreach($loc in $loclist.Location){ if($loc -like $location){ $loccheck=1 } }
if($loccheck -eq 1){ Write-Host "The virtual instance will be deployed in $location" else {
Write-Error -Message "The location provided in configuration file :- $location is not a valid input. Please correct the same and rerun the script" exit }
#Fetch resource group and storage account configured in the conf file $rg=Get-AzResourceGroup -ResourceGroupName $rgname -ev notPresent -ea 0 $rgcreatechoice='n' $storecreatechoice='n'
#If resource group does not exist, provision it before proceeding if($rg.ProvisioningState -ne "Succeeded") { echo "The resource group $rgname does not exist, do you wish to create it in $location(y/n):" $rgcreatechoice=Read-Host if($rgcreatechoice -eq 'y' -or $rgcreatechoice -eq 'Y') { echo "Creating resourcegroup $rgname in $location" $rg=New-AzResourceGroup -Name $rgname -Location $location if($rg.ProvisioningState -ne "Succeeded") { echo "Error creating resource group. Script will exit now" exit } echo "Created resource group. Continuing to provision the storage account" $storecreatechoice='y' }else { echo "Resource group specified does not exist in the selected subscription. Exiting" exit } }
if($rgcreatechoice -eq 'n') { $store=Get-AzStorageAccount -ResourceGroupName $rgname -Name $storename -ev stnotPresent -ea 0 if($store.ProvisioningState -ne "Succeeded"){ echo "The Storage account provided
"$storename
" doesn't exist in $rgname" echo "Do you wish to provision the storage account now(y/n):" $storecreatechoice=Read-Host if($storecreatechoice -ne 'y' -or $storecreatechoice -ne 'Y'){ echo "VM creation cannot continue without storage account. Exiting." if($rgcreatechoice -eq 'y' -or $rgcreatechoice -eq 'Y'){ echo "Resource group $rgname was provisioned in $location while script executed" echo "Please delete it if no longer in use" } exit } } } $storetype='Standard_LRS' if($storecreatechoice -eq 'y' -or $storecreatechoice -eq 'Y'){ echo "Preparing to provision storage account $storename in resource group $rgname" echo "Do you need geo redundant store or locally reduntant store" echo "Enter 1 for geo reduntant(Standard_GRS) or 2 for locally reduntant(Standard_LRS), if you need" echo "other options, enter"n
" to exit now and provision the storage account manually " echo "Enter your choice: " $storetypechoice=Read-Host if($storetypechoice -eq 1) { echo "Store type set to Standard_GRS" $storetype="Standard_GRS" } if($storetypechoice -eq 2) { echo "Store type set to Standard_LRS" $storetype="Standard_LRS" } if($storetypechoice -eq 'n' -or $storetypechoice -eq 'N') { echo "Exiting deployment as per user input" exit } echo "Creating storage account. This is a long operation. Please wait till it completes." $store=New-AzStorageAccount -ResourceGroupName $rgname -Name $storename -Location $location -SkuName $storetype}
if($store.ProvisioningState -ne "Succeeded") { echo "Storage account creation did not complete successfully. Exiting deployment" if($rgcreatechoice -eq 'y' -or $rgcreatechoice -eq 'Y'){ echo "Resource group $rgname was provisioned in $location. Please delete it manually if not needed" } exit }else { #Check if the container exists in target account $containercheck=Get-AzStorageContainer -Name $dstContainer -Context $store.Context -ErrorAction SilentlyContinue if($containercheck.Name -ne $dstContainer) { #Create Storage container with the provided name echo "Storage account creation successful, creating container for disk storage." New-AzStorageContainer -Name $dstContainer -Permission Off -Context $store.Context }
} #Availability set check if($avsetname -ne '') { $avset=Get-AzAvailabilitySet -Name $avsetname -ResourceGroupName $rgname -ErrorAction SilentlyContinue if($avset.Name -eq $avsetname) { if($avset.Managed) { echo "This availability set is not supported by the vm type being deployed," echo "Please use a classic availability set to deploy this VM" exit } echo "Availability set present, vm instance will be provisioned within availability set" $avcheck="Yes" sleep 10 } }
if($avcheck -eq "No" -and $avsetname -ne '') { echo "Creating availability set for the VM" $avset=New-AzAvailabilitySet -Name $avsetname -ResourceGroupName $rgname -Location $location -Sku classic sleep 10 if($avset.Name -eq $avsetname) { echo "Created availability set, deployment in progress" sleep 5 }else { echo "Deployment will stop now, failed to create availability set" echo "To deploy, create a classic availability set in the required resource group" echo "And execute the script again" exit } $avcheck="Yes" }
#Network configuration for the virtual machine
#create the interface names $nicnames=@() if($niccount -gt 0) { echo "Creating $niccount nic names" for($i=0; $i -lt $niccount; $i++) { $nicname=$name+"nic"+$i $nicnames+=$nicname
} }else { echo "The vm needs at least 1 interface to be configured, current value is $niccount" echo "Script will exit now. Please correct the config file as per recommendations and try again" exit }
$ipnames=@() if($niccount -gt 0) { echo "Creating $niccount ip names" for($i=0; $i -lt $niccount; $i++) { $ipname=$name+"ip"+$i $ipnames+=$ipname
} } if($vnetrgname -ne $rgname){ #Validate the resource group for provisioning vnet exists }
$vnet=Get-AzVirtualNetwork -Name $vnetname -ResourceGroupName $vnetrgname -ev vnetError -ea 0 $vnetcreate='n' if($vnet.ProvisioningState -eq "Succeeded") { echo "VirtualNetwork $vnetname exists, checking for subnet" $mgmtsnet=Get-AzVirtualNetworkSubnetConfig -Name $mgmtsubnetname -VirtualNetwork $vnet -ev snetPresent -ea 0 $svcsnet=Get-AzVirtualNetworkSubnetConfig -Name $svcsubnetname -VirtualNetwork $vnet -ev snetPresent -ea 0 }else { echo "Do you wish to create the Virtual Network as per the configuration provided" $vnetcreate=Read-Host -Prompt "Enter y/n" if($vnetcreate -ne 'y' -and $vnetcreate -ne 'Y') {
echo "Virtual Network configuration for the VM instance is not provisioned" echo "This script will now exit" if($rgcreatechoice -eq 'y' -or $rgcreatechoice -eq 'Y' ){ echo "Resource group $rgname was provisioned in $location " echo "It can be removed if not in use" } if($storecreatechoice -eq 'y' -or $storecreatechoice -eq 'Y'){ echo "Storage account $storename was provisoned by this script" echo "It can be removed if not used" } exit } echo "New Virtual network $vnetname with prefix $vnetprefix will be created in $location" $vnetcreate=Read-Host -Prompt "Do you wish to continue (y/n)" if($vnetcreate -ne 'y' -and $vnetcreate -ne 'Y') { echo "Script will exit now as per user input" if($rgcreatechoice -eq 'y' -or $rgcreatechoice -eq 'Y' ){ echo "Resource group $rgname was provisioned in $location " echo "It can be removed if not in use" } if($storecreatechoice -eq 'y' -or $storecreatechoice -eq 'Y'){ echo "Storage account $storename was provisoned by this script" echo "It can be removed if not used" } exit } $mgmtsnet=New-AzVirtualNetworkSubnetConfig -Name $mgmtsubnetname -AddressPrefix $mgmtsnetprefix -ev sNetCreate -ea 0 if($mgmtsnetprefix -ne $svcsubnetprefix) { $svcsnet=New-AzVirtualNetworkSubnetConfig -Name $svcsubnetname -AddressPrefix $svcsnetprefix -ev sNetCreate -ea 0 $vnet=New-AzVirtualNetwork -Name $vnetname -ResourceGroupName $vnetrgname -Location $location -AddressPrefix $vnetprefix -Subnet $mgmtsnet,$svcsnet -ev vNetCreate -ea 0 } else { $vnet=New-AzVirtualNetwork -Name $vnetname -ResourceGroupName $vnetrgname -Location $location -AddressPrefix $vnetprefix -Subnet $mgmtsnet -ev vNetCreate -ea 0 $svcsnet=$mgmtsnet }
}
if($vnet.ProvisioningState -ne "Succeeded"){ echo "Virtual network creation failed or script was unable to fetch" echo "the Virtual network configuration. Please check the configuration" echo "for possible errors and execute the script further" if($rgcreatechoice -eq 'y' -or $rgcreatechoice -eq 'Y' ){ echo "Resource group $rgname was provisioned in $location " echo "It can be removed if not in use" } if($storecreatechoice -eq 'y' -or $storecreatechoice -eq 'Y'){ echo "Storage account $storename was provisoned by this script" echo "It can be removed if not used" } exit } $snetcreate='n' $mgmtsnet=Get-AzVirtualNetworkSubnetConfig -Name $mgmtsubnetname -VirtualNetwork $vnet -ev sNetPresent -ea 0
if($mgmtsnet.ProvisioningState -ne "Succeeded") {
echo "A subnet $mgmtsubnetname with the required configuration $mgmtsnetprefix" echo "Was not found in $vnetname " echo "The instance provisioning will exit if subnet is not created" $snetcreate=Read-Host -Prompt "Do you wish to create it now (y/n)" if($snetcreate -ne 'y' -and $snetcreate -ne 'Y') { echo "You have chosen not to provision the subnet" echo "The script will exit now" echo "Please make sure all prerequisites are met and " echo "execute the script to provision the instance" if($rgcreatechoice -eq 'y' -or $rgcreatechoice -eq 'Y' ){ echo "Resource group $rgname was provisioned in $location " echo "It can be removed if not in use" } if($storecreatechoice -eq 'y' -or $storecreatechoice -eq 'Y'){ echo "Storage account $storename was provisoned by this script" echo "It can be removed if not used" } exit } $mgmtsnet=New-AzVirtualNetworkSubnetConfig -Name $subnetname -AddressPrefix $snetprefix -ev sNetCreate -ea 0 Set-AzVirtualNetworkSubnetConfig -Name $mgmtsubnetname -VirtualNetwork $vnet -ev sNetAssign -ea 0 }
$svcsnet=Get-AzVirtualNetworkSubnetConfig -Name $svcsubnetname -VirtualNetwork $vnet -ev sNetPresent -ea 0 if($svcsnet.ProvisioningState -ne "Succeeded") {
echo "A subnet $svcsubnetname with the required configuration $svcsnetprefix" echo "Was not found in $vnetname " echo "The instance provisioning will exit if subnet is not created" $snetcreate='n' $snetcreate=Read-Host -Prompt "Do you wish to create it now (y/n)" if($snetcreate -ne 'y' -and $snetcreate -ne 'Y') { echo "You have chosen not to provision the subnet" echo "The script will exit now" echo "Please make sure all prerequisites are met and " echo "execute the script to provision the instance" if($rgcreatechoice -eq 'y' -or $rgcreatechoice -eq 'Y' ){ echo "Resource group $rgname was provisioned in $location " echo "It can be removed if not in use" } if($storecreatechoice -eq 'y' -or $storecreatechoice -eq 'Y'){ echo "Storage account $storename was provisoned by this script" echo "It can be removed if not used" } exit } $svcsnet=New-AzVirtualNetworkSubnetConfig -Name $svcsubnetname -AddressPrefix $svcsnetprefix -ev sNetCreate -ea 0 Set-AzVirtualNetworkSubnetConfig -Name $svcsubnetname -VirtualNetwork $vnet -ev sNetAssign -ea 0 }
if(($mgmtsnet.ProvisioningState -ne "Succeeded") -or ($svcsnet.ProvisioningState -ne "Succeeded")){ echo "Subnet provisioning failed" echo "Deployment cannot continue" if($rgcreatechoice -eq 'y' -or $rgcreatechoice -eq 'Y' ){ echo "Resource group $rgname was provisioned in $location " echo "It can be removed if not in use" } if($storecreatechoice -eq 'y' -or $storecreatechoice -eq 'Y'){ echo "Storage account $storename was provisoned by this script" echo "It can be removed if not used" } exit }
if($sanityrun -eq 'y'){ Write-Host "Exiting sanity check" -Foreground Green exit }
#Start creation of the VM object echo "Creating the vm object...." #$cred=Get-Credential if($avcheck -eq "Yes") { $vm = New-AzVMConfig -VMName $name -VMSize $vmsize -AvailabilitySetId $avset.Id }else { $vm = New-AzVMConfig -VMName $name -VMSize $vmsize } #$vm = Set-AzureRmVMOperatingSystem -VM $vm -Linux -ComputerName $name -Credential $cred
#Create interfaces and ip objects as per config file $nics=@() $pip=@() $pipopt='n' echo "Do you wish to allocate public ip address to the instance" $pipopt=Read-Host -Prompt "Enter y or n to proceed" echo "Generating interface configuration and attaching ip addresses...." if($pipopt -eq 'y' -or $pipopt -eq 'Y'){ for($i=0; $i -lt $niccount ; $i++) { $pip=New-AzPublicIpAddress -Name $ipnames[$i] -ResourceGroupName $rgname -Location $location -AllocationMethod Dynamic #$nic=New-AzureRmNetworkInterface -Name $nicnames[$i] -ResourceGroupName $rgname -Location $location -SubnetId $svcsnet.Id -PublicIpAddressId $pip.Id if($i -eq 0) { $nic=New-AzNetworkInterface -Name $nicnames[$i] -ResourceGroupName $rgname -Location $location -SubnetId $mgmtsnet.Id -PublicIpAddressId $pip.Id $vm = Add-AzVMNetworkInterface -VM $vm -Id $nic.Id -Primary }else { $nic=New-AzNetworkInterface -Name $nicnames[$i] -ResourceGroupName $rgname -Location $location -SubnetId $svcsnet.Id -PublicIpAddressId $pip.Id } $vm = Add-AzVMNetworkInterface -VM $vm -Id $nic.Id echo "Nics = $nics" } } else { for($i=0; $i -lt $niccount ; $i++) {
if($i -eq 0) { $nic=New-AzNetworkInterface -Name $nicnames[$i] -ResourceGroupName $rgname -Location $location -SubnetId $mgmtsnet.Id $vm = Add-AzVMNetworkInterface -VM $vm -Id $nic.Id -Primary } else { $nic=New-AzNetworkInterface -Name $nicnames[$i] -ResourceGroupName $rgname -Location $location -SubnetId $svcsnet.Id } $vm = Add-AzVMNetworkInterface -VM $vm -Id $nic.Id echo "Nics = $nics" } }
#Setting up disks for the VM clear echo "Setting up the disks." $osdiskname=$name+"_"+"osdisk.vhd" $blob="$dstStorageURI/$dstContainer" $osDiskUri = "$blob/$osdiskname" $osimageUri = "$osimage"
echo "Disk info for the VM " echo "OS Disk : $osdiskname" echo "Blob : $blob" echo "OS disk URI : $osDiskUri"
sleep 10 clear echo "Copying disks to the path"
$storecontext=$store.Context Start-AzStorageBlobCopy -AbsoluteUri $osimageUri -Context $storecontext -DestContainer $dstContainer -DestBlob $osdiskname $osstatus=Get-AzStorageBlobCopyState -Context $storecontext -Blob $osdiskname -Container $dstContainer While($osstatus.Status -ne "Success") { sleep 20 $osstatus=Get-AzStorageBlobCopyState -Context $storecontext -Blob $osdiskname -Container $dstContainer if($osstatus.Status -ne "Pending") { Break } }
$vm=Set-AzVMOSDisk -VM $vm -Name $osdiskname -VhdUri $osDiskUri -CreateOption Attach -Linux #Create the azure Virtual machine clear echo "Disk setup completed, vm object generated succesfully. Creating the instance." New-AzVM -ResourceGroupName $rgname -Location $location -VM $vm -Verbose
I replaced the line:
$vm=Set-AzVMOSDisk -VM $vm -Name $osdiskname -VhdUri $osDiskUri -CreateOption Attach -Linux
with
$vm=Set-AzVMOSDisk -VM $vm -Name $osdiskname -VhdUri $osDiskUri -CreateOption FromImage -Linux
I have virtual machine with shared gallery image vm in azure like below:
Now you should create a managed disk from disk, VHD or snapshot following this MsDoc disk should not attached to any other vm like this
When I ran the below PowerShell script, I am able to attach the existing os disk from the shared gallery image vm to new vm.
Output: