Finding an Azure VM Image Sku Using PowerShell

<#

The function, azure-vm-image-sku, returns the sku of a user-selected 
Azure VM image interactively. It calls the function, pick-one-item, 
which accepts an item-list and returns a selected item interactively.

This script is for demonstrating and learning Azure and PowerShell. 
The code is not optimized and does not handle all error messages. 

Usage:

# Get a sku in the default text mode
azure-vm-image-sku 

# Get a sku with GUI
azure-vm-image-sku -gui $true

# Get a sku with optional switches
azure-vm-image-sku `
  -region 'targetAzureRegion' `
  -publisher 'targetPublisherName' `
  -offer 'targetOffer' `
  -gui $true

Examples: 

azure-vm-image-sku -region 'south central us' -gui $true

azure-vm-image-sku `
  -region 'south central us' `
  -publisher 'microsoftwindowsserver'

azure-vm-image-sku `
  -region 'south central us' `
  -publisher 'microsoftwindowsserver' `
  -offer 'windowsserver' 

© 2020 Yung Chou. All Rights Reserved.

#>

function pick-one-item {

  param (
    [array  ]$thisList = @('East Asia','South Central US', 'West Europe', 'UAE North', 'South Afraica North'), 
    [string ]$itemDescription ='Azure Region', 
    [boolean]$gui = $false
    )

  if ($gui) {

    $thisOne = $thisList | Out-GridView -Title "$itemDescription List" -PassThru
  
  } else {
  
    if ($thisList.count -eq 1) { $thisOne = $thisList[0] 
    } else {
      
      $i=1; $tempList = @()

      foreach ( $item in $thisList )  {
          $tempList+="`n$i.`t$item" 
          $i++
      }

      do {
          write-host "`nHere's the $itemDescription list `n$tempList"
          $thePick = Read-Host "`nWhich $itemDEscription"
      } while(1..$tempList.length -notcontains $thePick)

      $thisOne = $thisList[($thePick-1)]
    }
  }

  write-host "$(get-date -f T) - Selecting '$thisOne' from the $itemDescription list " -f green -b black

  return $thisOne
  
}

