VirtualMachine/New-ArmVirtualMachine.ps1

Function New-ArmVirtualMachine
{
    [CmdletBinding(DefaultParameterSetName='ByNameAndResourceGroupName')]
    Param (
        # Name of the VM to create
        [Parameter(Mandatory=$True,ParameterSetName='ByNameAndResourceGroupName',ValueFromPipeline=$false)]
        [Parameter(Mandatory=$True,ParameterSetName='ByNameAndResourceGroupId',ValueFromPipeline=$false)]
        $VMName,
        
        # Location if the VM. If omitted, the location of the Resource Group is used
        [Parameter(Mandatory=$False,ValueFromPipeline=$false)]
        $Location,
        
        # The virtual network to place the VM in (either vnet object or vnet name)
        [Parameter(Mandatory=$False,ValueFromPipeline=$false)]
        $Vnet,
        
        # The subnet to place the VM in (either subnet object or subnet name)
        [Parameter(Mandatory=$False,ValueFromPipeline=$false)]
        $Subnet,
        
        [Parameter(Mandatory=$True,ParameterSetName='ByNameAndResourceGroupName',ValueFromPipeline=$false)]
        [Parameter(Mandatory=$True,ParameterSetName='ByInstanceCountAndResourceGroupName',ValueFromPipeline=$false)]
        $ResourceGroupName,
        
        [Parameter(Mandatory=$True,ParameterSetName='ByNameAndResourceGroupId',ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory=$True,ParameterSetName='ByInstanceCountAndResourceGroupId',ValueFromPipelineByPropertyName=$true)]
        $ResourceGroupId,
        
        [Parameter(Mandatory=$True,ParameterSetName='ByInstanceCountAndResourceGroupName',ValueFromPipeline=$false)]
        [Parameter(Mandatory=$True,ParameterSetName='ByInstanceCountAndResourceGroupId',ValueFromPipeline=$false)]
        [int]$InstanceCount,
        
        [Parameter(Mandatory=$False,ParameterSetName='ByInstanceCountAndResourceGroupName',ValueFromPipeline=$false)]
        [Parameter(Mandatory=$False,ParameterSetName='ByInstanceCountAndResourceGroupId',ValueFromPipeline=$false)]
        $NamePattern="###-****",
        
        
        [Parameter(Mandatory=$False,ValueFromPipeline=$false)]
        $StorageAccountName,

        [String]$StorageAccountContainer = "vhds",
        
        [String]$VmImage,
        
        [String]$OsType,
        
        
        
        # Is Async is specified, the shell returns immediately, not waiting for the VM to be created.
        [Switch]$Async
    )
    
    Begin
    {}
    Process
    {
        if ($ResourceGroupId)
        {
            $ResourceGroup = Get-ArmResourceGroup | where {$_.ResourceGroupId -eq $ResourceGroupId}
        }
        ElseIf ($ResourceGroupName)
        {
            $ResourceGroup = Get-ArmResourceGroup -Name $ResourceGroupName
        }
        
        if (!$ResourceGroup)
        {
            Write-error "Resource Group $Name not found"
            Return
        }
        
        if (!$Location)
        {
            $Location = $ResourceGroup.Location
        }
            
            
        #Figure out if we need to do some calculations
        if ((!$Vnet) -or (!$Subnet) -or (!$StorageAccountName))
        {
            #We don't have all the required info
            $ExistingVMs = $ResourceGroup | Get-ArmVirtualMachine
            if ($ExistingVMs -eq $null)
            {
                Write-error "No existing VMs in resource group to read properties from."
                return
            }
            
            if ((!$vnet) -or (!$Subnet))
            {
                #Get the vnet
                $Vnets = @()
                Foreach ($VM in $ExistingVMs)
                {
                    $Nics = $vm | Get-ArmNetworkInterface -Verbose:$false
                    foreach ($Nic in $Nics)
                    {
                        if ($nic.Properties.IpConfigurations[0].properties.subnet.id)
                        {
                            $ThisVnet = Get-ArmVirtualNetwork -SubnetId $nic.Properties.IpConfigurations[0].properties.subnet.id
                            if ($ThisVnet)
                            {
                                $Vnets += $ThisVnet.VirtualNetworkId
                            }
                        }
                    }
                }
            }

            if (!$vnet)
            {
                if (($Vnets | select -Unique).count -gt 1)
                    {
                        Write-error "Existing VMs have different virtual networks, so you have to specify the virtual network for the new vm(s)"
                        return
                    }
                    Else
                    {
                        $ThisVnet = Get-ArmVirtualNetwork -VirtualNetworkId ($Vnets | select -Unique)
                        Write-Verbose "Autoselected virtual network $($ThisVnet.Name) based on existing vms in the same resource group"
                    }
            }
            Else
            {
                if ($Vnet.GetType().Name -eq "String")
                {
                    $vnet = Get-ArmVirtualNetwork -VirtualNetworkId $Vnet
                }
            }
            
            

            if (!$subnet)
            {
                $AllSubnets = @()
                if ($vnet.Properties.Subnets.count -eq 1)
                {
                    
                    $Subnet = $vnet.Properties.Subnets[0].Name
                    Write-Verbose "Autoselected subnet $subnet since that's the only one in selected vnet $($vnet.Name)"

                }
                Else
                {
                    $Nics = $ExistingVMs | Get-ArmNetworkInterface -verbose:$False
                    Foreach ($Nic in $Nics)
                    {
                        $SubnetId = $nics[0].Properties.IpConfigurations[0].properties.subnet.id
                        $AllSubnets += $SubnetId
                    }

                    if (($AllSubnets | select -Unique).count -gt 1)
                    {
                        Write-error "Existing VMs have subnets, and the selected virtual network contains more than one, so you have to specify the subnet for the new vm(s)"
                    }
                    Else
                    {
                        $Subnet = $AllSubnets | select -Unique
                        $Subnet = Get-ArmSubnet -subnetId $Subnet
                        #TODO: Build a subnet function thingy
                        Write-Verbose "Autoselected subnet: $($Subnet.Name) based on existing vms in the same resource group"
                    }
                    
                }


            }

            if (!$StorageAccount)
            {
                $AllOsDiskVhdUris = @()
                foreach ($ExistingVM in $ExistingVMs)
                {
                    #Grab the osdisk uri
                    [System.UriBuilder]$VhdUri = $ExistingVM.Properties.StorageProfile.OsDisk.Vhd.uri
                    $VhdStorageAccount = $vhduri.host
                    $AllOsDiskVhdUris += $VhdStorageAccount
                }

                if (($AllOsDiskVhdUris | select -Unique).count -eq 1)
                {
                    $StorageAccount = $AllOsDiskVhdUris | select -Unique
                    Write-Verbose "Autoselected storage account: $StorageAccount based on existing vms in the same resource group"
                }
            }
            
            if (!$Vmimage)
            {
                $AllImages = @()
                foreach ($ExistingVM in $ExistingVMs)
                {
                    #Grab the osdisk uri
                    $ImageRef = $ExistingVM.Properties.StorageProfile.ImageReference
                    $ImageRefString = "/$($ImageRef.Publisher)/$($ImageRef.Offer)/$($ImageRef.Sku)/$($ImageRef.Version)"
                    $AllImages += $ImageRefString
                }
                if (($AllImages | select -Unique).count -eq 1)
                {
                    $VMImage = $AllImages | select -Unique
                    Write-Verbose "Autoselected vm image: $VMImage based on existing vms in the same resource group"
                }
                Else
                {
                    Write-error "Unable to auto-select VMImage, plase specify th VMImage parameter"
                }
                
            }
        }
        
        
        if ($VmImage.Gettype().Name -eq "String")
        {
            if ($vmimage.StartsWith("/"))
            {
                #Get rid of the first slash
                $vmimage = $vmimage.remove(0,1)
            }
            $VmImageParts = $VMImage.split("/")
            $Publisher = $VmImageParts[0]
            $Offer = $VmImageParts[1]
            $Sku = $VmImageParts[2]
            $Version = $vmImageParts[3]
            
            $ImageSearcharams = @{
                "Location"=$Location;
                "Publisher"=$Publisher;
                "Offer"=$Offer;
                "Sku"=$Sku
            }
            if ($version.ToLower() -eq "latest")
            {
                $LatestVersion = $true
            }
            Else
            {
                $ImageSearcharams.Add("version",$Version)
            }
            
        }
        
        if (!$OsType)
        {
            Write-verbose "Looking up vm image"
            $VMImageResultList = Get-ArmVmImage @ImageSearcharams
            if ($LatestVersion)
            {
                Foreach ($ImageResult in $VMImageResultList)
                {
                    #Add some strongly sortable version thingys
                    [System.Version]$ImageVersion = $ImageResult.Version
                    $imageresult | Add-Member -Name "VersionType" -MemberType NoteProperty -Value $ImageVersion -Force
                    
                }
                $SelectedVmImage = $VMImageResultList | sort VersionType -Descending | select -First 1
                Write-verbose "Selected latest image version, which is $($SelectedVmImage.Version)"
            }
            
            $OsType = $SelectedVmImage.properties.osDiskImage.operatingSystem
            Write-Verbose "Selected image has OS type $OsType"    
        }
        
        if (!$InstanceCount)
        {
            $InstanceCount = 1
        }
        Else
        {
            Write-verbose "Generating $InstanceCount VMs"
        }
        
        $VMCreateCounter = 1
        Do
        {
            Write-verbose "Generating vm $VMCreateCounter of $InstanceCount"
            if ($VmName)
            {
                
            }
            Else
            {
                $NameArray = Invoke-InternalStringToArray -InputString $NamePattern
                $RealNameArray = @()
                foreach ($Char in $NameArray)
                {
                    if ($Char -eq "#")
                    {
                        #Generate random char
                        $Random = Get-Random -Minimum 65 -Maximum 90
                        $RandomChar = [char]$Random
                        $RealNameArray += $RandomChar
                    }
                    Elseif ($Char -eq "*")
                    {
                        #Generate random number
                        $Random = get-random -Minimum 1 -Maximum 9
                        $RealNameArray += $Random.ToString()
                    }
                    Else
                    {
                        $RealNameArray += $Char
                    }
                }
                $VMCreateVMName = $RealNameArray -join ""
                Write-Verbose "Generating VM $VMCreateVMName"
                $VmCreateParams = @{
                    "VMName"=$VMCreateVMName;
                    "ResourceGroup"=$ResourceGroup;
                    "Location"=$Location;
                    #TODO: VMSIZE
                    "VMSize"=$VMSize;
                    "VMImage"=$SelectedVmImage;
                    "OsType"=$Ostype
                    "StorageAccount"=$StorageAccount;
                    "StorageAccountContainer"=$StorageAccountContainer;
                    #TODO: AdminCreds
                    "AdminUserName"=$AdminUserName;
                    "AdminPassword"=$AdminPassword;
                }
                
                $CreateVMResult = Create-InternalArmVM @VmCreateParams
            }
            $VMCreateCounter ++
        }
        Until ($VMCreateCounter -gt $InstanceCount)
        
        
        
    }
    end
    {
        
    }
}