Skip to content

Commit 293edc9

Browse files
Merge pull request #123 from larisaborodina/vNext
Add VmExtension ps API calls
2 parents ced23b4 + 82f426e commit 293edc9

2 files changed

Lines changed: 201 additions & 1 deletion

File tree

ComputeAdmin/AzureStack.ComputeAdmin.psm1

Lines changed: 187 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55

66
<#
77
.SYNOPSIS
8-
Contains 4 functions.
8+
Contains 6 functions.
99
Add-VMImage: Uploads a VM Image to your Azure Stack and creates a Marketplace item for it.
1010
Remove-VMImage: Removes an existing VM Image from your Azure Stack. Does not delete any
1111
maketplace items created by Add-VMImage.
1212
New-Server2016VMImage: Creates and Uploads a new Server 2016 Core and / or Full Image and
1313
creates a Marketplace item for it.
1414
Get-VMImage: Gets a VM Image from your Azure Stack as an Administrator to view the provisioning state of the image.
15+
Add-VMExtension: Uploads a VM extension to your Azure Stack.
16+
Remove-VMExtension: Removes an existing VM extension from your Azure Stack.
1517
#>
1618

1719
Function Add-VMImage{
@@ -789,6 +791,190 @@ Function Get-VMImage{
789791
}catch{
790792
return $null
791793
}
794+
}
795+
796+
Function Add-VMExtension{
797+
798+
[CmdletBinding(DefaultParameterSetName='VMExtensionFromLocal')]
799+
Param(
800+
[Parameter(Mandatory=$true, ParameterSetName='VMExtensionFromLocal')]
801+
[Parameter(Mandatory=$true, ParameterSetName='VMExtesionFromAzure')]
802+
[ValidatePattern([a-zA-Z0-9-]{3,})]
803+
[String] $publisher,
804+
805+
[Parameter(Mandatory=$true, ParameterSetName='VMExtensionFromLocal')]
806+
[Parameter(Mandatory=$true, ParameterSetName='VMExtesionFromAzure')]
807+
[ValidatePattern(\d+\.\d+\.\d+)]
808+
[String] $version,
809+
810+
[Parameter(ParameterSetName='VMExtensionFromLocal')]
811+
[Parameter(ParameterSetName='VMExtesionFromAzure')]
812+
[String] $type,
813+
814+
[Parameter(Mandatory=$true, ParameterSetName='VMExtensionFromLocal')]
815+
[ValidateNotNullorEmpty()]
816+
[String] $extensionLocalPath,
817+
818+
[Parameter(Mandatory=$true, ParameterSetName='VMExtesionFromAzure')]
819+
[ValidateNotNullorEmpty()]
820+
[String] $extensionBlobURI,
821+
822+
[Parameter(Mandatory=$true, ParameterSetName='VMExtensionFromLocal')]
823+
[Parameter(Mandatory=$true, ParameterSetName='VMExtesionFromAzure')]
824+
[ValidateSet('Windows' ,'Linux')]
825+
[String] $osType,
826+
827+
[Parameter(ParameterSetName='VMExtensionFromLocal')]
828+
[Parameter(ParameterSetName='VMExtesionFromAzure')]
829+
[bool] $vmScaleSetEnabled = $false,
830+
831+
[Parameter(ParameterSetName='VMExtensionFromLocal')]
832+
[Parameter(ParameterSetName='VMExtesionFromAzure')]
833+
[bool] $supportMultipleExtensions = $false,
834+
835+
[Parameter(Mandatory=$true, ParameterSetName='VMExtensionFromLocal')]
836+
[Parameter(Mandatory=$true, ParameterSetName='VMExtesionFromAzure')]
837+
[ValidateNotNullorEmpty()]
838+
[String] $tenantID,
839+
840+
[Parameter(ParameterSetName='VMExtensionFromLocal')]
841+
[Parameter(ParameterSetName='VMExtesionFromAzure')]
842+
[String] $location = 'local',
843+
844+
[Parameter(Mandatory=$true, ParameterSetName='VMExtensionFromLocal')]
845+
[Parameter(Mandatory=$true, ParameterSetName='VMExtesionFromAzure')]
846+
[System.Management.Automation.PSCredential] $azureStackCredentials,
847+
848+
[Parameter(ParameterSetName='VMExtensionFromLocal')]
849+
[Parameter(ParameterSetName='VMExtesionFromAzure')]
850+
[string] $ArmEndpoint = 'https://adminmanagement.local.azurestack.external'
851+
)
852+
853+
$resourceGroupName = "addvmextresourcegroup"
854+
$storageAccountName = "addvmextstorageaccount"
855+
$containerName = "addvmextensioncontainer"
856+
857+
$subscription, $headers = (Get-AzureStackAdminSubTokenHeader -TenantId $tenantId -AzureStackCredentials $azureStackCredentials -ArmEndpoint $ArmEndpoint)
858+
859+
#potentially the RG was not cleaned up when exception happened in previous run. Test for exist
860+
if (-not (Get-AzureRmResourceGroup -Name $resourceGroupName -Location $location -ErrorAction SilentlyContinue)) {
861+
New-AzureRmResourceGroup -Name $resourceGroupName -Location $location
862+
}
863+
864+
#same for storage
865+
$storageAccount = Get-AzureRmStorageAccount -Name $storageAccountName -ResourceGroupName $resourceGroupName -ErrorAction SilentlyContinue
866+
if (-not ($storageAccount)) {
867+
$storageAccount = New-AzureRmStorageAccount -Name $storageAccountName -Location $location -ResourceGroupName $resourceGroupName -Type Standard_LRS
868+
}
869+
870+
Set-AzureRmCurrentStorageAccount -StorageAccountName $storageAccountName -ResourceGroupName $resourceGroupName
871+
872+
#same for container
873+
$container = Get-AzureStorageContainer -Name $containerName -ErrorAction SilentlyContinue
874+
if (-not ($container)) {
875+
$container = New-AzureStorageContainer -Name $containerName -Permission Blob
876+
}
877+
878+
if($pscmdlet.ParameterSetName -eq "VMExtensionFromLocal")
879+
{
880+
$storageAccount.PrimaryEndpoints.Blob
881+
$script:extensionName = Split-Path $extensionLocalPath -Leaf
882+
$script:extensionBlobURIFromLocal = '{0}{1}/{2}' -f $storageAccount.PrimaryEndpoints.Blob.AbsoluteUri, $containerName,$extensionName
883+
Set-AzureStorageBlobContent -File $extensionLocalPath -Container $containerName -Blob $extensionName
884+
}
885+
886+
$ArmEndpoint = $ArmEndpoint.TrimEnd("/")
887+
$uri = $armEndpoint + '/subscriptions/' + $subscription + '/providers/Microsoft.Compute.Admin/locations/' + $location + '/artifactTypes/VMExtension/publishers/' + $publisher
888+
$uri = $uri + '/types/' + $type + '/versions/' + $version + '?api-version=2015-12-01-preview'
889+
890+
Log-Info $uri
792891

892+
#building request body JSON
893+
if($pscmdlet.ParameterSetName -eq "VMExtensionFromLocal") {
894+
$sourceBlobJSON = '"SourceBlob" : {"Uri" :"' + $extensionBlobURIFromLocal + '"}'
895+
}
896+
else {
897+
$sourceBlobJSON = '"SourceBlob" : {"Uri" :"' + $extensionBlobURI + '"}'
898+
}
899+
900+
$osTypeJSON = '"VmOsType" : "' + $osType + '"'
901+
$ComputeRoleJSON = '"ComputeRole" : "N/A"'
902+
$VMScaleSetEnabledJSON = '"VMScaleSetEnabled" : "' + $vmScaleSetEnabled + '"'
903+
$SupportMultipleExtensionsJSON = '"SupportMultipleExtensions" : "' + $supportMultipleExtensions + '"'
904+
$IsSystemExtensionJSON = '"IsSystemExtension" : "false"'
905+
906+
$propertyBody = $sourceBlobJSON + "," + $osTypeJSON + ',' + $ComputeRoleJSON + "," + $VMScaleSetEnabledJSON + "," + $SupportMultipleExtensionsJSON + "," + $IsSystemExtensionJSON
907+
908+
#building ARMResource
909+
910+
$RequestBody = '{"Properties":{'+$propertyBody+'}}'
911+
912+
Invoke-RestMethod -Method PUT -Uri $uri -Body $RequestBody -ContentType 'application/json' -Headers $Headers
913+
914+
$extensionHandler = Invoke-RestMethod -Method GET -Uri $uri -ContentType 'application/json' -Headers $Headers
915+
916+
while($extensionHandler.Properties.ProvisioningState -ne 'Succeeded')
917+
{
918+
if($extensionHandler.Properties.ProvisioningState -eq 'Failed')
919+
{
920+
Write-Error -Message ('VM extension download failed with Error:"{0}.' -f $publisher, $_.Exception.Message ) -ErrorAction Stop
921+
}
922+
923+
if($extensionHandler.Properties.ProvisioningState -eq 'Canceled')
924+
{
925+
Write-Error -Message "VM extension download was canceled." -ErrorAction Stop
926+
}
927+
928+
Write-Host "Downloading";
929+
Start-Sleep -Seconds 4
930+
$extensionHandler = Invoke-RestMethod -Method GET -Uri $uri -ContentType 'application/json' -Headers $Headers
931+
}
932+
933+
Remove-AzureStorageContainer –Name $containerName -Force
934+
Remove-AzureRmStorageAccount -ResourceGroupName $resourceGroupName -AccountName $storageAccountName
935+
Remove-AzureRmResourceGroup -Name $resourceGroupName -Force
936+
}
937+
938+
Function Remove-VMExtension{
939+
Param(
940+
[ValidatePattern([a-zA-Z0-9-]{3,})]
941+
[String] $publisher,
942+
943+
[Parameter(Mandatory=$true)]
944+
[ValidatePattern(\d+\.\d+\.\d+)]
945+
[String] $version,
946+
947+
[String] $type = "CustomScriptExtension",
948+
949+
[Parameter(Mandatory=$true)]
950+
[ValidateSet('Windows' ,'Linux')]
951+
[String] $osType,
952+
953+
[Parameter(Mandatory=$true)]
954+
[ValidateNotNullorEmpty()]
955+
[String] $tenantID,
956+
957+
[String] $location = 'local',
958+
959+
[Parameter(Mandatory=$true)]
960+
[System.Management.Automation.PSCredential] $azureStackCredentials,
961+
962+
[string] $ArmEndpoint = 'https://adminmanagement.local.azurestack.external'
963+
)
964+
965+
$subscription, $headers = (Get-AzureStackAdminSubTokenHeader -TenantId $tenantId -AzureStackCredentials $azureStackCredentials -ArmEndpoint $ArmEndpoint)
966+
967+
$ArmEndpoint = $ArmEndpoint.TrimEnd("/")
968+
$uri = $armEndpoint + '/subscriptions/' + $subscription + '/providers/Microsoft.Compute.Admin/locations/' + $location + '/artifactTypes/VMExtension/publishers/' + $publisher
969+
$uri = $uri + '/types/' + $type + '/versions/' + $version + '?api-version=2015-12-01-preview'
970+
971+
Log-Info $uri
972+
973+
try{
974+
Invoke-RestMethod -Method DELETE -Uri $uri -ContentType 'application/json' -Headers $headers
975+
}
976+
catch{
977+
Write-Error -Message ('Deletion of VM extension with publisher "{0}" failed with Error:"{1}.' -f $publisher, $_.Exception.Message ) -ErrorAction Stop
978+
}
793979
}
794980

ComputeAdmin/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,17 @@ Remove-VMImage -publisher "Canonical" -offer "UbuntuServer" -sku "14.04.3-LTS" -
8686
```
8787

8888
Note: This cmdlet will remove the associated Marketplace item unless the -KeepMarketplaceItem parameter is specified.
89+
90+
## Add a VM extension to the Compute with PowerShell
91+
An example usage is the following:
92+
```powershell
93+
$path = "<Path to vm extension zip>"
94+
Add-VMExtension -publisher $publisher -version $version -extensionLocalPath $path -osType Windows -tenantID $aadTenant -azureStackCredentials $azureStackCredentials -type "CustomVmExtension"
95+
```
96+
97+
# Remove a VM extension with PowerShell
98+
Run the below command to remove an uploaded VM extension.
99+
100+
```powershell
101+
Remove-VMExtension -publisher $publisher -version $version -osType Windows -tenantID $tenantId -azureStackCredentials $azureStackCredentials -type "CustomVmExtension"
102+
```

0 commit comments

Comments
 (0)