function azure-vm-image-sku {

  param (

    [boolean]$gui = $false, 
    
    [string]$region = (pick-one-item `
      -thisList (Get-AzLocation).DisplayName `
      -itemDescription "Azure region" `
      -gui $gui ),

    [string]$publisher = (pick-one-item `
      -thisList (Get-AzVMImagePublisher -Location $region).PublisherName `
      -itemDescription "Azure $region publisher" `
      -gui $gui ),

    [string]$offer = (pick-one-item `
      -thisList (Get-AzVMImageOffer -Location $region -PublisherName $publisher).offer `
      -itemDescription "Azure $region $publisher's Offer" `
      -gui $gui ),  

    [string]$itemDescription = "Azure $region $publisher $offer Sku"

    )

  return $sku = (pick-one-item `
    -thisList (Get-AzVMImageSku -Location $region -PublisherName $publisher -Offer $offer).skus `
    -itemDescription $itemDescription `
    -gui $gui )

}

Creating Azure Usage and Quota Report Using PowerShell


write-host "

This script, based on the original script published in the article,

Report Azure resource usage with PowerShell
https://4sysops.com/archives/report-azure-resource-usage-with-powershell/,

displays interactively the Azure compute, storage, 
and network quota and usage of an examined region relevant to 
an Azure subscription. It also generates a text file accordingly. 

© 2020 Yung Chou. All Rights Reserved.

"

#region [Customization]

$region="uksouth"

#endregion

Connect-AzAccount

#region [Needed only if an account owns multiple subscriptions]

# Set the context for subsequent operations
$context = (Get-AzSubscription | Out-GridView -Title 'Set subscription context' -PassThru)
Set-AzContext -Subscription $context | Out-Null
write-host "Azure context set for the subscription, `n$((Get-AzContext).Name)" -f green

#endregion

#region [DO NOT CHANGE]

($vm = Get-AzVMUsage -Location $region `
| select @{label='ResourceType';expression={$_.name.LocalizedValue}}, currentvalue, limit) `
| Out-GridView -Title "Azure $region Region Compute Quota & Usage"

($storage = Get-AzStorageUsage -Location $region `
| select @{label='ResourceType';expression={$_.name}}, currentvalue, limit) `
| Out-GridView -Title "Azure $region Region Storage Account Quota & Usage"

($network = Get-AzNetworkUsage -Location $region `
| select @{label='ResourceType';expression={$_.resourcetype}}, currentvalue, limit) `
| Out-GridView -Title "Azure $region Network Quota & Usage"

$when=get-date -format 'yyyyMMdd-hhmm'

($usage = @("Azure $region Region Quota and usage, as of $when",$vm,"`n",$storage,"`n",$network) | ft) `
>> "usage-$region-$when.txt"

#endregion [DO NTO CHANGE]

Creating Azure Managed Disk with VHD Using PowerShell


#region [CREATE MANAGED DISK WITH VHD]

write-host "
------------------------------------------------------------

This script is based on the following reference and for
learning Azure and PowerShell. I have made changes to the
original scrtip for clarity and portability.

Ref: Create a managed disk from a VHD file
https://docs.microsoft.com/en-us/azure/virtual-machines/scripts/virtual-machines-windows-powershell-sample-create-managed-disk-from-vhd

Recommend manually running the script statement by
statement in cloud shell.

© 2020 Yung Chou. All Rights Reserved.

------------------------------------------------------------
"

#region [CUSTOMIZATION]

#region [Needed only if an account owns multiple subscriptions]

Get-AzSubscription | Out-GridView  # Copy the target subscription name

# Set the context for subsequent operations
$context = (Get-AzSubscription | Out-GridView -Title 'Set subscription context' -PassThru)
Set-AzContext -Subscription $context | Out-Null
write-host "Azure context set for the subscription, `n$((Get-AzContext).Name)" -f green

#endregion

$sourceVhdStorageAccountResourceId = '/subscriptions/…/StorageAccounts/'
$sourceVhdUri = 'https://.../.vhd'

#Get-AzLocation
$sourceVhdLoc = 'centralus'

$mngedDiskRgName ="da-mnged-$(get-date -format 'mmss')"
#$mngedDiskRgName ='dnd-mnged'

#Provide the name of a to-be-created Managed Disk
$mngedDiskName = 'myMngedDisk'
$mngedStorageType = 'Premium_LRS' # Premium_LRS,Standard_LRS,Standard_ZRS
$mngedDiskSize = '128' # In GB greater than the source VHD file size

#endregion

if (($existingRG = (Get-AzResourceGroup | Where {$_.ResourceGroupName -eq $mngedDiskRgName})) -eq $Null) {
write-host "Resource group, $mngedDiskRgName, not found, creating it" -f y
New-AzResourceGroup -Name $mngedDiskRgName -Location $mngedDiskLoc
} else {
write-host "Using this resource group, $mngedDiskRgName, for the managed disk, $mngedDiskName" -f y
}

$diskConfig = New-AzDiskConfig `
-AccountType $mngedStorageType `
-Location $sourceVhdLoc `
-CreateOption Import `
-StorageAccountId $sourceVhdStorageAccountResourceId `
-SourceUri $sourceVhdUri

New-AzDisk `
-Disk $diskConfig `
-ResourceGroupName $mngedDiskRgName `
-DiskName $mngedDiskName `
-Verbose

#endregion [CREATE MANAGED DISK WITH VHD]

#region [CLean up]
# Remove-AzResourceGroup -Name $mngedDiskRgName -Force -AsJob
#endregion

Deploying Azure VM with Diagnostics Extension and Boot Diagnostics

This is a sample script for deploying an Azure VM with Diagnostics Extension and Boot Diagnostics, while each in a different resource group. The intent is to clearly illustrate the process with required operations, while paying minimal effort for code optimization.

Ideally an Azure VM, Diagnostic Extension, and Boot Diagnostics are to be deployed with the same resource group. However in production, it may be necessary to organize them into individual resource groups for standardization, which is what this script demonstrates.

The script can be run as it is. Or simply make changes in customization section and leave the rest in place. For VM Diagnostic Extension, the configuration file should be placed where the script is. Or update the variable, $diagnosticsConfigPath, accordingly. This script uses Storage Account Key for access which allows the storage account with a subscription different from that deploys the VM. A sample configuration file, diagnostics_publicconfig_NoStorageAccount.xml, is available  and notice there is no <StorageAccount> element specified in this file.

Here’s the user experience up to finishing the [Deploying] section in the script. By default, an Azure VM is deployed with Boot Diagnostic enabled. The script upon a VM deployment changes and disables the Boot Diagnostic of the VM. For the following sample run, it took 3 minutes and 58 seconds.

Deploying Azure VM and setting Boot Diagnostics as disabled Deploying Azure VM and setting Boot Diagnostics as disabled

Now with an Azure VM in place, the script adds VM Diagnostic Extension, followed by enabling Boot Diagnostics. Herr either extension uses a storage account in a resource group different form the VM’s. So this script creates 3 resource groups for: a VM itself, and the Diagnostics Extension and the Boot Diagnostics of the VM.

VM, Diagnostics, and Boot Diagnostics deployed with individual resource groups

VM, Diagnostics, and Boot Diagnostics deployed with individual resource groups


write-host "
---------------------------------------------------------

This is a sample script for deploying an Azure VM
with Diagnostics Extension and Boot Diagnostics,
while each in a different resource group.

The intent is to clearly illustrate the process with
required operations, while paying minimal effort for
code optimization.

Ideally an Azure VM, Diagnostic Extension, and Boot Diagnostics
are to be deployed with the same resource group. However
in production, it may be necessary to organize them into
individual resource groups for standardization,
which is what this script demonstrates.

The script can be run as it is. Or simply make changes
in customization section, while leave the rest in place.
For VM Diagnostic Extension, the configuration file should
be placed where thi script is. Or update the variable,
$diagnosticsConfigPath, accordingly. This script uses a
Storage Account Key for access. This configuration allows
the storage account with a subscription different from that
deploys the VM. A sample configuration file,
diagnostics_publicconfig_NoStorageAccount.xml, is available at

https://1drv.ms/u/s!AuraBlxqDFRshVSl0IpWcsjRQkUX?e=3CGcgq

and notice there is no <StorageAccount> element specified in this file.

© 2020 Yung Chou. All Rights Reserved.

---------------------------------------------------------
"

Disconnect-AzAccount; Connect-AzAccount
# If multipel subscription
# Set-AzContext -SubscriptionId "xxxx-xxxx-xxxx-xxxx"

#region [Customization]

$cust=@{
initial='yc'
;region='southcentralus'
}

$diagnosticsConfigPath='diagnostics_publicconfig_NoStorageAccount.xml'

#region [vm admin credentials]

# 1.To hard-code
$cust+=@{
vmAdmin ='changeMe'
;vmAdminPwd='forDemoOnly!'
}
$vmAdmPwd=ConvertTo-SecureString $cust.vmAdminPwd -AsPlainText -Force
$vmAdmCred=New-Object System.Management.Automation.PSCredential ($cust.vmAdmin, $vmAdmPwd);
#>

# 2. Or interactively
#$vmAdminCred = Get-Credential -Message "Enter the VM Admin credentials."

#endregion

$tag=$cust.initial+(get-date -format 'mmss')
Write-host "`nSession ID = $tag" -f y

# Variables for common values
$vmRGName=$tag+'-RG'
$loc=$cust.region
$vmName=$tag+'vm'

$deployment=@{
vmSize='Standard_B2ms'
;dataDiskSzieInGB=5
;publisher='MicrosoftWindowsServer'
;offer='WindowsServer'
;sku='2016-Datacenter'
;version='latest'
;vnetAddSpace='192.168.0.0/16'
;subnetAddSpace='192.168.1.0/24'
}

#endregion

#region [Deployment Preping]

# Create a resource group
New-AzResourceGroup -Name $vmRGName -Location $loc
# Remove-AzResourceGroup -Name $vmRGName -AsJob

# Create a subnet configuration
$subnetConfig = `
New-AzVirtualNetworkSubnetConfig `
-Name 'default' `
-AddressPrefix ($deployment.subnetAddSpace) `
-WarningAction 'SilentlyContinue'

# Create a virtual network
$vnet = `
New-AzVirtualNetwork `
-ResourceGroupName $vmRGName `
-Location $loc `
-Name "$tag-vnet" `
-AddressPrefix $deployment.vnetAddSpace `
-Subnet $subnetConfig

# Create a public IP address and specify a DNS name
$pip = `
New-AzPublicIpAddress `
-ResourceGroupName $vmRGName `
-Location $loc `
-Name "$vmName-pip" `
-AllocationMethod Static `
-IdleTimeoutInMinutes 4

# Create an inbound network security group rule for port 3389
$nsgRuleRDP = `
New-AzNetworkSecurityRuleConfig `
-Name "$vmName-rdp" `
-Protocol Tcp `
-Direction Inbound `
-Priority 1000 `
-SourceAddressPrefix * `
-SourcePortRange * `
-DestinationAddressPrefix * `
-DestinationPortRange 3389 `
-Access Allow

# Create an inbound network security group rule for port 80,443
$nsgRuleHTTP = `
New-AzNetworkSecurityRuleConfig `
-Name "$vmName-http" -Protocol Tcp `
-Direction Inbound `
-Priority 1010 `
-SourceAddressPrefix * `
-SourcePortRange * `
-DestinationAddressPrefix * `
-DestinationPortRange 80,443 `
-Access Allow

$nsg= `
New-AzNetworkSecurityGroup `
-ResourceGroupName $vmRGName `
-Location $loc `
-Name "$vmName-nsg" `
-SecurityRules $nsgRuleRDP, $nsgRuleHTTP `
-Force

# Create a virtual network card and associate with public IP address and NSG
$nic = `
New-AzNetworkInterface `
-Name "$vmName-nic" `
-ResourceGroupName $vmRGName `
-Location $loc `
-SubnetId $vnet.Subnets[0].Id `
-PublicIpAddressId $pip.Id `
-NetworkSecurityGroupId $nsg.Id

$vmConfig = `
New-AzVMConfig `
-VMName $vmName `
-VMSize $deployment.vmSize `
| Set-AzVMOperatingSystem `
-Windows `
-ComputerName $vmName `
-Credential $vmAdmCred `
| Set-AzVMSourceImage `
-PublisherName $deployment.publisher `
-Offer $deployment.offer `
-Skus $deployment.sku `
-Version $deployment.version `
| Add-AzVMNetworkInterface `
-Id $nic.Id

#endregion

#region [Deploying]

$StopWatch = New-Object -TypeName System.Diagnostics.Stopwatch; $stopwatch.start()
write-host "`nDeploying the vm, $vmName, to $loc...`n" -f y

$vmStatus = `
New-AzVM `
-ResourceGroupName $vmRGName `
-Location $loc `
-VM $vmConfig `
-WarningAction 'SilentlyContinue' `
-Verbose

Set-AzVMBgInfoExtension `
-ResourceGroupName $vmRGName `
-VMName $vmName `
-Name 'bginfo'

$vm = Get-AzVM -ResourceGroupName $vmRGName -Name $vmName
# Set by default not to enable boot diagnostic
Set-AzVMBootDiagnostic `
-VM $vm `
-Disable `
| Update-AzVM
write-host "`nSet the vm, $vmName, with BootDiagnostic 'Disabled'`n" -f y

write-host '[Deployment Elapsed Time]' -f y
$stopwatch.stop(); $stopwatch.elapsed

#endregion

#region [Set VM Diagnostic Extension]
<# If using a diagnostics storage account name for the VM Diagnostic Extension, the storage account must be in the same subscription as the virtual machine. If the diagnostics storage account is in a different subscription than the virtual machine's, then enable sending diagnostics data to that storage account by explicitly specifying its name and key. #>
$vmDiagRGName=$tag+'vmDiag-RG'
$vmDiagStorageName=$tag+'vmdiagstore'

New-AzResourceGroup -Name $vmDiagRGName -Location $loc
#Remove-AzResourceGroup -Name $vmDiagRGName -AsJob

New-AzStorageAccount `
-ResourceGroupName $vmDiagRGName `
-AccountName $vmDiagStorageName `
-Location $loc `
-SkuName Standard_LRS

Set-AzVMDiagnosticsExtension `
-ResourceGroupName $vmRGName `
-VMName $vmName `
-DiagnosticsConfigurationPath $diagnosticsConfigPath `
-StorageAccountName $vmDiagStorageName `
-StorageAccountKey (
Get-AzStorageAccountKey `
-ResourceGroupName $vmDiagRGName `
-AccountName $vmDiagStorageName
).Value[0] `
-WarningAction 'SilentlyContinue'

$vmExtDiag = Get-AzVMDiagnosticsExtension -ResourceGroupName $vmRGName -VMName $vmName

#endregion

#region [Enable Boot Diagnostic]

# The resource group and the storage account are
# different from the vm's.

$vmBootDiagRGName=$tag+'bootDiag-RG'
$bootDiagStorageName=$tag+'bootdiagstore'

New-AzResourceGroup -Name $vmBootDiagRGName -Location $loc
#Remove-AzResourceGroup -Name $vmBootDiagRGName -AsJob

New-AzStorageAccount `
-ResourceGroupName $vmBootDiagRGName `
-AccountName $bootDiagStorageName `
-Location $loc `
-SkuName Standard_LRS

Set-AzVMBootDiagnostic `
-Enable `
-VM $vm `
-ResourceGroupName $vmBootDiagRGName `
-StorageAccountName $bootDiagStorageName `
| Update-AzVM

#endregion

#region [Session Summary]

($RGs = Get-AzResourceGroup | Where ResourceGroupName -like "$tag*") `
| ft ResourceGroupName, Location

($vms = Get-AzVM| Where ResourceGroupName -like "$tag*") `
| ft ResourceGroupName, Location, Name

($SAs = Get-AzStorageAccount | Where ResourceGroupName -like "$tag*") `
| ft ResourceGroupName, Location, StorageAccountName

#endregion

<# [Clean Up] 
Remove-AzResourceGroup -Name $vmRGName -AsJob 
Remove-AzResourceGroup -Name $vmDiagRGName -AsJob 
Remove-AzResourceGroup -Name $vmBootDiagRGName -AsJob 
#>

Azure, Ubuntu, and LVM on Encrypted Disks

:' 
Title: Azure, Ubuntu, and LVM on Encrypted Disks

Yung Chou © 2019

@yungchou
https://yungchou.wordpress.com
https://www.linkedin.com/in/yungchou/

This article depicts the logical flow with step-by-step
operations for configuring LVM on encrypted disks of an 
Azure Ubuntu VM. The configured LVM is a 3-disk stripe
set.
My intent is to provide clarity on the how-to with 
the following Azure CLI and BASH statements, while
considering little in optimizing and automating 
the process.

Notice that the flow of the steps and operations 
involves switching context between 

- a remote shell session to the Azure subscription 
- an ssh session to the deployed Azure Ubuntu VM

To follow the steps and execute the operations, first 
start a BASH shell session, log into Azure and set a 
subscription context, as applicable. Then simply 
populate the customization section with intended 
values, copy and paste selected statements into the 
Azure remote shell or an ssh session to the deployed 
Azure Ubuntu VM for execution, as directed.

STEP
0. LOG IN AZURE WITH A REMOTE SHELL SESSION
1. CUSTOMIZE SETTINGS
2. CREATE A RESOURCE GROUP FOR ALL RESOURCES
3. DEPLOY A VM FOR HOSTING LVM
4. ATTACH DATA DISKS 
5. ADD A KEY VAULT AND A KEY FOR ENCRYPTION

6. SSH INTO THE DEPLOYED VM,
   FORMAT AND MOUNT THE DATA DISKS,
   THEN EXIT AND BACK TO AZURE SESSION

7. BACK TO AZURE,
   ENABLE VM ENCRYPTION WITH KEK

8. SSH INTO THE DEPLOYED VM,
   CONFIGURE LVM, AND
   REBOOT THE VM

9. SSH INTO THE DEPLOYED VM UPON RESTART AND
   VERIFY LVM CONFIGURATION AND MOUNT POINT

X. OPTIONALLY CLEAN UP THE DEPLOYED RESOURCES

'
#---------------------------------------------
# 0. LOG IN AZURE WITH A REMOTE SHELL SESSION
#---------------------------------------------
az login -o table

# If multiple subscriptions, identifying an intended subscription
az account list -o table
# Then set the context
az account set --subscription 'subscription_name_or_id'

#-----------------------
# 1. CUSTOMIZE SETTINGS
#-----------------------
id=$(date +"%M%S") # Session ID

# Deploy a VM for hosting a LVM
rgName=rg$id
vmName=vm$id

sku='UbuntuLTS'  # Azure image sku, e.g. win2016datacenter
location='southcentralus'  # Azure region

# Listing VM sizes available in the Azure region
# az vm list-sizes -l $location | more

vmSize='Standard_B2ms'  # For configuring LVM, at least 8 GB RAM

diskSize=5    # GB
numOfDisks=3  # LUN {0...numOfdisks-1}
diskNamePrefix="disk$id-"

user='testing'
pwd='Notforproduction!'

kvName="kv$id"
keyName="key$id"
volType='DATA'      # Encrypting only data disks

#----------------------------------------------
# 2. CREATE A RESOURCE GROUP FOR ALL RESOURCES
#----------------------------------------------
az group create --name $rgName --location $location -o table

#--------------------------------
# 3. DEPLOY A VM FOR HOSTING LVM
#--------------------------------
az vm create \
    -g $rgName \
    -n $vmName \
    --image $sku \
    --size $vmSize \
    --admin-username $user \
    --admin-password $pwd \
    --verbose; \
az vm get-instance-view -g $rgName -n $vmName  -o table
#az vm list -g $rgName -d -o table

# VM Public IP
pubip=$(az vm show -d -g $rgName -n $vmName --query publicIps -o tsv)

#az vm open-port --port 80 --resource-group $rgName --name $vmName

#----------------------
# 4. ATTACH DATA DISKS 
#----------------------
let n=$numOfDisks-1

for lun in $(seq 0 $n)
do
az vm disk attach \
   --vm-name $vmName \
   -g $rgName \
   -n $diskNamePrefix$diskSize$lun \
   --size-gb $diskSize \
   --new \
   --verbose
done; \
az disk list -g $rgName -o table

#---------------------------------------------
# 5. ADD A KEY VAULT AND A KEY FOR ENCRYPTION
#---------------------------------------------
az keyvault create \
  -g $rgName \
  -n $kvName \
  --location $location \
  --enabled-for-disk-encryption \
  -o table \
  --verbose

az keyvault key create \
  --vault-name $kvName \
  --name $keyName \
  --ops decrypt encrypt sign unwrapKey verify wrapKey \
  --verbose
  
az keyvault key list --vault-name $kvName -o table

#----------------------------------------
# 6. SSH INTO THE DEPLOYED VM,
#    FORMAT AND MOUNT THE DATA DISKS,
#    THEN EXIT AND BACK TO AZURE SESSION
#----------------------------------------
user_at_ip=$user@$pubip

#-----------------------------------------
# Now ssh to the VM, format and mount the 
# disks before enabling encryption.
#-----------------------------------------
ssh $user_at_ip
clear
sudo su -

# No such file, if disks not added to the VM in Azure
ls -l /dev/disk/azure/scsi1/lun*
dmesg | grep SCSI

# Here, assuming disks already added in Azure portal as LUN {0...x}
echo 'y' | mkfs.ext4 /dev/disk/azure/scsi1/lun0
echo 'y' | mkfs.ext4 /dev/disk/azure/scsi1/lun1
echo 'y' | mkfs.ext4 /dev/disk/azure/scsi1/lun2

lsblk -f # FSTYPE and UUID populated

UUID0="$(blkid -s UUID -o value /dev/disk/azure/scsi1/lun0)"
UUID1="$(blkid -s UUID -o value /dev/disk/azure/scsi1/lun1)"
UUID2="$(blkid -s UUID -o value /dev/disk/azure/scsi1/lun2)"

mkdir /lun-0  # mount point for lun0
mkdir /lun-1  # moutn point for lun1
mkdir /lun-2  # moutn point for lun2

echo "UUID=$UUID0 /lun-0 ext4 defaults,nofail 0 0" >>/etc/fstab
echo "UUID=$UUID1 /lun-1 ext4 defaults,nofail 0 0" >>/etc/fstab
echo "UUID=$UUID2 /lun-2 ext4 defaults,nofail 0 0" >>/etc/fstab

more /etc/fstab | grep lun* 

mount -a      # Making sure disks mounted without issue
df -h /lun*   # Examining the mount point of each disk

exit  # exiting sudo
exit  # clsoing ssh and back to Azure remote shell session

#----------------------------------------
# 7. BACK TO AZURE,
#    ENABLE VM ENCRYPTION WITH KEK
#
#    The data disks to be encrypted must 
#    be mounted at this time in the VM.
#----------------------------------------
vaultResourceId=$(az keyvault show -g $rgName -n $kvName --query id -o tsv)

# The encryption may take a few minutes.
az vm encryption enable \
  -n $vmName \
  -g $rgName \
  --disk-encryption-keyvault $vaultResourceId \
  --key-encryption-keyvault $vaultResourceId \
  --key-encryption-key $keyName \
  --volume-type $volType \
  --encrypt-format-all \
  --verbose 

az vm encryption show \
  -g $rgName \
  -n $vmName \
  --query '[status,substatus]'

#------------------------------
# 8. SSH INTO THE DEPLOYED VM,
#   CONFIGURE LVM, AND
#   REBOOT THE VM
#------------------------------
ssh $user_at_ip
sudo su -

df -h /lun*

umount /lun-0  
umount /lun-1
umount /lun-2

fdisk -l | grep mapper
more /etc/crypttab  # Identifying the mapping

#----------------------------------------------
# Update the following mapping before creating
# physical volumes and volume group
#----------------------------------------------
echo 'y' | pvcreate /dev/mapper/???...???
echo 'y' | pvcreate /dev/mapper/???...???
echo 'y' | pvcreate /dev/mapper/???...???

volGroup="vg$id"
vgcreate $volGroup \
  /dev/mapper/???...??? \
  /dev/mapper/???...??? \
  /dev/mapper/???...???

vgdisplay -v $volGroup

logicalVol='stripes3'
lvcreate --extents 100%FREE --stripes 3 -n $logicalVol $volGroup
echo 'yes' | mkfs.ext4 /dev/$volGroup/$logicalVol

lvdisplay -a -m

mount -a
df -h /lun*

reboot

#----------------------------------------------
# 9. SSH INTO THE DEPLOYED VM UPON RESTRAT AND
#   VERIFY LVM CONFIGURATION AND MOUNT POINT
#----------------------------------------------
ssh $user_at_ip
sudo su -

lsblk -f
more /etc/fstab | grep mapper

# If all has gone well, LVM is up and running at this time.
vgdisplay -v $volGroup

exit # form sudo su -
exit # from the VM

#-----------------------------------------------
# X. OPTIONALLY CLEAN UP THE DEPLOYED RESOURCES
#-----------------------------------------------
az group delete -g $rgName --yes -y --no-wait
az logout

Building IoT Solutions with IoT Central

For those who have been working on IoT and IoT Edge, this is what we have all been waiting for. IoT Central offers a vehicle to streamline and automate the process, while shortening and accelerating your go-to-market. Edge computing has never been so easy. Ranga Vadlamudi (@RangaVadlamudi), a Microsoft Principal PM, who explained and demonstrated how one can realize an IoT Edge computing solution from planning, architecture, configuration, to deployment, visualization and monitoring. For those who just started or want to start IoT, IoT Central is a highly integrated, cohesive and converged solution platform to deliver maximal values with minimal domain-knowledge. Much peripheral knowledge on data management and visualization are in place and allow one to focus on process optimization and value extractions.  And finally those Machine Learning developers, IoT Central simplifies the mechanics to pilot a solution and allow you to focus more on developing and experimenting the analytics modules.

My presentation on 20191113

Four topics I talked about in this presentation :

  • VM preparation for migrating from on-premises to cloud
  • High Availability, Disaster Recovery, and Scalability
  • Azure Internet-of-Things (IoT) edge computing
  • Machine Learning (ML) application development