Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 91 additions & 2 deletions samples/ClassroomLabs/Modules/Library/Az.LabServices.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -996,20 +996,107 @@ function Publish-AzLab {
end { }
}

function Get-AzLabAccountSharedGallery {
[CmdletBinding()]
param(
[parameter(Mandatory = $true, HelpMessage = "Lab Account to get attached Shared Gallery.", ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
$LabAccount
)

begin { . BeginPreamble }
process {
try {
foreach ($la in $LabAccount) {
$uri = (ConvertToUri -resource $la) + "/SharedGalleries/"
return InvokeRest -Uri $uri -Method 'Get'
}
}
catch {
Write-Error -ErrorRecord $_ -EA $callerEA
}
}
end { }
}

function Get-AzLabAccountSharedImage {
[CmdletBinding()]
param(
[parameter(Mandatory = $true, HelpMessage = "Lab Account to get shared images from", ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
$LabAccount
$LabAccount,

[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true, HelpMessage = "Are the images enabled? Enabled = Yes, and Disabled = No")]
[ValidateSet('Enabled', 'Disabled', 'All')]
[string] $EnableState = "Enabled"
)

begin { . BeginPreamble }
process {
try {

foreach ($la in $LabAccount) {
$uri = (ConvertToUri -resource $la) + "/SharedImages"
return InvokeRest -Uri $uri -Method 'Get' | Where-Object { $_.properties.EnableState -eq 'Enabled' }

if ($EnableState -eq "All") {
$response = InvokeRest -Uri $uri -Method 'Get'
}
else {
$response = InvokeRest -Uri $uri -Method 'Get' | Where-Object { $_.properties.EnableState -eq $EnableState }
}

return $response
}
}
catch {
Write-Error -ErrorRecord $_ -EA $callerEA
}
}
end { }
}

function Set-AzLabAccountSharedImage {
[CmdletBinding()]
param(
[parameter(Mandatory = $true, HelpMessage = "Shared image to update.", ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
$SharedImage,

[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true, HelpMessage = "Should this image be enabled? Enabled = Yes, and Disabled = No")]
[ValidateSet('Enabled', 'Disabled')]
[string] $EnableState = "Enabled"
)

begin { . BeginPreamble }
process {
try {

foreach ($image in $SharedImage) {
$ResourceGroupName = $image.id.split('/')[4]
$LabAccountName = $image.id.split('/')[8]
$LabAccount = Get-AzLabAccount -ResourceGroupName $ResourceGroupName -LabAccountName $LabAccountName

Write-Verbose "Image to update:\n$($image | ConvertTo-Json)"

$body = @{
id = $image.id
name = $image.name
properties =
@{
EnableState = $EnableState
sharedGalleryId = $image.properties.sharedGalleryId
osType = $image.properties.osType
imageType = $image.properties.imageType
displayName = $image.properties.displayName
definitionName = $image.properties.definitionName
}
} | ConvertTo-Json

$uri = (ConvertToUri -resource $LabAccount) + "/SharedImages/"+ $image.name

$updatedImage = InvokeRest -Uri $uri -Method 'PUT' -Body ($body)
Write-Verbose "Updated image\n$($updatedImage | ConvertTo-Json)"
return WaitProvisioning -uri $uri -delaySec 60 -retryCount 120
}
}
catch {
Expand Down Expand Up @@ -1686,6 +1773,7 @@ Export-ModuleMember -Function Get-AzLabAccount,
Get-AzLab,
New-AzLab,
Get-AzLabAccountSharedImage,
Set-AzLabAccountSharedImage,
Get-AzLabAccountGalleryImage,
Remove-AzLab,
Get-AzLabTemplateVM,
Expand All @@ -1709,6 +1797,7 @@ Export-ModuleMember -Function Get-AzLabAccount,
Get-AzLabForVm,
New-AzLabAccountSharedGallery,
Remove-AzLabAccountSharedGallery,
Get-AzLabAccountSharedGallery,
Get-AzLabAccountPricingAndAvailability,
Stop-AzLabTemplateVm,
Start-AzLabTemplateVm,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,29 +338,78 @@ function Publish-Labs {
$ConfigObject
)

$lacs = $ConfigObject | Select-Object -Property ResourceGroupName, LabAccountName -Unique
$lacs = $ConfigObject | Select-Object -Property ResourceGroupName, LabAccountName, SharedGalleryResourceId, EnableSharedGalleryImages | Sort-Object -Property ResourceGroupName, LabAccountName
$lacNames = $lacs | Select-Object -Property ResourceGroupName, LabAccountName -Unique

# Get the first unique resource group\lab account and attempt to attach a shared gallery if one is specified in the csv. If the resource group\lab account exists
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if at this point we should require that the lab account, location, resource group name and shared image gallery id all match exactly... I think this might be a good validation item to force people to do the right thing rather than have the smarts here...

# more than once in the csv, we only attempt to attach to the first one and skip the rest.
$lacsToCreate = @()
foreach ($lacName in $lacNames){
$lac = $lacs | Where-Object {$_.ResourceGroupName -eq $lacName.ResourceGroupName -and $_.LabAccountName -eq $lacName.LabAccountName} | Select-Object -First 1
$lacsToCreate += $lac
}

Write-Host "Operating on the following Lab Accounts:"
Write-Host $lacs
Write-Host $lacsToCreate

$block = {
param($path, $ResourceGroupName, $LabAccountName)
param($path, $ResourceGroupName, $LabAccountName, $SharedGalleryResourceId, $EnableSharedGalleryImages)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

$modulePath = Join-Path $path '..\Az.LabServices.psm1'
Import-Module $modulePath

if ((Get-AzLabAccount -ResourceGroupName $ResourceGroupName -LabAccountName $LabAccountName) -eq $null ){
New-AzLabAccount -ResourceGroupName $ResourceGroupName -LabAccountName $LabAccountName | Out-Null
$labAccount = Get-AzLabAccount -ResourceGroupName $ResourceGroupName -LabAccountName $LabAccountName

if ($labAccount -eq $null ){
$labAccount = New-AzLabAccount -ResourceGroupName $ResourceGroupName -LabAccountName $LabAccountName
Write-Host "$LabAccountName lab account created."
}
else {
Write-Host "$LabAccountName lab account found - skipping create."
}

if ($SharedGalleryResourceId -ne $null){

$gallery = $labAccount | Get-AzLabAccountSharedGallery
if ($gallery -ne $null) {
Write-Host "$LabAccountName lab account already has attached gallery $gallery."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's the wrong gallery that's attached to the lab account, should we change it to what's in the CSV file? I think currently we don't 'fix' settings in other places - but I'm wondering what the user's expectation would be. Perhaps we should consider this as a "Upsert" (update/insert) operation when running the scripts for any changes? The downside is that changing the SIG if there are labs & student VMs means that users couldn't reset the student VMs from SIG anymore...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I was hesitant changing it if it's already set for the reasons you mentioned. I was thinking that if there are failures of some sort (for example, 503 which i've hit occassionally), which we could also include when there is an attached SIG already, that we could output this in a .csv...similar to what you're planning. When you're done with your code, we can likely reuse it here too.

}
else {
$gallery = Get-AzGallery -ResourceId $SharedGalleryResourceId

if ($gallery -ne $null) {
Write-Host "$SharedGalleryResourceId shared gallery found."
New-AzLabAccountSharedGallery -LabAccount $labAccount -SharedGallery $gallery
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be a good idea to do this by Resource ID instead of by object... The reason is because if the SIG is in a different subscription- we don't want to manually swap subscriptions back and forth to get the object if we don't have to (and I think the API just needs the SIG ID)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch - I've changed it to look by resource id...but, i am still having issues with it working to find a SIG successfully across subs. I've tested it in my subs, but I have different tentants involved. Also, tried it with Roger where we used our Microsoft subs, and still couldn't get it to work. I'd like to talk to you more to see what I'm missing.

Write-Host "$SharedGalleryResourceId shared gallery attached."
}
else {
Write-Host "$SharedGalleryResourceId shared gallery not found - skipping attach."
}
}

Write-Host "Enabling images for lab account: $labAccount"
if ($EnableSharedGalleryImages -ne $null)
{
$imageNames = $EnableSharedGalleryImages.Split(',')
}

Write-Host "Images to enable: $imageNames"
$images = $labAccount | Get-AzLabAccountSharedImage -EnableState All
foreach ($imageName in $imageNames)
{
$image = $images | Where-Object { $_.name -like $imageName } | Set-AzLabAccountSharedImage -EnableState Enabled
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we explicitly set the ones not in the CSV file as disabled, if the field is included? I'm not sure but that might be the default anyway right after attaching the SIG...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I can do that...i think that makes sense to do.

Write-Host "Image enabled: $image"
}
}
Write-Host "$LabAccountName lab account created or found."
}

Write-Host "Starting lab accounts creation in parallel. Can take a while."
$jobs = @()
$lacs | ForEach-Object {
$jobs += Start-ThreadJob -ScriptBlock $block -ArgumentList $PSScriptRoot, $_.ResourceGroupName, $_.LabAccountName -Name $_.LabAccountName -ThrottleLimit $ThrottleLimit
$lacsToCreate | ForEach-Object {
$jobs += Start-ThreadJob -ScriptBlock $block -ArgumentList $PSScriptRoot, $_.ResourceGroupName, $_.LabAccountName, $_.SharedGalleryResourceId, $_.EnableSharedGalleryImages -Name $_.LabAccountName -ThrottleLimit $ThrottleLimit
}

$hours = 1
Expand Down Expand Up @@ -419,7 +468,6 @@ function Publish-Labs {
}
}


# Needs to create resources in this order, aka parallelize in these three groups, otherwise we get contentions:
# i.e. different jobs trying to create the same common resource (RG or lab account)
New-ResourceGroups -ConfigObject $aggregateLabs
Expand Down