@@ -108,8 +108,10 @@ Function Add-VMImage{
108108 $subscription , $headers = (Get-AzureStackAdminSubTokenHeader - TenantId $tenantId - AzureStackCredentials $azureStackCredentials - ArmEndpoint $ArmEndpoint )
109109
110110 # pre validate if image is not already deployed
111+ $VMImageAlreadyAvailable = $false
111112 if (Get-AzureRmVMImage - Location $location - PublisherName $publisher - Offer $offer - Skus $sku - Version $version - ErrorAction SilentlyContinue) {
112- Write-Error - Message (' VM Image with publisher "{0}", offer "{1}", sku "{2}", version "{3}" already is present. Please remove it first or change on of the values' -f $publisher , $offer , $sku , $version ) - ErrorAction Stop
113+ $VMImageAlreadyAvailable = $true
114+ Write-Verbose - Message (' VM Image with publisher "{0}", offer "{1}", sku "{2}", version "{3}" already is present.' -f $publisher , $offer , $sku , $version ) - Verbose - ErrorAction Stop
113115 }
114116
115117 # potentially the RG was not cleaned up when exception happened in previous run. Test for exist
@@ -129,13 +131,12 @@ Function Add-VMImage{
129131 $container = New-AzureStorageContainer - Name $containerName - Permission Blob
130132 }
131133
132- if ($pscmdlet.ParameterSetName -eq " VMImageFromLocal" )
134+ if (( $pscmdlet.ParameterSetName -eq " VMImageFromLocal" ) -and ( -not $VMImageAlreadyAvailable ) )
133135 {
134136 $storageAccount.PrimaryEndpoints.Blob
135137 $script :osDiskName = Split-Path $osDiskLocalPath - Leaf
136138 $script :osDiskBlobURIFromLocal = ' {0}{1}/{2}' -f $storageAccount.PrimaryEndpoints.Blob.AbsoluteUri , $containerName , $osDiskName
137- # Add-AzureRmVhd -Destination $osDiskBlobURIFromLocal -ResourceGroupName $resourceGroupName -LocalFilePath $osDiskLocalPath -OverWrite
138- Set-AzureStorageBlobContent - File $osDiskLocalPath - Container $containerName - Blob $osDiskName
139+ Add-AzureRmVhd - Destination $osDiskBlobURIFromLocal - ResourceGroupName $resourceGroupName - LocalFilePath $osDiskLocalPath - OverWrite
139140
140141 $script :dataDiskBlobURIsFromLocal = New-Object System.Collections.ArrayList
141142 if ($PSBoundParameters.ContainsKey (' dataDisksLocalPaths' ))
@@ -238,10 +239,13 @@ Function Add-VMImage{
238239
239240 $RequestBody = ' {"Properties":{' + $propertyBody + ' }}'
240241
241- Invoke-RestMethod - Method PUT - Uri $uri - Body $RequestBody - ContentType ' application/json' - Headers $Headers
242+ if (-not $VMImageAlreadyAvailable ){
243+ Invoke-RestMethod - Method PUT - Uri $uri - Body $RequestBody - ContentType ' application/json' - Headers $Headers
244+ }
242245
243246 $platformImage = Invoke-RestMethod - Method GET - Uri $uri - ContentType ' application/json' - Headers $Headers
244247
248+ $downloadingStatusCheckCount = 0
245249 while ($platformImage.Properties.ProvisioningState -ne ' Succeeded' )
246250 {
247251 if ($platformImage.Properties.ProvisioningState -eq ' Failed' )
@@ -255,12 +259,21 @@ Function Add-VMImage{
255259 }
256260
257261 Write-Host " Downloading" ;
258- Start-Sleep - Seconds 4
262+ Start-Sleep - Seconds 10
263+ $downloadingStatusCheckCount ++
264+ if ($downloadingStatusCheckCount % 30 -eq 0 ){
265+ Write-Verbose - Message " Obtaining refreshed token..."
266+ $subscription , $Headers = (Get-AzureStackAdminSubTokenHeader - TenantId $tenantId - AzureStackCredentials $azureStackCredentials - ArmEndpoint $ArmEndpoint )
267+ }
259268 $platformImage = Invoke-RestMethod - Method GET - Uri $uri - ContentType ' application/json' - Headers $Headers
260269 }
261270
262271 if ($CreateGalleryItem -eq $true -And $platformImage.Properties.ProvisioningState -eq ' Succeeded' )
263272 {
273+ # reaquire storage account context
274+ Set-AzureRmCurrentStorageAccount - StorageAccountName $storageAccountName - ResourceGroupName $resourceGroupName
275+ $container = Get-AzureStorageContainer - Name $containerName - ErrorAction SilentlyContinue
276+
264277 $GalleryItem = CreateGalleyItem - publisher $publisher - offer $offer - sku $sku - version $version - osType $osType - title $title - description $description
265278 $blob = $container | Set-AzureStorageBlobContent –File $GalleryItem.FullName –Blob $galleryItem.Name
266279 $galleryItemURI = ' {0}{1}/{2}' -f $storageAccount.PrimaryEndpoints.Blob.AbsoluteUri , $containerName , $galleryItem.Name
@@ -294,10 +307,6 @@ Function Remove-VMImage{
294307 [ValidatePattern (“ \d+\.\d+\.\d+” )]
295308 [String ] $version ,
296309
297- [Parameter (Mandatory = $true )]
298- [ValidateSet (' Windows' , ' Linux' )]
299- [String ] $osType ,
300-
301310 [Parameter (Mandatory = $true )]
302311 [ValidateNotNullorEmpty ()]
303312 [String ] $tenantID ,
@@ -314,25 +323,30 @@ Function Remove-VMImage{
314323
315324 $subscription , $headers = (Get-AzureStackAdminSubTokenHeader - TenantId $tenantId - AzureStackCredentials $azureStackCredentials - ArmEndpoint $ArmEndpoint )
316325
326+ $VMImageExists = $false
317327 if (Get-AzureRmVMImage - Location $location - PublisherName $publisher - Offer $offer - Skus $sku - Version $version - ErrorAction SilentlyContinue - ov images) {
318- Write-Verbose " VM Image has been added to Azure Stack - continuing"
328+ Write-Verbose " VM Image has been added to Azure Stack - continuing" - Verbose
329+ $VMImageExists = $true
319330 }
320331 else {
321- Write-Error - Message (' VM Image with publisher "{0}", offer "{1}", sku "{2}" is not present.' -f $publisher , $offer , $sku ) - ErrorAction Stop
332+ Write-Verbose - Message (' VM Image with publisher "{0}", offer "{1}", sku "{2}" is not present and will not be removed. Marketplace item may still be removed .' -f $publisher , $offer , $sku ) - ErrorAction Stop
322333 }
323334
324335 $ArmEndpoint = $ArmEndpoint.TrimEnd (" /" )
325336 $uri = $armEndpoint + ' /subscriptions/' + $subscription + ' /providers/Microsoft.Compute.Admin/locations/' + $location + ' /artifactTypes/platformImage/publishers/' + $publisher
326337 $uri = $uri + ' /offers/' + $offer + ' /skus/' + $sku + ' /versions/' + $version + ' ?api-version=2015-12-01-preview'
327338
328339 try {
329- Invoke-RestMethod - Method DELETE - Uri $uri - ContentType ' application/json' - Headers $headers
340+ if ($VMImageExists ){
341+ Invoke-RestMethod - Method DELETE - Uri $uri - ContentType ' application/json' - Headers $headers
342+ }
330343 }
331344 catch {
332345 Write-Error - Message (' Deletion of VM Image with publisher "{0}", offer "{1}", sku "{2}" failed with Error:"{3}.' -f $publisher , $offer , $sku , $Error ) - ErrorAction Stop
333346 }
334347
335348 if (-not $KeepMarketplaceItem ){
349+ Write-Verbose " Removing the marketplace item for the VM Image." - Verbose
336350 $name = " $offer$sku "
337351 # Remove periods so that the offer and sku can be retrieved from the Marketplace Item name
338352 $name = $name -replace " \." , " -"
@@ -373,6 +387,8 @@ function New-Server2016VMImage {
373387
374388 [ValidateNotNullorEmpty ()]
375389 [String ] $TenantId ,
390+
391+ [String ] $location = ' local' ,
376392
377393 [Parameter ()]
378394 [bool ] $CreateGalleryItem = $true ,
@@ -404,12 +420,16 @@ function New-Server2016VMImage {
404420 Write-Error - Message " VHD was not created" - ErrorAction Stop
405421 }
406422 Write-Verbose - Message " Preparing VHD"
407- $VHDMount = Mount-DiskImage - ImagePath $VHDPath - PassThru - ErrorAction Stop
408- $disk = $VHDMount | Get-DiskImage | Get-Disk - ErrorAction Stop
409- $disk | Initialize-Disk - PartitionStyle MBR - ErrorAction Stop
410- $partition = New-Partition - UseMaximumSize - Disknumber $disk.DiskNumber - IsActive:$True - AssignDriveLetter - ErrorAction Stop
411- $volume = Format-Volume - Partition $partition - FileSystem NTFS - confirm:$false - ErrorAction Stop
412- $VHDDriveLetter = $volume.DriveLetter
423+
424+ $VHDDriveLetter = (Mount-VHD - Path $VHDPath - Passthru | `
425+ get-disk - number {$_.DiskNumber } | `
426+ Initialize-Disk - PartitionStyle MBR - PassThru | `
427+ New-Partition - UseMaximumSize - AssignDriveLetter:$False - MbrType IFS | `
428+ Format-Volume - Confirm:$false - FileSystem NTFS - force | `
429+ get-partition | `
430+ Add-PartitionAccessPath - AssignDriveLetter - PassThru | `
431+ get-volume ).DriveLetter
432+
413433 Write-Verbose - Message " VHD is mounted at drive letter: $VHDDriveLetter "
414434
415435 Write-Verbose - Message " Mounting ISO"
@@ -441,11 +461,11 @@ function New-Server2016VMImage {
441461 } catch {
442462 Write-Error - ErrorRecord $_ - ErrorAction Stop
443463 } finally {
444- if ($VHDMount ) {
445- $VHDMount | Dismount-DiskImage
464+ if (Test-Path - Path " $VHDDriveLetter `:\ " ) {
465+ $VHDPath | Dismount-DiskImage
446466 }
447467 if ($IsoMount ) {
448- $IsoMount | Dismount-DiskImage
468+ $IsoMount | Dismount-DiskImage
449469 }
450470 }
451471 }
@@ -461,7 +481,7 @@ function New-Server2016VMImage {
461481 process {
462482 Write-Verbose - Message " Checking authorization against your Azure Stack environment" - Verbose
463483
464- $subscription , $headers = (Get-AzureStackAdminSubTokenHeader - TenantId $tenantId - AzureStackCredentials $azureStackCredentials - ArmEndpoint $ArmEndpoint )
484+ $subscription , $headers = (Get-AzureStackAdminSubTokenHeader - TenantId $tenantId - AzureStackCredentials $azureStackCredentials - ArmEndpoint $ArmEndpoint - ErrorAction Stop )
465485
466486 Write-Verbose - Message " Authorization verified" - Verbose
467487
@@ -529,39 +549,69 @@ function New-Server2016VMImage {
529549 tenantID = $tenantID
530550 azureStackCredentials = $AzureStackCredentials
531551 ArmEndpoint = $ArmEndpoint
552+ location = $location
532553 }
533554
534555 if ($Version -eq ' Core' -or $Version -eq ' Both' ) {
556+
557+ $sku = " 2016-Datacenter-Core"
558+
559+ # Pre-validate that the VM Image is not already available
560+ $VMImageAlreadyAvailable = $false
561+ if (Get-AzureRmVMImage - Location $PublishArguments.location - PublisherName $PublishArguments.publisher - Offer $PublishArguments.offer - Skus $sku - Version $PublishArguments.version - ErrorAction SilentlyContinue) {
562+ $VMImageAlreadyAvailable = $true
563+ Write-Verbose - Message (' VM Image with publisher "{0}", offer "{1}", sku "{2}", version "{3}" already is present.' -f $publisher , $offer , $sku , $version ) - Verbose - ErrorAction Stop
564+ }
565+
535566 $ImagePath = " $ModulePath \Server2016DatacenterCoreEval.vhd"
536567 try {
537- Write-Verbose - Message " Creating Server Core Image"
538- CreateWindowsVHD @ConvertParams - VHDPath $ImagePath - Edition $CoreEdition - ErrorAction Stop - Verbose
568+ if ((! (Test-Path - Path $ImagePath )) -and (! $VMImageAlreadyAvailable )) {
569+ Write-Verbose - Message " Creating Server Core Image"
570+ CreateWindowsVHD @ConvertParams - VHDPath $ImagePath - Edition $CoreEdition - ErrorAction Stop - Verbose
571+ }else {
572+ Write-Verbose - Message " Server Core VHD already found."
573+ }
574+
539575 if ($CreateGalleryItem )
540576 {
541577 $description = " This evaluation image should not be used for production workloads."
542- Add-VMImage - sku " 2016-Datacenter-Core " - osDiskLocalPath $ImagePath @PublishArguments - title " Windows Server 2016 Datacenter Core Eval" - description $description - CreateGalleryItem $CreateGalleryItem
578+ Add-VMImage - sku $sku - osDiskLocalPath $ImagePath @PublishArguments - title " Windows Server 2016 Datacenter Core Eval" - description $description - CreateGalleryItem $CreateGalleryItem
543579 }
544580 else
545581 {
546- Add-VMImage - sku " 2016-Datacenter-Core " - osDiskLocalPath $ImagePath @PublishArguments - CreateGalleryItem $CreateGalleryItem
582+ Add-VMImage - sku $sku - osDiskLocalPath $ImagePath @PublishArguments - CreateGalleryItem $CreateGalleryItem
547583 }
548584 } catch {
549585 Write-Error - ErrorRecord $_ - ErrorAction Stop
550586 }
551587 }
552588 if ($Version -eq ' Full' -or $Version -eq ' Both' ) {
553589 $ImagePath = " $ModulePath \Server2016DatacenterFullEval.vhd"
554- Write-Verbose - Message " Creating Server Full Image " - Verbose
590+
555591 try {
556- CreateWindowsVHD @ConvertParams - VHDPath $ImagePath - Edition $FullEdition - ErrorAction Stop - Verbose
592+ $sku = " 2016-Datacenter"
593+
594+ # Pre-validate that the VM Image is not already available
595+ $VMImageAlreadyAvailable = $false
596+ if (Get-AzureRmVMImage - Location $PublishArguments.location - PublisherName $PublishArguments.publisher - Offer $PublishArguments.offer - Skus $sku - Version $PublishArguments.version - ErrorAction SilentlyContinue) {
597+ $VMImageAlreadyAvailable = $true
598+ Write-Verbose - Message (' VM Image with publisher "{0}", offer "{1}", sku "{2}", version "{3}" already is present.' -f $publisher , $offer , $sku , $version ) - Verbose - ErrorAction Stop
599+ }
600+
601+ if ((! (Test-Path - Path $ImagePath )) -and (! $VMImageAlreadyAvailable )) {
602+ Write-Verbose - Message " Creating Server Full Image" - Verbose
603+ CreateWindowsVHD @ConvertParams - VHDPath $ImagePath - Edition $FullEdition - ErrorAction Stop - Verbose
604+ }else {
605+ Write-Verbose - Message " Server Full VHD already found."
606+ }
557607 if ($CreateGalleryItem )
558608 {
559609 $description = " This evaluation image should not be used for production workloads."
560- Add-VMImage - sku " 2016-Datacenter " - osDiskLocalPath $ImagePath @PublishArguments - title " Windows Server 2016 Datacenter Eval" - description $description - CreateGalleryItem $CreateGalleryItem
610+ Add-VMImage - sku $sku - osDiskLocalPath $ImagePath @PublishArguments - title " Windows Server 2016 Datacenter Eval" - description $description - CreateGalleryItem $CreateGalleryItem
561611 }
562612 else
563613 {
564- Add-VMImage - sku " 2016-Datacenter " - osDiskLocalPath $ImagePath @PublishArguments - CreateGalleryItem $CreateGalleryItem
614+ Add-VMImage - sku $sku - osDiskLocalPath $ImagePath @PublishArguments - CreateGalleryItem $CreateGalleryItem
565615 }
566616 } catch {
567617 Write-Error - ErrorRecord $_ - ErrorAction Stop
0 commit comments