update
This commit is contained in:
+251
@@ -0,0 +1,251 @@
|
||||
function Get-ITDVMwareSharePointNetworkList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VM Networks')/items" + '?$top=10000' + '&$select=ID,Title,Vlan_Id,CIDR,PA_Zone,Secure,AutoUpdate'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL
|
||||
Method = "Get"
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true
|
||||
}
|
||||
|
||||
$List = (Invoke-RestMethod @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
#$List = (Invoke-RestMethod -Uri $URL -Method Get -UseDefaultCredentials -headers @{ "Accept" = "application/json;odata=verbose" }) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDPAInterface {
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
[string[]]
|
||||
$Number
|
||||
)
|
||||
|
||||
begin {
|
||||
#[xml]$RawXmlZones = (Invoke-RestMethod -Uri 'https://itdnettools.nd.gov/rktest/7050zones.py').Content
|
||||
$RawXmlZones = (Invoke-RestMethod -Uri 'https://itdnettools.nd.gov/rktest/7050zones.py')
|
||||
$Zones = $RawXmlZones.response.result.zone.entry
|
||||
$UniversalDenyZones = Get-ITDPAUniversalDenyZone
|
||||
}
|
||||
|
||||
process {
|
||||
$result = @()
|
||||
ForEach ($Zone in $Zones) {
|
||||
#$Interfaces = $Zone.network.layer3.member | ForEach-Object{$_ -replace 'ae1.'}
|
||||
$Interfaces = $Zone.network.layer3.member | ForEach-Object { $_ -replace "ethernet\d/\d\d." }
|
||||
If ($Number) {
|
||||
$Interfaces = (Compare-Object -ReferenceObject $Interfaces -DifferenceObject $Number -ExcludeDifferent -IncludeEqual).InputObject
|
||||
}
|
||||
ForEach ($Interface in $Interfaces) {
|
||||
$obj = [PSCustomObject]@{
|
||||
Interface = $Interface;
|
||||
Zone = $Zone.name
|
||||
ZeroTrust = If (@($UniversalDenyZones) -eq $Zone.Name) { $true }Else { $false };
|
||||
}
|
||||
$result += $obj
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
Write-Output $result
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDPAUniversalDenyZone {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
|
||||
)
|
||||
|
||||
Begin {
|
||||
$Inbound = (((((Invoke-RestMethod -Uri 'http://itdnettools.nd.gov/rktest/7050denyinbound.py?policy=Universal%20Zone%20Deny%20Inbound') -split '[\r\n]+') | Where-Object { $_ -match "<member>" -and $_ -notmatch "any" -and $_ -notmatch "Deny" }) -replace "<member>") -replace "</member>") -Replace " " | Sort-Object
|
||||
$Outbound = (((((Invoke-RestMethod -Uri 'http://itdnettools.nd.gov/rktest/7050denyinbound.py?policy=Universal%20Zone%20Deny%20Outbound') -split '[\r\n]+') | Where-Object { $_ -match "<member>" -and $_ -notmatch "any" -and $_ -notmatch "Deny" }) -replace "<member>") -replace "</member>") -Replace " " | Sort-Object
|
||||
}
|
||||
Process {
|
||||
$result = Compare-Object -ReferenceObject $Inbound -DifferenceObject $Outbound -IncludeEqual | Sort-Object InputObject
|
||||
}
|
||||
End {
|
||||
Write-Output ($result | Where-Object SideIndicator -EQ '==').InputObject
|
||||
}
|
||||
}
|
||||
|
||||
function Set-ITDVMwareSharePointNetworkRecord {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[string]
|
||||
$Vlan_Id,
|
||||
|
||||
[string]
|
||||
$PA_Zone,
|
||||
|
||||
[ValidateSet("True", "False")]
|
||||
[string]
|
||||
$Secure,
|
||||
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
Begin {
|
||||
$UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
}
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
#$RequestDigest = Invoke-RestMethod -Uri $UrlContextInfo -Method Post -UseDefaultCredentials
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Networks')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
}
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
#$List = Invoke-RestMethod -uri $UrlList -UseDefaultCredentials
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Networks')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
#$ListItems=((Invoke-RestMethod -Uri $UrlListItem -Method Get -UseDefaultCredentials -headers @{ "Accept" = "application/json;odata=verbose" }) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
$ListItems = ((Invoke-RestMethod @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
}
|
||||
Process {
|
||||
$RecordToModify = $ListItems | Where-Object Vlan_id -EQ $Vlan_Id
|
||||
If (@($RecordToModify).count -gt 1) {
|
||||
Write-Warning "More than one result, skipping $Vlan_Id"
|
||||
}
|
||||
Else {
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Networks')/items($IDtoModify)"
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName }
|
||||
}
|
||||
|
||||
If ($PA_Zone) { $SetRecord += @{PA_Zone = $PA_Zone } }
|
||||
If ($Secure) { $SetRecord += @{Secure = $Secure } }
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
}
|
||||
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
}
|
||||
}
|
||||
End {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
$SharePointList = Get-ITDVMwareSharePointNetworkList -Credential $SharePointCredential
|
||||
|
||||
$PAInterfaces = Get-ITDPAInterface -ErrorAction SilentlyContinue # | select *, @{n = 'Vlan_Id'; e = { $_.Interface.PadLeft(4, '0') } }
|
||||
|
||||
If ($null -eq $PAInterfaces) {
|
||||
|
||||
}
|
||||
Else {
|
||||
ForEach ($SPItem in $SharePointList) {
|
||||
Write-Warning ($SPItem.Vlan_Id + ", " + $SPItem.CIDR + " - Start")
|
||||
$change = $false
|
||||
|
||||
If ($SPItem.AutoUpdate -eq $true) {
|
||||
$SetITDVMwareSharePointVMNetworkParams = $null
|
||||
|
||||
$PAItem = $PAInterfaces | Where-Object Interface -EQ ($SPItem.Vlan_Id -as [int])
|
||||
$SetITDVMwareSharePointVMNetworkParams = @{Vlan_Id = $SPItem.Vlan_Id;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
If ($PAItem.ZeroTrust) {
|
||||
If ($SPItem.Secure -ne $PAItem.ZeroTrust) {
|
||||
$SetITDVMwareSharePointVMNetworkParams += @{Secure = [bool]$PAItem.ZeroTrust }
|
||||
$change = $true
|
||||
}
|
||||
}
|
||||
Else {
|
||||
If ($SPItem.Secure -eq $false) {
|
||||
# Secure is accurate
|
||||
}
|
||||
Else {
|
||||
$SetITDVMwareSharePointVMNetworkParams += @{Secure = $false }
|
||||
$change = $true
|
||||
}
|
||||
}
|
||||
|
||||
If ($SPItem.PA_Zone -ne $PAItem.Zone) {
|
||||
$SetITDVMwareSharePointVMNetworkParams += @{PA_Zone = $PAItem.Zone }
|
||||
$change = $true
|
||||
}
|
||||
|
||||
If ($Change -eq $true) {
|
||||
Write-Warning ("Set VM network metadata: Vlan " + $SPItem.Vlan_Id + ", " + $SPItem.CIDR)
|
||||
Set-ITDVMwareSharePointNetworkRecord @SetITDVMwareSharePointVMNetworkParams
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$postParams = [PSCustomObject]@{
|
||||
AutomationName = "Infra-VMware";
|
||||
Action = 'Provisioning';
|
||||
Units = 5;
|
||||
Platform = 'PowerShell-VMware-NetworkSync';
|
||||
}
|
||||
|
||||
Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json)
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54'
|
||||
$AppId = '60244573-7130-4026-9c6d-47de73f8ca29'
|
||||
$SecureStringPwd = "sQV8Q~sNLcrDl2RgB32gsSEsDVgdFhNMcBdPoaEX"
|
||||
#$zm = Get-Credential -username $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force)
|
||||
|
||||
$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force)
|
||||
Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId
|
||||
|
||||
# laptop
|
||||
Connect-AzAccount -ServicePrincipal -Credential $IaasAutoAzApp -Tenant $tenantId
|
||||
+843
@@ -0,0 +1,843 @@
|
||||
# https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=dVIj9zHSJwNeR2Ow8QTOoiSoKaPPux9EVJsQAMiGUPg%3d
|
||||
<#
|
||||
$ComputerName = 'itddotfrsql3.nd.gov'
|
||||
$CPU = 8
|
||||
$MemoryGB = 32
|
||||
$OS = 'Windows Server 2019 Datacenter'
|
||||
$Subnet = '10.21.12.0/22'
|
||||
$Environment = "Production"
|
||||
$Platform = "Azure"
|
||||
$AppName = 'DOT-FacialRec'
|
||||
$LicensingRestrictions='Microsoft SQL Enterprise'
|
||||
$Credential = $PrvCred
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object] $WebhookData
|
||||
)
|
||||
|
||||
<# New-ITDVMwareWindowsVMAA
|
||||
#>
|
||||
|
||||
function New-ITDAzureWindowsVMAA {
|
||||
[CmdLetBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$ComputerName,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[int]
|
||||
$CPU,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[int]
|
||||
$MemoryGB,
|
||||
|
||||
#[Parameter(Mandatory = $true)]
|
||||
#[int]
|
||||
#$DiskOS,
|
||||
|
||||
#[Parameter(Mandatory = $true)]
|
||||
#[int]
|
||||
#$DiskData,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$Subnet,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$OS,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$Environment,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$AppName,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$LicensingRestrictions
|
||||
|
||||
#[Parameter(Mandatory = $true)]
|
||||
#[PSCredential]
|
||||
#$Credential
|
||||
)
|
||||
|
||||
|
||||
$Body = "
|
||||
ComputerName=$ComputerName
|
||||
CPU=$CPU
|
||||
MemoryGB=$MemoryGB
|
||||
VlanId=$VlanId
|
||||
OS=$OS
|
||||
Environment=$Environment
|
||||
Datacenter=$Datacenter
|
||||
LicensingRestrictions=$LicensingRestrictions
|
||||
AppName=$AppName
|
||||
|
||||
RunningOn=$env:computername
|
||||
RunningAs=$env:username
|
||||
Credential=$Credential.UserName
|
||||
"
|
||||
Send-MailMessage -From "zmauto@nd.gov" -To "zmeier@nd.gov" -SmtpServer apprelay1.nd.gov -Body $Body -Subject "AutoBuildAzure-$ComputerName"
|
||||
|
||||
$FQDN = $ComputerName
|
||||
$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54'
|
||||
|
||||
If ($Credential) {
|
||||
$IaasAuto = $Credential
|
||||
}
|
||||
|
||||
#$IaasAutoAzApp = Get-AutomationPSCredential -Name 'Azure IaaS Service Principal'
|
||||
|
||||
Write-Warning "[$FQDN]:Start"
|
||||
$SPCred = $IaasAuto
|
||||
$ADCred = $IaasAuto
|
||||
$PSCred = $IaasAuto
|
||||
$VMCred = $IaasAuto
|
||||
$CcmCred = $IaasAuto
|
||||
|
||||
#$RadiusCred = $RadiusCred
|
||||
$RadiusCred = New-Object System.Management.Automation.PSCredential($IaasAuto.username.split('\')[1], ($IaaSAuto.Password))
|
||||
|
||||
Clear-DnsClientCache
|
||||
$HostName = $FQDN.split('.')[0]
|
||||
|
||||
|
||||
|
||||
# Infoblox
|
||||
#$InfobloxVlanMetadata = Get-ITDIbVlan -CIDR $Subnet -Credential $RadiusCred # not valid for Azure
|
||||
#$Cidr = ($InfobloxVlanMetadata.AssignedTo | Out-String).TrimEnd()
|
||||
$Cidr = $Subnet
|
||||
[Net.IpAddress]$NetworkId = $Cidr.split('/')[0]
|
||||
[Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress
|
||||
$SubnetMaskInt = $CIDR.split('/')[1]
|
||||
$Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2))
|
||||
[Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(),
|
||||
([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(),
|
||||
([math]::Truncate(($Int64 % 65536) / 256)).ToString(),
|
||||
([math]::Truncate($Int64 % 256)).ToString()
|
||||
$IPSplit = $Subnet.Split('.')
|
||||
[Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($CIDR.split('/')[0].split('.')[-1] -as [int]) + 1) )
|
||||
|
||||
If ($IpAddress) {
|
||||
If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) {
|
||||
Write-Warning "DNS record already exists, CIDR Block match"
|
||||
}
|
||||
Else {
|
||||
Write-Error "DNS record already exists, and does not match CIDR Block"
|
||||
Break
|
||||
}
|
||||
}
|
||||
Else {
|
||||
New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred
|
||||
Start-Sleep -Seconds 5
|
||||
[Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress
|
||||
|
||||
|
||||
If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) {
|
||||
Write-Error "IP Address already in use." -ErrorAction Stop
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Passwordstate
|
||||
If ($FQDN -like "itdcnd*") {
|
||||
$PasswordStateList = "Peoplesoft Share PW"
|
||||
}
|
||||
Else {
|
||||
$PasswordStateList = "CSRC"
|
||||
}
|
||||
|
||||
$LocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $PSCred
|
||||
#$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
#$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ($LocalCredential.UserName, ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($LocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
#$GuestCredential = $GuestCredentialBB
|
||||
|
||||
switch ($Environment) {
|
||||
{ $_ -eq 'Test' -or $_ -eq 'Development' } {
|
||||
Write-Warning 'Environment is Test or Development'
|
||||
$EnvShortString = 'tst'
|
||||
#$VMSizeFilter="*_B*s*"
|
||||
$VMSizeFilter1 = "*_D[0-9]*s_v3"
|
||||
$VMSizeFilter2 = "*_E[0-9]*s_v3"
|
||||
$VMSizeFilter3 = "*_F[0-9]*s_v2"
|
||||
|
||||
$Subscription = "npd01"
|
||||
$VNet = "vnet-npd01-001"
|
||||
$VNetSubnet = "sn-shared-zerotrust-npd-10.21.8.0_22"
|
||||
}
|
||||
'Production' {
|
||||
Write-Warning 'Environment is Production'
|
||||
$EnvShortString = 'prd'
|
||||
#$VMSizeFilter="*_D*s_*"
|
||||
$VMSizeFilter1 = "*_D[0-9]*s_v3"
|
||||
$VMSizeFilter2 = "*_E[0-9]*s_v3"
|
||||
$VMSizeFilter3 = "*_F[0-9]*s_v2"
|
||||
$Subscription = "prd01"
|
||||
$VNet = "vnet-prd01-001"
|
||||
$VnetSubnet = "sn-shared-zerotrust-prd-10.21.12.0_22"
|
||||
}
|
||||
'CARES-tst' {
|
||||
Write-Warning 'Environment is CARES-tst'
|
||||
$EnvShortString = 'tst'
|
||||
#$VMSizeFilter="*_D*s_*"
|
||||
$VMSizeFilter1 = "*_D[0-9]*s_v3"
|
||||
$VMSizeFilter2 = "*_E[0-9]*s_v3"
|
||||
$VMSizeFilter3 = "*_F[0-9]*s_v2"
|
||||
$Subscription = "cares01"
|
||||
$VNet = "vnet-infra-azurenetworking-cares01-npd"
|
||||
$VnetSubnet = "sn-shared-zerotrust-npd-10.69.254.0_24"
|
||||
}
|
||||
'CARES-prd' {
|
||||
Write-Warning 'Environment is CARES-prd'
|
||||
$EnvShortString = 'prd'
|
||||
#$VMSizeFilter="*_D*s_*"
|
||||
$VMSizeFilter1 = "*_D[0-9]*s_v3"
|
||||
$VMSizeFilter2 = "*_E[0-9]*s_v3"
|
||||
$VMSizeFilter3 = "*_F[0-9]*s_v2"
|
||||
$Subscription = "cares01"
|
||||
$VNet = "vnet-infra-azurenetworking-cares01-prd"
|
||||
$VnetSubnet = "sn-shared-zerotrust-prd-10.69.126.0_24"
|
||||
}
|
||||
|
||||
Default {
|
||||
Write-Error "Environment failed" -ErrorAction Stop
|
||||
}
|
||||
}
|
||||
|
||||
switch ($OS) {
|
||||
"Windows Server 2019 Datacenter" {
|
||||
$VMOS = "Windows"
|
||||
$Publisher = "MicrosoftWindowsServer"
|
||||
$Offer = "WindowsServer"
|
||||
$sku = "2019-Datacenter"
|
||||
}
|
||||
"Windows Server 2022 Datacenter" {
|
||||
$VMOS = "Windows"
|
||||
$Publisher = "MicrosoftWindowsServer"
|
||||
$Offer = "WindowsServer"
|
||||
$sku = "2022-datacenter"
|
||||
}
|
||||
Default { Write-Error "Invalid operating system" -ErrorAction Stop }
|
||||
}
|
||||
|
||||
# finalize VM size
|
||||
Connect-AzAccount -ServicePrincipal -Credential $IaasAutoAzApp -Tenant $tenantId
|
||||
|
||||
$location = "centralus"
|
||||
$VMSize = Get-AzVMSize -Location $location | `
|
||||
Where-Object { $_.Name -Like "$VMSizeFilter1" -or $_.Name -Like "$VMSizeFilter2" -or $_.Name -Like "$VMSizeFilter3" } | `
|
||||
Where-Object { $_.NumberOfCores -ge $CPU -and $_.MemoryInMB -ge ($Memory * 1024) } | `
|
||||
Where-Object Name -NotMatch "_Promo" | `
|
||||
Sort-Object NumberOfCores, MemoryInMB | `
|
||||
Select-Object -First 1
|
||||
|
||||
|
||||
# resource group things
|
||||
$VMOwner = $AppName.split('-')[0].ToLower()
|
||||
$VMFunction = (($AppName -replace "$VMOwner-") -replace "-").ToLower() -replace " "
|
||||
#$IPAddress = (Resolve-DnsName -Name $ComputerName -ErrorAction Stop).IpAddress
|
||||
$ResourceGroup = "rg-$VMOwner-$VMFunction-$EnvShortString"
|
||||
If ($ResourceGroupIndex) { $ResourceGroup = $ResourceGroup + "-$ResourceGroupIndex" }
|
||||
$VMName = "vm-$HostName-$EnvShortString"
|
||||
|
||||
|
||||
$NewITDAzureRMVMParams = @{
|
||||
VMFQDN = $ComputerName
|
||||
VMSubscription = $Subscription
|
||||
VMEnvironment = $EnvShortString
|
||||
VMOwner = $VMOwner
|
||||
VMFunction = $VMFunction
|
||||
VMSize = $VMSize.Name
|
||||
VMOS = $VMOS
|
||||
VMPublisher = $Publisher
|
||||
VMOffer = $Offer
|
||||
VMSku = $sku
|
||||
VMVnetName = $VNet
|
||||
VMSubnet = $VNetSubnet
|
||||
VMLocation = $location
|
||||
VMIP = $IPAddress.IPAddressToString
|
||||
VMCredential = $LocalCredential
|
||||
AppName = $AppName
|
||||
}
|
||||
<#
|
||||
$VMFQDN = $ComputerName
|
||||
$VMSubscription = $Subscription
|
||||
$VMEnvironment = $EnvShortString
|
||||
$VMOwner = $VMOwner
|
||||
$VMFunction = $VMFunction
|
||||
$VMSize = $VMSize.Name
|
||||
$VMOS = $VMOS
|
||||
$VMPublisher = $Publisher
|
||||
$VMOffer = $Offer
|
||||
$VMSku = $sku
|
||||
$VMVnetName = $VNet
|
||||
$VMSubnet = $VNetSubnet
|
||||
$VMLocation = $location
|
||||
$VMIP = $IPAddress
|
||||
$VMCredential = $LocalCredential
|
||||
$AppName = $AppName
|
||||
#>
|
||||
New-ITDAzureRMVM @NewITDAzureRMVMParams
|
||||
|
||||
# wait for build
|
||||
$VMName = ('vm-' + $ComputerName.split('.')[0] + '-' + $EnvShortString)
|
||||
|
||||
$VMStatus = $null
|
||||
$VMCreation = $Null
|
||||
While ($VMCreation -ne "Complete") {
|
||||
If (( (Get-AzVM -ResourceGroupName $ResourceGroup -Name $VMName -Status).Statuses | Where-Object Code -Match "PowerState").Code -eq "PowerState/running") {
|
||||
$VMCreation = "Complete"
|
||||
}
|
||||
else {
|
||||
Start-Sleep -Seconds 300
|
||||
}
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds 30
|
||||
|
||||
# Add extra disk
|
||||
Add-ITDAzureRMNewDataDisk -VMName $VMName -SizeGB 20
|
||||
|
||||
# pre-firewall Guest OS customization
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\1-SetWMITags.ps1'
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\3-Disks.ps1'
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\5-TimeZone.ps1'
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\6-PerformanceCounters.ps1'
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\7-DisableWindowsFirewall.ps1'
|
||||
|
||||
# determine Active Directory Forest and OU
|
||||
$DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1)
|
||||
switch ($DomainName) {
|
||||
'nd.gov' {
|
||||
$SearchBaseDomain = "dc=nd,dc=gov"
|
||||
}
|
||||
'ndcloud.gov' {
|
||||
$SearchBaseDomain = "dc=ndcloud,dc=gov"
|
||||
}
|
||||
}
|
||||
If ($DomainName -eq "nd.gov") {
|
||||
$OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq $AppName }
|
||||
If (!($OUAppName)) {
|
||||
$OUAppName = Get-ADOrganizationalUnit -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' }
|
||||
}
|
||||
$ExistingADComputer = Get-ADComputer -Filter { Name -eq $Hostname }
|
||||
If ($ExistingADComputer) {
|
||||
If ($ExistingADComputer.DistinguishedName -like ("*" + $AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") {
|
||||
Write-Warning "AD object already exists, OU path does match"
|
||||
$OuFinal = $ExistingADComputer.DistinguishedName -replace '^.+?(?<!\\),', ''
|
||||
}
|
||||
Else {
|
||||
Write-Error "AD object already exists, OU path mismatch"
|
||||
Exit
|
||||
Exit
|
||||
}
|
||||
}
|
||||
Else {
|
||||
switch ($Environment) {
|
||||
'Test' {
|
||||
If ($AppName -like "Shared-Peoplesoft*") { $EnvString = "Non-Prod" }
|
||||
Else { $EnvString = "Test" }
|
||||
$OuAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -EQ "$EnvString"
|
||||
}
|
||||
'Production' {
|
||||
If ($AppName -like "Shared-Peoplesoft*") { $EnvString = "Prod" }
|
||||
Else { $EnvString = "Prod" }
|
||||
|
||||
$OuAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -EQ "$EnvString"
|
||||
}
|
||||
}
|
||||
If ($OuAppNameEnv) { $OUFinal = $OUAppNameEnv.DistinguishedName }
|
||||
Else { $OuFinal = $OUAppName.DistinguishedName }
|
||||
|
||||
New-ADComputer -Name $HostName.ToUpper() -Path $OUFinal -Credential $ADCred -Description ($SPItem | Select-Object AppName, Environment | ConvertTo-Json)
|
||||
}
|
||||
}
|
||||
|
||||
# disconnect, wait for firewall, then reconnect
|
||||
Disconnect-AzAccount
|
||||
While ($PingStatus -eq $false) {
|
||||
$PingTest = Test-NetConnection -ComputerName $FQDN
|
||||
If ($PingTest.PingSuccedded -eq $true) {
|
||||
$PingStatus = $true
|
||||
}
|
||||
Start-Sleep -Seconds 300
|
||||
}
|
||||
|
||||
|
||||
Connect-AzAccount -ServicePrincipal -Credential $IaasAutoAzApp -Tenant $tenantId
|
||||
Set-AzContext -Subscription $Subscription
|
||||
|
||||
|
||||
|
||||
# post-firewall Guest OS customization
|
||||
switch ($DomainName) {
|
||||
'nd.gov' {
|
||||
Write-Warning "Attempting domain join nd.gov"
|
||||
Write-Warning "Domain: $DomainName"
|
||||
Write-Warning "OuPath: $OuFinal"
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\8-Domain-ndgov.ps1' -Parameter @{"DomainName" = 'nd.gov'; "OuPath" = ' CN=ITDSOSCMTSQL22,OU=SOS-BLS,OU=SOS-All,OU=Windows,OU=SERVERS,OU=COMPUTERS,OU=ITD,DC=nd,DC=gov' }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Write-Verbose -Message "Activating windows against $KMS..."
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\9-KMS.ps1'
|
||||
|
||||
<#
|
||||
Write-Warning "[$FQDN]:Register SCCM Client"
|
||||
$CcmRegistered = $false
|
||||
While ($CcmRegistered -eq $false) {
|
||||
$CcmResult = Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\10-SCCM-a.ps1'
|
||||
If ($CcmResult.Value -match "SCCM Client is registered") {
|
||||
Write-Warning "Client is registered."
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
ElseIf ($CcmRegistered -eq $false) { Start-Sleep -Seconds 60 }
|
||||
}
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Approve SCCM Client"
|
||||
#Start-Sleep -Seconds 30 # ADD LOOP/SMARTS TO WAIT FOR DISCOVERY AND ANOTHER FOR APPROVAL
|
||||
Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $CcmCred -ArgumentList $Hostname -ScriptBlock {
|
||||
Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1'
|
||||
$PSDrives = Get-PSDrive
|
||||
If ($PSDrives | Where-Object Name -EQ "ITD") {
|
||||
# ITD Drive exists, do nothing
|
||||
}
|
||||
else {
|
||||
New-PSDrive -Name "ITD" -PSProvider AdminUI.PS.Provider\CMSite -Root itdsccmp2.nd.gov
|
||||
}
|
||||
|
||||
Set-Location ITD:\
|
||||
$Device = Get-CMDevice -Name $args[0]
|
||||
If ($Device.IsApproved -eq 0) {
|
||||
Approve-CMDevice -DeviceName $args[0]
|
||||
}
|
||||
}
|
||||
#>
|
||||
|
||||
|
||||
}
|
||||
|
||||
function New-ITDAzureRMVM {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
# VM Computer Name (FQDN)
|
||||
[Parameter(Mandatory = $true, Position = 0)]
|
||||
[String]
|
||||
$VMFQDN,
|
||||
|
||||
# VM Subscription (tst,prd,dr)
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMSubscription,
|
||||
|
||||
# Environment (tst,prd,dr)
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMEnvironment,
|
||||
|
||||
# Owner (infra,shared,ITD,DHS,etc)
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMOwner,
|
||||
|
||||
# Function (testdc, POC, etc)
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMFunction,
|
||||
|
||||
#[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$ResourceGroupIndexNumber,
|
||||
|
||||
# Azure VM Size
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMSize,
|
||||
|
||||
# Azure OS (Windows or Linux)
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMOS,
|
||||
|
||||
# Availability Set
|
||||
[switch]
|
||||
$VMAS,
|
||||
|
||||
# Availability Set Tier
|
||||
[string]
|
||||
$VMASTier,
|
||||
|
||||
# Availability Zone
|
||||
[ValidateSet(1, 2, 3)]
|
||||
[int]
|
||||
$VMAvailZone,
|
||||
|
||||
# Azure Publisher
|
||||
[string]
|
||||
$VMPublisher,
|
||||
|
||||
# Azure Offer
|
||||
[string]
|
||||
$VMOffer,
|
||||
|
||||
# Azure Sku
|
||||
[string]
|
||||
$VMSku,
|
||||
|
||||
# Azure vNet
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMVNetName,
|
||||
|
||||
# Azure Subnet
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMSubnet,
|
||||
|
||||
# Azure Location
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMLocation,
|
||||
|
||||
# Azure Private IP
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMIP,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[PSCredential]
|
||||
$VMCredential,
|
||||
|
||||
# App name to be used for the RG
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$AppName
|
||||
)
|
||||
Begin {
|
||||
$VMName = $VMFQDN.Split('.')[0]
|
||||
#$VMIndexNumber = "001"
|
||||
$VMIPConfigName = "ipconfig-$VMName-$VMEnvironment"
|
||||
$VMNicName = "nic-$VMName-$VMEnvironment" ######
|
||||
$VMObjectName = "vm-$VMName-$VMEnvironment"
|
||||
$ResourceGroup = "rg-$VMOwner-$VMFunction-$VMEnvironment"
|
||||
#If($ResourceGroupIndexNumber){$ResourceGroup = $ResourceGroup + "-$ResourceGroupIndexNumber"}
|
||||
#removing diag storage account because replaced by managed storage accounts for boot diagnostics
|
||||
#$VMDiagStorageAcct = "sa" + $VMOwner + $VMFunction + "diag" + $VMEnvironment
|
||||
$VMOSDiskName = "vm-$VMName-os-$VMEnvironment"
|
||||
|
||||
<#
|
||||
If($VMASTier)
|
||||
{
|
||||
$VMASName = "as-$VMOwner-$VMFunction-$VMASTier-$VMEnvironment"
|
||||
}
|
||||
Else
|
||||
{
|
||||
$VMASName = "as-$VMOwner-$VMFunction-$VMEnvironment"
|
||||
}
|
||||
#>
|
||||
|
||||
<#
|
||||
Write-Verbose "Checking Storage Account Length"
|
||||
If (($VmDiagStorageAcct.Length) -gt 24){
|
||||
Write-Verbose "Storage Account Length is too long. Truncating function...."
|
||||
$TruncateCharacters = $VmDiagStorageAcct.Length - 24
|
||||
$ShortVMFunction = $VMFunction.Substring(0, ($VMFunction.length) - $TruncateCharacters)
|
||||
$VMDiagStorageAcct = "sa" + $VMOwner + $ShortVMFunction + "diag" + $VMEnvironment
|
||||
}
|
||||
|
||||
If (($VmDiagStorageAcct.Length) -gt 24){
|
||||
Write-Verbose "Storage Account Length is too long after truncating. Terminating Build"
|
||||
Return
|
||||
}
|
||||
#>
|
||||
Write-Verbose "Verifying Applicable Inputs are Lowercase"
|
||||
$VMIPConfigName = $VMIPConfigName.ToLower()
|
||||
$VMNicName = $VMNicName.ToLower()
|
||||
$VMObjectName = $VMObjectName.ToLower()
|
||||
$ResourceGroup = $ResourceGroup.ToLower()
|
||||
#$VMDiagStorageAcct = $VMDiagStorageAcct.ToLower()
|
||||
$VMOSDiskName = $VMOSDiskName.ToLower()
|
||||
}
|
||||
Process {
|
||||
Set-AzContext $VMSubscription
|
||||
$ResGroupExist = ""
|
||||
Write-Verbose "Creating Resource Group if it doesn't exist"
|
||||
$ResGroupExist = Get-AzResourceGroup -Name $ResourceGroup -ErrorAction SilentlyContinue
|
||||
|
||||
|
||||
If (@($ResGroupExist).count -gt 1) {
|
||||
Write-Error "Multiple Resource Groups matched" -ErrorAction Stop
|
||||
}
|
||||
If (@($ResGroupExist).count -lt 1) {
|
||||
Write-Warning "No matching resource group found, creating it now"
|
||||
New-AzResourceGroup -Name $ResourceGroup -Location $VMLocation -Tag @{ApplicationName = $AppName }
|
||||
$ResourceGroupName = $ResourceGroupSearch.ResourceGroupName
|
||||
#Write-Error "No Resource Groups matched" -ErrorAction Stop
|
||||
}
|
||||
If (@($ResGroupExist).count -eq 1) {
|
||||
Write-Warning "Exactly one matching resource group found"
|
||||
$ResourceGroupName = $ResourceGroupSearch.ResourceGroupName
|
||||
}
|
||||
|
||||
<#
|
||||
Write-Verbose "Checking Storage Account Availability in Subscription"
|
||||
If (!(Get-AzureRmStorageAccount | Where-Object {$_.StorageAccountName -eq $VMDiagStorageAcct}))
|
||||
{
|
||||
If ((Get-AzureRmStorageAccountNameAvailability -Name $VMDiagStorageAcct).NameAvailable -eq $True)
|
||||
{
|
||||
|
||||
New-AzureRmStorageAccount -Name $VMDiagStorageAcct -Location $VMLocation -ResourceGroupName $ResourceGroup -SkuName "Standard_LRS" -EnableHttpsTrafficOnly $true
|
||||
#Start-Sleep -Seconds 5
|
||||
Get-AzureRmStorageAccount -ResourceGroupName $ResourceGroup -Name $VMDiagStorageAcct | Update-AzureRmStorageAccountNetworkRuleSet -DefaultAction Deny -Bypass None
|
||||
#Update-AzureRmStorageAccountNetworkRuleSet -ResourceGroupName $ResourceGroup -Name $VMDiagStorageAcct -DefaultAction Deny -Bypass None
|
||||
Add-AzureRmStorageAccountNetworkRule -ResourceGroupName $ResourceGroup -AccountName $VMDiagStorageAcct -IPAddressOrRange "165.234.248.3"
|
||||
}
|
||||
Else
|
||||
{
|
||||
Write-Verbose "Storage Account already exists. Re-run with a valid storage account"
|
||||
Return
|
||||
}
|
||||
}
|
||||
#>
|
||||
<#
|
||||
Write-Verbose "Evaluating Availability Set"
|
||||
If($VMAS)
|
||||
{
|
||||
Write-Verbose "Checking for existing Availability Set"
|
||||
$VMASExist = Get-AzAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName -ErrorAction SilentlyContinue
|
||||
If($VMASExisting)
|
||||
{
|
||||
$VMASID = $VMASExist.id
|
||||
}
|
||||
Else
|
||||
{
|
||||
New-AzAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName -Location $VMLocation -PlatformFaultDomainCount 3 -PlatformUpdateDomainCount 5 -Sku Aligned
|
||||
$VMASID = (Get-AzAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName).id
|
||||
}
|
||||
}
|
||||
#>
|
||||
|
||||
Write-Verbose "Preparing Network Config"
|
||||
$VNet = (Get-AzVirtualNetwork | where { $_.Name -eq $VMVNetName })
|
||||
$VNetID = $VNet.id
|
||||
$Subnet = ($VNet.Subnets | where { $_.Name -eq $VMSubnet })
|
||||
$SubnetName = $Subnet.name
|
||||
$SubnetID = $Subnet.id
|
||||
|
||||
Write-Verbose "Creating IPConfig and NIC"
|
||||
$IPConfig = New-AzNetworkInterfaceIpConfig -Name $VMIPConfigName -PrivateIpAddress $VMIP -PrivateIpAddressVersion IPv4 -Subnet $Subnet
|
||||
$VMNIC = New-AzNetworkInterface -IpConfigurationName $IPConfig -Location $VMLocation -Name $VMNICName -ResourceGroupName $ResourceGroup -SubnetId $SubnetID
|
||||
$VMNIC.IpConfigurations[0].PrivateIpAllocationMethod = "Static"
|
||||
$VMNIC.IpConfigurations[0].PrivateIpAddress = $VMIP
|
||||
Set-AzNetworkInterface -NetworkInterface $VMNIC
|
||||
|
||||
Write-Verbose "Building VM Config"
|
||||
#If($VMAS)
|
||||
#{
|
||||
#$vmConfig = New-AzVMConfig -VMName $VMObjectName -VMSize $VMSize -AvailabilitySetId $VMASID
|
||||
#}
|
||||
#Else
|
||||
#{
|
||||
#If($VMAvailZone)
|
||||
#{
|
||||
# Write-Verbose "AvailZone $VMAvailZone"
|
||||
# $vmConfigParams = @{
|
||||
# VMName = $VMObjectName
|
||||
# VMSize = $VMSize
|
||||
# Zone = $VMAvailZone
|
||||
# }
|
||||
#}
|
||||
#Else
|
||||
#{
|
||||
# Write-Verbose "No AvailZone"
|
||||
$vmConfigParams = @{
|
||||
VMName = $VMObjectName
|
||||
VMSize = $VMSize
|
||||
}
|
||||
#}
|
||||
#$vmConfig = New-AzureRmVMConfig -VMName $VMObjectName -VMSize $VMSize
|
||||
$vmConfig = New-AzVMConfig @vmConfigParams
|
||||
#}
|
||||
|
||||
|
||||
|
||||
$vmConfig | Set-AzVMOSDisk -Name $VMOSDiskName -CreateOption FromImage
|
||||
If ($VMOS -eq "Windows") {
|
||||
$vmConfig | Set-AzVMOperatingSystem -Windows -ComputerName $VMName -Credential $VMCredential
|
||||
$vmConfig | Set-AzVMSourceImage -PublisherName $VMPublisher -Offer $VMOffer -Skus $VMSku -Version latest
|
||||
}
|
||||
If ($VMOS -eq "Linux") {
|
||||
$vmConfig | Set-AzVMOperatingSystem -Linux -ComputerName $VMFQDN -Credential $VMCredential
|
||||
Switch ($VMSubscription) {
|
||||
#"npd01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/76297098-764c-43de-8525-c9fda1b237be/resourceGroups/rg-infra-templates-tst-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-001"}
|
||||
#"infra01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/e53aa0c7-824d-40a2-b420-4ab77b1051d2/resourceGroups/rg-infra-templates-prd-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-001"}
|
||||
#"prd01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/437b2bfa-850e-4464-b6c2-38a68cda7c69/resourceGroups/rg-infra-templates-prd-002/providers/Microsoft.Compute/images/vm-rhel74template-prd-002"}
|
||||
|
||||
"npd01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/76297098-764c-43de-8525-c9fda1b237be/resourceGroups/rg-infra-templates-tst-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-103" }
|
||||
"infra01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/e53aa0c7-824d-40a2-b420-4ab77b1051d2/resourceGroups/rg-infra-templates-prd-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-403" }
|
||||
"prd01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/437b2bfa-850e-4464-b6c2-38a68cda7c69/resourceGroups/rg-infra-templates-prd-002/providers/Microsoft.Compute/images/vm-rhel74template-prd-003" }
|
||||
}
|
||||
}
|
||||
|
||||
$vmConfig | Add-AzVMNetworkInterface -Id $VMNIC.ID
|
||||
#$vmConfig | Set-AzureRmVMBootDiagnostics -Enable -ResourceGroupName $ResourceGroup -StorageAccountName $VMDiagStorageAcct
|
||||
##set to use managed storage account after module conversion to Az
|
||||
#$vmConfig | Set-AzVMBootDiagnostic -VM $vmConfig -Enable -ResourceGroupName $ResourceGroup
|
||||
Set-AzVMBootDiagnostic -VM $vmConfig -Enable -ResourceGroupName $ResourceGroup
|
||||
|
||||
Write-Verbose "Creating VM"
|
||||
New-AzVM -VM $vmConfig -ResourceGroupName $resourceGroup -Location $VMLocation -DisableBginfoExtension -LicenseType "Windows_Server" -AsJob
|
||||
|
||||
}
|
||||
End {
|
||||
}
|
||||
}
|
||||
|
||||
function Add-ITDAzureRMNewDataDisk {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[string]
|
||||
$VMName,
|
||||
|
||||
[int[]]
|
||||
$SizeGB
|
||||
)
|
||||
|
||||
Begin {
|
||||
$search = @()
|
||||
$Hostname = $VMName.split('-')[1]
|
||||
$Environment = $VMName.split('-')[2]
|
||||
|
||||
Get-AzSubscription | ForEach-Object {
|
||||
$Subscription = $_
|
||||
Set-AzContext $_ | Out-Null
|
||||
$search += Get-AzVM | Where-Object Name -EQ $VMName | Select-Object *, @{n = 'SubscriptionName'; e = { $Subscription.Name } }
|
||||
}
|
||||
}
|
||||
Process {
|
||||
If ($search.count -eq 1) {
|
||||
Set-AzContext $search.SubscriptionName
|
||||
$ResourceGroup = $search.ResourceGroupName.ToLower()
|
||||
$Location = (Get-AzResourceGroup -Name $ResourceGroup).Location
|
||||
$VM = Get-AzVM -Name $VMName -ResourceGroupName $ResourceGroup
|
||||
$Zone = $VM.Zones
|
||||
|
||||
|
||||
ForEach ($Size in $SizeGB) {
|
||||
$ExistingDisks = @($VM.StorageProfile.DataDisks | Select-Object *, @{n = 'ItdId'; e = { [int]($_.Name -replace "vm-$hostname-app-$environment-") } })
|
||||
|
||||
$NewDiskItdIdInt = ($ExistingDisks | Sort-Object ItdId -Descending | Select-Object -First 1).ItdId + 1
|
||||
$NewDiskItdIdStr = $NewDiskItdIdInt.ToString("000")
|
||||
$NewDiskName = "vm-$Hostname-app-$Environment-$NewDiskItdIdStr" #vm-itduc4p1-app-tst-001
|
||||
|
||||
$LunID = ($ExistingDisks | Sort-Object Lun -Descending | Select-Object -First 1).Lun + 1
|
||||
|
||||
$count = 0
|
||||
If ($ExistingDisks) {
|
||||
while ($Size -match $ExistingDisks.DiskSizeGB) {
|
||||
$count++
|
||||
Write-Warning "SizeGB: $Size, Count: $count"
|
||||
If ($count -ge 11) {
|
||||
Write-Error "Disk size not available" -ErrorAction Stop
|
||||
}
|
||||
Else {
|
||||
$Size = $Size - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning "SizeGB: $Size, Count: $count"
|
||||
|
||||
$AzureRmDiskConfigParams = @{
|
||||
DiskSizeGB = $Size
|
||||
Location = $Location
|
||||
CreateOption = "Empty"
|
||||
SkuName = "Premium_LRS"
|
||||
}
|
||||
|
||||
If ($Zone) {
|
||||
Write-Verbose "VM is located in Zone $Zone"
|
||||
$AzureRmDiskConfigParams += @{Zone = $Zone }
|
||||
}
|
||||
#$DiskConfig = New-AzureRmDiskConfig -DiskSizeGB $Size -Location $Location -CreateOption Empty -SkuName Premium_LRS
|
||||
$DiskConfig = New-AzDiskConfig @AzureRmDiskConfigParams
|
||||
|
||||
If (!(Get-AzDisk -ResourceGroupName $ResourceGroup -DiskName $NewDiskName -ErrorAction SilentlyContinue)) {
|
||||
$NewDisk = New-AzDisk -DiskName $NewDiskName -Disk $DiskConfig -ResourceGroupName $ResourceGroup
|
||||
|
||||
$VM = Add-AzVMDataDisk -Name $NewDiskName -CreateOption Attach -ManagedDiskId $NewDisk.Id -VM $VM -Lun $LunID -Caching ReadOnly
|
||||
Update-AzVM -VM $VM -ResourceGroupName $ResourceGroup -AsJob
|
||||
}
|
||||
}
|
||||
}
|
||||
Else {
|
||||
Write-Error "Search count invalid" -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
End {
|
||||
}
|
||||
}
|
||||
|
||||
$IaasAutoCred = Get-AutomationPSCredential -Name 'ITD Iaas Automation'
|
||||
|
||||
$IaasAutoCred = $IaaSAutoAz
|
||||
<#
|
||||
New-ITDAzureWindowsVMAA `
|
||||
-ComputerName itdbuilddba.nd.gov `
|
||||
-CPU 2 `
|
||||
-MemoryGB 8 `
|
||||
-Subnet '10.21.8.0/22'`
|
||||
-OS 'Windows Server 2019 Datacenter' `
|
||||
-Environment 'Test' `
|
||||
-AppName 'Infra-SoftDev-TFS' `
|
||||
-LicensingRestrictions 'No Licensing Restrictions' `
|
||||
-verbose
|
||||
#>
|
||||
|
||||
<#
|
||||
|
||||
$params = @{
|
||||
ComputerName = "itdpurshir1.nd.gov"
|
||||
CPU = 2;
|
||||
MemoryGB = 8;
|
||||
Subnet = '10.69.254.0/24';
|
||||
OS = 'Windows Server 2022 Datacenter';
|
||||
Environment = 'CARES-tst';
|
||||
AppName = 'ITD-POC-Purview';
|
||||
LicensingRestrictions = 'No Licensing Restrictions';
|
||||
Verbose = $true;
|
||||
}
|
||||
|
||||
New-ITDAzureWindowsVMAA @params
|
||||
#>
|
||||
$params = @{
|
||||
ComputerName = "itdsoscmtsql22.nd.gov"
|
||||
CPU = 4;
|
||||
MemoryGB = 16;
|
||||
Subnet = '10.21.8.0/22';
|
||||
OS = 'Windows Server 2022 Datacenter';
|
||||
Environment = 'Test';
|
||||
AppName = 'SOS-BLS';
|
||||
LicensingRestrictions = 'Microsoft SQL Standard';
|
||||
Verbose = $true;
|
||||
}
|
||||
|
||||
New-ITDAzureWindowsVMAA @params
|
||||
|
||||
|
||||
|
||||
#>
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
$RestMethodParams = @{
|
||||
Method = 'Post';
|
||||
Uri = 'https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=dVIj9zHSJwNeR2Ow8QTOoiSoKaPPux9EVJsQAMiGUPg%3d';
|
||||
Headers = @{ITD = 'mXJU74ABYyDHcVY6iJihPDk8LidJ2ibBA2sA3RAwKaBHS6Gw7Rr2Zz5JZAhPm6wMuvY7X54ZzJxAXaM7ig3PHG4MKvtkBf8X7q3jGNcePgUqg9WCwCSJ3JWG7AA6M39x4vpihKeZV'};
|
||||
Body = [PSCustomObject]@{
|
||||
ComputerName = 'itddhsharvestp1.nd.gov';
|
||||
CPU = 2;
|
||||
MemoryGB = 24;
|
||||
VlanId = 3822;
|
||||
OS = 'Windows Server 2022 Datacenter';
|
||||
Environment = 'Production';
|
||||
Datacenter = 'Bismarck';
|
||||
AppName = 'DHS-Orchard-Harvest';
|
||||
LicensingRestrictions = 'No Licensing Restrictions';
|
||||
} | ConvertTo-Json;
|
||||
}
|
||||
|
||||
Invoke-RestMethod @RestMethodParams | ConvertTo-Json
|
||||
+1102
File diff suppressed because it is too large
Load Diff
+1101
File diff suppressed because it is too large
Load Diff
+358
@@ -0,0 +1,358 @@
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object] $WebhookData
|
||||
)
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq '6EE8DaFMbswirY38qPfewwT82G9Bdiv8p3SKEdisX88mfnFfiredy6uti4nJprecedegJkTGBHDV3alpineePkM5grainsE56xp3JmuffWjwL') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$FQDN = 'itdzmbuild01.nd.gov'
|
||||
|
||||
# Get Credentials
|
||||
$SPCred = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
$ADCred = Get-AutomationPSCredential -Name 'ITD IaaS Automation'
|
||||
$PSCred = Get-AutomationPSCredential -Name 'ITD IaaS Automation'
|
||||
$IBCred = New-Object System.Management.Automation.PSCredential ($ADCred.UserName.split('\')[1], $ADCred.Password)
|
||||
$VMCred = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
|
||||
Clear-DnsClientCache
|
||||
$SharePointList = Get-ITDVMwareSharePointVMGuestListTst -Credential $SPCred
|
||||
$SPItem = $SharePointList | Where-Object Title -eq $FQDN
|
||||
$HostName = $FQDN.split('.')[0]
|
||||
|
||||
# Infoblox
|
||||
[Net.IpAddress]$NetworkId = $SPItem.CIDR.split('/')[0]
|
||||
[Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress
|
||||
$SubnetMaskInt = $SPItem.Cidr.split('/')[1]
|
||||
$Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2))
|
||||
[Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(),
|
||||
([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(),
|
||||
([math]::Truncate(($Int64 % 65536) / 256)).ToString(),
|
||||
([math]::Truncate($Int64 % 256)).ToString()
|
||||
$IPSplit = $SPItem.Cidr.Split('.')
|
||||
[Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($SPItem.Cidr.split('/')[0].split('.')[-1] -as [int]) + 1) )
|
||||
|
||||
If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) {
|
||||
Write-Verbose "IP Address and CIDR Block match"
|
||||
}
|
||||
Else {
|
||||
Write-Error "DNS record already exists, and does not match CIDR Block" -ErrorAction Stop
|
||||
}
|
||||
|
||||
If ($IpAddress) {
|
||||
If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) {
|
||||
Write-Warning "DNS record already exists, CIDR Block match"
|
||||
}
|
||||
else {
|
||||
Write-Error "DNS record already exists, and does not match CIDR Block"
|
||||
Break
|
||||
}
|
||||
}
|
||||
Else {
|
||||
New-ITDIbDNSRecordNextAvailableIP -HostName $SPItem.Title -CIDR $SPItem.CIDR -Credential $IBCred
|
||||
}
|
||||
|
||||
If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) {
|
||||
Write-Error "IP Address already in use." -ErrorAction Stop
|
||||
}
|
||||
|
||||
# Active Directory
|
||||
If ($PSEdition -eq 'Core') { Import-Module ActiveDirectory -UseWindowsPowerShell }
|
||||
$Filter = ("{Name -eq '" + $SPItem.AppName + "'}")
|
||||
$OUAppName = Get-ADOrganizationalUnit -SearchBase "OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD,dc=nd,dc=gov" -Filter $Filter
|
||||
If (!($OUAppName)) {
|
||||
$OUAppName = Get-ADOrganizationalUnit -SearchBase "OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD,dc=nd,dc=gov" -Filter { Name -eq 'All-General' }
|
||||
}
|
||||
$ExistingADComputer = Get-ADComputer -Identity $Hostname -ErrorAction SilentlyContinue
|
||||
If ($ExistingADComputer) {
|
||||
If ($ExistingADComputer.DistinguishedName -like ("*" + $SPItem.AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") {
|
||||
Write-Warning "AD object already exists, OU path does match"
|
||||
}
|
||||
Else {
|
||||
Write-Error "AD object already exists, OU path mismatch"
|
||||
Exit
|
||||
Exit
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch ($SPItem.Environment) {
|
||||
'Test' {
|
||||
$OUAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -like "*Test*"
|
||||
}
|
||||
'Production' {
|
||||
$OUAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -like "*Prod*"
|
||||
}
|
||||
}
|
||||
If ($OUAppNameEnv) { $OUFinal = $OUAppNameEnv }
|
||||
Else { $OUFinal = $OUAppName }
|
||||
|
||||
New-ADComputer -Name $HostName.ToUpper() -Path $OUFinal -Credential $ADCred -Description ($SPItem | Select-Object AppName, Environment | ConvertTo-Json)
|
||||
}
|
||||
|
||||
# Passwordstate
|
||||
$LocalCredential = New-ITDPassword -Title $FQDN -Username itdadmin -Description 'Local Administrator' -PasswordList CSRC -Credential $PrvCred
|
||||
$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ($LocalCredential.UserName, ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
|
||||
# VMware
|
||||
If (Get-VM -Name $FQDN -ErrorAction SilentlyContinue) {
|
||||
Write-Error "Virtual machine with the name $FQDN already exists." -ErrorAction Stop
|
||||
Stop
|
||||
Stop
|
||||
}
|
||||
|
||||
switch ($SPItem.Cluster) {
|
||||
"WINDOWS1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"WINDOWS2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"SQL1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data"
|
||||
$DiskStorageFormat = 'EagerZeroedThick'
|
||||
}
|
||||
"SQL2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data"
|
||||
$DiskStorageFormat = 'EagerZeroedThick'
|
||||
}
|
||||
"WAS1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"WAS2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"PS1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-PS1-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"PS2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-PS2-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"TEL1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL1-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"TEL2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL2-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"DCN1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-DCN-vMotion-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
}
|
||||
|
||||
# verify disk will fit
|
||||
$DiskTotal = $SPItem.Disk1 + $SPItem.Disk2 + $SPItem.Disk3
|
||||
$DatastoreCluster = Get-DatastoreCluster | Where-Object Name -like ("*" + $SPItem.Cluster + "*")
|
||||
$ClusterDatastoreWithHighestFreeSpaceGB = ($DatastoreCluster | Get-Datastore | Sort-Object FreeSpaceGB -Descending | Select -First 1)
|
||||
If ($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB -gt $DiskTotal) {
|
||||
Write-Verbose ("VM DiskTotal " + $DiskTotal + "GB, will fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)")
|
||||
}
|
||||
else {
|
||||
Write-Verbose ("VM DiskTotal " + $DiskTotal + "GB, will not fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)")
|
||||
Write-Error ("New VM " + $FQDN + " needs " + $DiskTotal + "GB of free space on a single datastore in the " + $DatastoreCluster.Name + " datastore cluster.") -ErrorAction Stop
|
||||
}
|
||||
|
||||
|
||||
$FolderLocation = Get-Folder -Server $ViServer -Name "_New Builds"
|
||||
|
||||
switch ($SPItem.OS) {
|
||||
"Windows Server 2012R2 Standard (64-Bit)" { $Template = "Windows Server 2012R2 Standard" }
|
||||
"Windows Server 2016 Standard (64-Bit)" { $Template = "Windows Server 2016 Standard" }
|
||||
"Windows Server 2019 Standard (64-Bit)" { $Template = "Windows Server 2019 Standard" }
|
||||
Default {}
|
||||
}
|
||||
|
||||
$PortGroupsAvailable = Get-VDPortGroup -Server $ViServer -VDSwitch $VirtualSwitch
|
||||
$PortGroup = $PortGroupsAvailable | Where-Object Name -eq ("dvPG_" + $SPItem.Vlan_Id + "_" + $NetworkId.IPAddressToString + "_" + $SubnetMaskInt)
|
||||
If (!($PortGroup)) {
|
||||
Write-Error "Virtual port group not found" -ErrorAction Stop
|
||||
Stop
|
||||
}
|
||||
|
||||
$NewOSSpecName = ("AutoBuild-$Hostname-" + (Get-Date -UFormat "%Y%m%d%H%M%S"))
|
||||
Get-OSCustomizationSpec -Name "Windows (Auto)" -Server $ViServer | New-OSCustomizationSpec -Name $NewOSSpecName -Type Persistent
|
||||
|
||||
Get-OSCustomizationSpec -Name $NewOSSpecName | `
|
||||
Set-OSCustomizationSpec `
|
||||
-NamingScheme fixed `
|
||||
-NamingPrefix $Hostname `
|
||||
-AdminPassword $GuestCredentialBB.GetNetworkCredential().Password `
|
||||
|
||||
Get-OSCustomizationSpec -Name $NewOSSpecName | `
|
||||
Get-OSCustomizationNicMapping | `
|
||||
Set-OSCustomizationNicMapping `
|
||||
-IpMode UseStaticIP `
|
||||
-IpAddress $IpAddress.IPAddressToString `
|
||||
-SubnetMask $SubnetMask.IPAddressToString `
|
||||
-DefaultGateway $DefaultGateway.IPAddressToString `
|
||||
-Dns "10.2.7.40", "10.2.5.40"
|
||||
|
||||
$OSSpec = Get-OSCustomizationSpec -Name $NewOSSpecName
|
||||
|
||||
$NewVMParams = @{
|
||||
Name = $FQDN;
|
||||
ResourcePool = $SPItem.Cluster;
|
||||
Datastore = $DatastoreCluster;
|
||||
DiskStorageFormat = $DiskStorageFormat;
|
||||
Template = $Template;
|
||||
Location = $FolderLocation;
|
||||
OSCustomizationSpec = $OSSpec;
|
||||
}
|
||||
|
||||
New-VM @NewVMParams
|
||||
|
||||
#If (!($BuildError)) {
|
||||
$VM = Get-VM -Name $FQDN
|
||||
|
||||
# Ensure CPU/Memory Hot-Add Enabled
|
||||
$vmView = $VM | Get-View
|
||||
$vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
|
||||
$vmOptValCPU = New-Object VMware.Vim.OptionValue
|
||||
$vmOptValMem = New-Object VMware.Vim.OptionValue
|
||||
$vmOptValCPU.Key = "vcpu.hotadd"
|
||||
$vmOptValMem.Key = "mem.hotadd"
|
||||
$vmOptValCPU.Value = "true"
|
||||
$vmOptValMem.Value = "true"
|
||||
$vmConfigSpec.ExtraConfig += $vmOptValCPU
|
||||
$vmConfigSpec.ExtraConfig += $vmOptValMem
|
||||
$vmView.ReconfigVM($vmConfigSpec)
|
||||
|
||||
# Set CPU, Memory, Network
|
||||
$VM | Set-VM -NumCpu $SPItem.Processors -MemoryGB $SPItem.RAM -Confirm:$false
|
||||
$VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $PortGroup -Confirm:$false
|
||||
|
||||
# Power On VM
|
||||
$VM | Start-VM
|
||||
|
||||
# Wait for Customization to finish
|
||||
$VMStarted = $false
|
||||
$VMCustomizationStarted = $false
|
||||
$VMCustomizationResult = $false
|
||||
|
||||
While ($VMStarted -eq $false -or $VMCustomizationStarted -eq $false -or $VMCustomizationResult -eq $false) {
|
||||
Write-Warning ("Customization wait loop started " + (Get-Date))
|
||||
Write-Verbose "Current Status:"
|
||||
Write-Verbose ("VMStarted: " + $VMStarted)
|
||||
Write-Verbose ("VMCustomizationStarted: " + $VMCustomizationStarted)
|
||||
Write-Verbose ("VMCustomizationResult: " + $VMCustomizationResult)
|
||||
$GetVIEventRuntime = Measure-Command -Expression { $VMEvents = Get-VIEvent -Entity $VM -Server $ViServer -ErrorAction SilentlyContinue }
|
||||
Write-Verbose ("Get-VIEvent last run time: " + $GetVIEventRuntime.TotalSeconds + " seconds")
|
||||
If ($VMStarted -eq $false) {
|
||||
If (@($VMEvents | Where-Object { $_.GetType().Name -eq "VMStartingEvent" })) {
|
||||
$VMStarted = $true
|
||||
Write-Warning "[$FQDN]:Virtual machine started"
|
||||
}
|
||||
}
|
||||
If ($VMCustomizationStarted -eq $false) {
|
||||
If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationStartedEvent" })) {
|
||||
$VMCustomizationStarted = $true
|
||||
Write-Warning "[$FQDN]:Virtual machine customization started"
|
||||
}
|
||||
}
|
||||
If ($VMCustomizationResult -eq $false) {
|
||||
If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationFailed" })) {
|
||||
$VMCustomizationResult = $true
|
||||
Write-Error "[$FQDN]:Virtual machine customization failed"
|
||||
Exit
|
||||
Exit
|
||||
}
|
||||
If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationSucceeded" })) {
|
||||
$VMCustomizationResult = $true
|
||||
Write-Warning "[$FQDN]:Virtual machine customization completed"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Delete OS Customization Spec
|
||||
Get-OSCustomizationSpec -Name $NewOSSpecName | Remove-OSCustomizationSpec -Confirm:$false
|
||||
|
||||
# Add/Expand Disks
|
||||
$VMDisk = $VM | Get-HardDisk
|
||||
$VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1"
|
||||
$VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2"
|
||||
$VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3"
|
||||
|
||||
If ($SPItem.Disk1) {
|
||||
If (!$VMDisk1) {
|
||||
$VM | New-HardDisk `
|
||||
-CapacityGB $SPItem.Disk1 `
|
||||
-StorageFormat Thin `
|
||||
-DiskType Flat `
|
||||
-Persistence Persistent
|
||||
}
|
||||
$VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1"
|
||||
If ($VMDisk1.CapacityGB -lt $SPItem.Disk1) {
|
||||
Set-HardDisk -HardDisk $VMDisk1 -CapacityGB $SPItem.Disk1 -Confirm:$false
|
||||
}
|
||||
}
|
||||
|
||||
If ($SPItem.Disk2) {
|
||||
If (!$VMDisk2) {
|
||||
$VM | New-HardDisk `
|
||||
-CapacityGB $SPItem.Disk2 `
|
||||
-StorageFormat Thin `
|
||||
-DiskType Flat `
|
||||
-Persistence Persistent
|
||||
}
|
||||
$VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2"
|
||||
If ($VMDisk2.CapacityGB -lt $SPItem.Disk2) {
|
||||
Set-HardDisk -HardDisk $VMDisk2 -CapacityGB $SPItem.Disk2 -Confirm:$false
|
||||
}
|
||||
}
|
||||
|
||||
If ($SPItem.Disk3) {
|
||||
If (!$VMDisk3) {
|
||||
$VM | New-HardDisk `
|
||||
-CapacityGB $SPItem.Disk3 `
|
||||
-StorageFormat Thin `
|
||||
-DiskType Flat `
|
||||
-Persistence Persistent
|
||||
}
|
||||
$VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3"
|
||||
If ($VMDisk3.CapacityGB -lt $SPItem.Disk3) {
|
||||
Set-HardDisk -HardDisk $VMDisk3 -CapacityGB $SPItem.Disk3 -Confirm:$false
|
||||
}
|
||||
}
|
||||
|
||||
# Run Guest OS code
|
||||
|
||||
$InvokeVMScriptFunc = {
|
||||
|
||||
}
|
||||
|
||||
$VM | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptText $InvokeVMScriptFunc
|
||||
#}
|
||||
}
|
||||
|
||||
Else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
"target_platform","target_hostname","target_cpus","target_memory","target_osdisk","target_datadisk","target_subnet","target_os","target_environment","target_vm_app_name","target_datacenter","target_licensingrestrictions"
|
||||
"VMware","itdzmtest110.nd.gov","1","4","50","20","10.11.12.0/23","Windows Server 2022 Datacenter","Production","ITD-POC-zmeier","Bismarck","No Licensing Restrictions"
|
||||
|
+64
@@ -0,0 +1,64 @@
|
||||
$DriveLetter = 'D'
|
||||
$CsvPath = ($DriveLetter + ":\AutoBuildInputFiles\")
|
||||
$FailedPath = ($DriveLetter + ":\AutoBuildInputFiles\Failed")
|
||||
$CompletedPath = ($DriveLetter + ":\AutoBuildInputFiles\Completed")
|
||||
|
||||
$GetBuildFile = Get-ChildItem -Path $CsvPath -Filter *.csv | Sort-Object LastWriteTime | select -First 1
|
||||
|
||||
#$IaasAutoCred = Get-AutomationPSCredential -Name 'ITD Iaas Automation'
|
||||
$IaasAutoCred = $PrvCred
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false -InvalidCertificateAction Ignore
|
||||
|
||||
$InputParams = Import-Csv -Path $GetBuildFile.FullName
|
||||
|
||||
$ComputerName = $InputParams.target_hostname.ToLower()
|
||||
Send-MailMessage -From "zmauto@nd.gov" -To "zmeier@nd.gov" -SmtpServer apprelay1.nd.gov -Body $InputParams -Subject ("AutoBuildFromFile-$ComputerName-" + $InputParams.target_platform)
|
||||
|
||||
try {
|
||||
switch ($InputParams.target_platform) {
|
||||
'azure' {
|
||||
|
||||
}
|
||||
'vmware' {
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $IaasAutoCred
|
||||
|
||||
New-ITDVMwareWindowsVM -ComputerName $ComputerName `
|
||||
-CPU $InputParams.target_cpus `
|
||||
-MemoryGB $InputParams.target_memory `
|
||||
-DiskOS $InputParams.target_osdisk `
|
||||
-DiskData $InputParams.target_datadisk `
|
||||
-Subnet $InputParams.target_subnet `
|
||||
-OS $InputParams.target_os `
|
||||
-Environment $InputParams.target_environment `
|
||||
-Datacenter $InputParams.target_datacenter `
|
||||
-AppName $InputParams.target_vm_app_name `
|
||||
-LicensingRestrictions $InputParams.target_licensingrestrictions `
|
||||
-Credential $IaasAutoCred `
|
||||
-Verbose
|
||||
|
||||
Move-Item -Path $GetBuildFile.FullName -Destination $CompletedPath
|
||||
|
||||
$postParams = [PSCustomObject]@{
|
||||
AutomationName = "Infra-VMware";
|
||||
Action = 'Provisioning';
|
||||
Units = 240;
|
||||
Platform = 'PowerShell-VMware-VMWindows';
|
||||
}
|
||||
|
||||
Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
$error[0]
|
||||
Write-Warning "Email vmware admins about failure"
|
||||
$Body = $error[0] | Select-Object *
|
||||
Send-MailMessage -From autobuild@nd.gov -To "zmeier@nd.gov" -Subject "Failure-AutoBuildFromFile-$ComputerName" -SmtpServer apprelay.nd.gov -Body $Body
|
||||
|
||||
Write-Warning "Error detected. Moving csv input file to folder Failed"
|
||||
Move-Item -Path $GetBuildFile.FullName -Destination $FailedPath
|
||||
}
|
||||
|
||||
Disconnect-VIServer -Server * -Confirm:$false -ErrorAction SilentlyContinue
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
$RestMethodParams = @{
|
||||
Method = 'Post';
|
||||
Uri = 'https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=4cWZz%2fq97AqMdlNak6qv2lUurLPFsWmPJmovLmAE%2fNg%3d';
|
||||
Headers = @{ITD = 'mXJU74ABYyDHcVY6iJihPDk8LidJ2ibBA2sA3RAwKaBHS6Gw7Rr2Zz5JZAhPm6wMuvY7X54ZzJxAXaM7ig3PHG4MKvtkBf8X7q3jGNcePgUqg9WCwCSJ3JWG7AA6M39x4vpihKeZV' };
|
||||
Body = [PSCustomObject]@{
|
||||
target_platform = "VMware"
|
||||
target_hostname = 'itdcndsperms.nd.gov';
|
||||
target_cpus = 1;
|
||||
target_memory = 8;
|
||||
target_osdisk = 100;
|
||||
target_datadisk = 20; # this is now swap
|
||||
target_subnet = '10.221.8.0/28';
|
||||
target_os = 'Windows Server 2019 Datacenter';
|
||||
target_environment = 'Production';
|
||||
target_vm_app_name = 'Shared-PeopleSoft-State';
|
||||
target_datacenter = 'Bismarck';
|
||||
target_licensingrestrictions = 'No Licensing Restrictions';
|
||||
} | ConvertTo-Json;
|
||||
}
|
||||
|
||||
Invoke-RestMethod @RestMethodParams
|
||||
|
||||
$VMNames=@"
|
||||
itdcndhftdb22.nd.gov
|
||||
itdcndhhtdb22.nd.gov
|
||||
"@
|
||||
$VMNames = ConvertTo-Array -MultiLineString $VMNames
|
||||
|
||||
Invoke-Command -ComputerName $VMNames -Credential $PrvCred -ScriptBlock {
|
||||
Get-Process -Name ccmexec*,cohesity*,cortex*,nessus*,vmtoolsd*
|
||||
} | sort-object PSComputerName
|
||||
+1131
File diff suppressed because it is too large
Load Diff
+23
@@ -0,0 +1,23 @@
|
||||
#https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=4cWZz%2fq97AqMdlNak6qv2lUurLPFsWmPJmovLmAE%2fNg%3d
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object] $WebhookData
|
||||
)
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'mXJU74ABYyDHcVY6iJihPDk8LidJ2ibBA2sA3RAwKaBHS6Gw7Rr2Zz5JZAhPm6wMuvY7X54ZzJxAXaM7ig3PHG4MKvtkBf8X7q3jGNcePgUqg9WCwCSJ3JWG7AA6M39x4vpihKeZV') {
|
||||
Write-Verbose "Header has required data"
|
||||
Write-Host $
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$ComputerName = $InputParams.target_hostname.ToLower()
|
||||
$TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
$InputParams | Export-Csv "E:\AutoBuildInputFiles\$ComputerName-$Timestamp.csv"
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object]
|
||||
$WebhookData
|
||||
)
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'PJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5svBxbnq2g9M7cQJtFN3iGU4kD4p') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$VMName = $InputParams.HostName
|
||||
$Id = $InputParams.Id
|
||||
$Duration = $InputParams.Duration
|
||||
|
||||
$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | select -first 1).Name }
|
||||
|
||||
switch ($Duration) {
|
||||
{$Duration -ge 1 -and $Duration -le 7}
|
||||
{
|
||||
Write-Verbose "Duration = Snapshot"
|
||||
$VMSnapshots = $VM | Get-Snapshot | where-object Description -like "AutoSnap_$Id*"
|
||||
|
||||
If (@($VMSnapshots).count -eq 1) {
|
||||
Write-Verbose "Exactly one snapshot match found"
|
||||
$Taken = $true
|
||||
$VMSnapshot = $VMSnapshots
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoSnap_$Id*")
|
||||
}
|
||||
else {
|
||||
if (@($VMSnapshots | where-object Description -like "AutoSnap_$Id*").count -gt 1) {
|
||||
Write-Error "More than one snapshot match found, abort"
|
||||
Exit
|
||||
}
|
||||
else { Write-Verbose "Snapshot Id #$Id match not found on $VMName" }
|
||||
}
|
||||
}
|
||||
{$Duration -ge 8}
|
||||
{
|
||||
Write-Verbose "Duration = Clone"
|
||||
$VMClones = Get-VM | Where-Object Name -eq ($VMName + "_AutoClone_" + $Id)
|
||||
|
||||
If (@($VMClones).count -eq 1) {
|
||||
Write-Verbose "Exactly one clone match found"
|
||||
$Taken = $true
|
||||
$VMClone = $VMClones
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoClone_$Id*")
|
||||
}
|
||||
else {
|
||||
if (@($VMClones).count -gt 1) {
|
||||
Write-Error "More than one VM clone match found, abort"
|
||||
Exit
|
||||
}
|
||||
else { Write-Verbose "Clone Id #$Id match not found for $VMName" }
|
||||
}
|
||||
}
|
||||
Default {
|
||||
Write-Error "Duration less than zero."
|
||||
}
|
||||
}
|
||||
|
||||
If ($Taken -eq $true) {
|
||||
write-verbose "Updating SharePoint fields named Status and SnapshotTaken"
|
||||
$UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one record, stopping"; break }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Taken';
|
||||
SnapshotTaken = $Task.PrevRunTime;
|
||||
AutoExpire = ($Task.Description -split '[\r\n]+')[1].split('_')[1];
|
||||
AutoDelete = ($Task.Description -split '[\r\n]+')[2].split('_')[1];
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
Disconnect-VIServer * -Confirm:$false -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
# 2021 https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=EHlEzPMvDt02gdqMb9wlkdt1FrbmlZjbfQpFTtoIrBc%3d
|
||||
# content-type application/x-www-form-urlencoded
|
||||
# 2022 https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=%2b6PP2%2bd3FDLqb4bgMs%2b4V1%2bDAMw0tPxN%2f4Ee0eWMa5Q%3d
|
||||
#
|
||||
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object] $WebhookData
|
||||
)
|
||||
|
||||
function Get-ITDVMwareSharePointSnapshotRequestList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL
|
||||
Method = "Get"
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'VRLEq2Yi7yzWW8fpKNCPB5gUcnHfr9sdhXC53y7gWf5BDtHAKpueFYU4L3N9ZxCWy63znqPGh3AJ2bn43uP7GjzfLcgqYLQRkirMXTKqtHssnNGBrew3gxXkr3mZA3NV7DszpR3kjiLgi3FpRPgUWus') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
|
||||
$UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,NotifyEmail&$expand=Author/Id'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$SPListItem = $ListItems | Where-object Id -eq $InputParams.Id
|
||||
If ($SPListItem.Title -ne $InputParams.HostName) {
|
||||
Write-Error ("Web request JSON does not match SharePoint Record for SPListItem.Hostname " + $SPListItem.HostName + " and InputParams.Hostname " + $InputParams.Hostname)
|
||||
Exit
|
||||
}
|
||||
|
||||
$VMName = $InputParams.HostName
|
||||
$SnapTime = [DateTime]$SPListItem.DateTime
|
||||
|
||||
$NotifyEmail = $SPListItem.Author.Email
|
||||
If ($SPListItem.NotifyEmail) { $NotifyEmail = $NotifyEmail + ',' + $SPListItem.NotifyEmail }
|
||||
|
||||
$tryCount = 0
|
||||
#while ($tryCount -lt 5) {
|
||||
try {
|
||||
$tryCount++
|
||||
|
||||
|
||||
|
||||
$SnapName = "AutoSnap_" + $SPListItem.ID
|
||||
$SnapExpireDateTime = $SnapTime.AddDays($SPListItem.Duration)
|
||||
If ($SnapExpireDateTime.DayOfWeek -eq "Saturday" -or $SnapExpireDateTime.DayOfWeek -eq "Sunday") {
|
||||
$SnapExpireDateTime = $SnapExpireDateTime.AddDays(2)
|
||||
}
|
||||
$SnapDeleteDateTime = $SnapExpireDateTime.AddDays(2)
|
||||
|
||||
$SnapDescription = "AutoSnap_" + $InputParams.ID + "`r" + "AutoExpire_$SnapExpireDateTime" + "`r" + "AutoDelete_$SnapDeleteDateTime"
|
||||
$SnapDescription = "AutoSnap_" + 1080 + "`r" + "AutoExpire_$SnapExpireDateTime" + "`r" + "AutoDelete_$SnapDeleteDateTime"
|
||||
$snapMemory = $false
|
||||
$snapQuiesce = $false
|
||||
|
||||
Write-Warning $VMName
|
||||
Write-Warning $SnapName
|
||||
Write-Warning ("SharePoint: " + $SnapTime)
|
||||
If ($SnapTime -lt (Get-Date)) {
|
||||
$SnapTime = (Get-Date).AddSeconds(30)
|
||||
}
|
||||
Write-Warning ("PowerShell: " + $SnapTime)
|
||||
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | Select-Object -First 1).Name }
|
||||
$VIServer = $VM.Uid.split('@')[1].split(':')[0]
|
||||
|
||||
$si = Get-View ServiceInstance -Server $VIServer
|
||||
$scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager -Server $VIServer
|
||||
|
||||
$spec = New-Object VMware.Vim.ScheduledTaskSpec
|
||||
$spec.Name = $SnapName, $VMname -join '_'
|
||||
$spec.Description = "$SnapDescription"
|
||||
$spec.Enabled = $true
|
||||
$spec.Notification = $NotifyEmail
|
||||
|
||||
$spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler
|
||||
$spec.Scheduler.runat = $SnapTime
|
||||
|
||||
$spec.Action = New-Object VMware.Vim.MethodAction
|
||||
$spec.Action.Name = "CreateSnapshot_Task"
|
||||
|
||||
@($SnapName, $SnapDescription, $SnapMemory, $SnapQuiesce) | ForEach-Object {
|
||||
$arg = New-Object VMware.Vim.MethodActionArgument
|
||||
$arg.Value = $_
|
||||
$spec.Action.Argument += $arg
|
||||
}
|
||||
|
||||
# prep for update SharePoint record status
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one result, stopping"; Exit }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $SharePointCredential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
# Create vCenter scheduled task
|
||||
$scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)
|
||||
Start-Sleep -Seconds 3
|
||||
}<#
|
||||
catch [System.Management.Automation.MethodInvocationException] {
|
||||
If ($tryCount -lt 4) {
|
||||
If ($Error[1].Exception -like "*You have attempted to schedule the scheduler at a time*in the past*") {
|
||||
Write-Warning ((Get-Date))# + ": Attempted schedule in past @ $SnapTime, trying again")
|
||||
}
|
||||
write-warning $trycount
|
||||
}
|
||||
Else {
|
||||
write-error "vCenter Snapshot Scheduled Task Creation failed"
|
||||
write-error $error[1]
|
||||
Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov
|
||||
$Status = "Errored"
|
||||
exit
|
||||
}
|
||||
}#>
|
||||
catch {
|
||||
write-error "vCenter Snapshot Scheduled Task Creation failed default message"
|
||||
write-error $error[1]
|
||||
Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed Default Message - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov
|
||||
$Status = "Errored"
|
||||
exit
|
||||
}
|
||||
#}
|
||||
|
||||
# update SharePoint record status
|
||||
If ($Status -ne "Errored") { $Status = "Scheduled" }
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = $Status;
|
||||
}
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
$postParams = [PSCustomObject]@{
|
||||
AutomationName = "Infra-VMware";
|
||||
Action = 'Provisioning';
|
||||
Units = 5;
|
||||
Platform = 'PowerShell-VMware-SnapshotNew';
|
||||
}
|
||||
Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json)
|
||||
|
||||
Disconnect-VIServer -Server * -Confirm:$false -ErrorAction SilentlyContinue
|
||||
}
|
||||
Else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
|
||||
)
|
||||
$StartTime = Get-Date
|
||||
function Get-ITDVMwareSharePointSnapshotRequestList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail,AutoExpire,AutoDelete&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList -Credential $SharePointCredential
|
||||
$ListToRemove = $SnapshotList | Where-Object { $_.Status -eq "Expired, Delete Approved" } | Sort-Object AutoDelete
|
||||
|
||||
ForEach ($SPRecord in $ListToRemove) {
|
||||
$Id = $null
|
||||
$VMName = $null
|
||||
$SnapName = $null
|
||||
|
||||
$Id = $SPRecord.ID
|
||||
$VMName = $SPRecord.Title
|
||||
$SnapName = "AutoSnap_" + $Id
|
||||
|
||||
$SnapshotToRemove = Get-Snapshot -Name $SnapName -VM $VMName
|
||||
$Datastore = Get-VM $VMName | Get-Datastore
|
||||
$ViServer = $SnapshotToRemove.uid.split('@')[1].split(':')[0]
|
||||
|
||||
Write-Warning ($SnapshotToRemove.Name + " for " + $SnapshotToRemove.VM + " on " + $Datastore + " on " + $ViServer)
|
||||
|
||||
try {
|
||||
$SnapshotTaskCount = @(Get-Task -Server $ViServer | Where-Object { $_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running" }).count
|
||||
Write-Warning $SnapshotTaskCount
|
||||
while ($SnapshotTaskCount -ge 1) {
|
||||
$timestamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, pausing 60 seconds."
|
||||
Start-Sleep -Seconds 60
|
||||
|
||||
$timestamp = $null
|
||||
$SnapshotTaskCount = @(Get-Task | Where-Object { $_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running" }).count
|
||||
Write-Warning $SnapshotTaskCount
|
||||
}
|
||||
$timestamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, starting removal."
|
||||
$SnapshotToRemove | Remove-Snapshot -Confirm:$false
|
||||
}
|
||||
catch {
|
||||
Write-Error "Snapshot Removal failed";
|
||||
Write-Error $Error[1];
|
||||
exit
|
||||
}
|
||||
|
||||
#update SharePoint field
|
||||
Write-Verbose "Exactly one match found, updating SharePoint fields named Status and SnapshotTaken"
|
||||
$UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($Id)"
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Removed';
|
||||
SnapshotRemoved = [datetime](Get-Date);
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
}
|
||||
Disconnect-VIServer -Server * -Confirm:$false -ErrorAction SilentlyContinue
|
||||
|
||||
$DiffTime = [math]::round((4+((Get-Date) - $StartTime).Minutes),0)
|
||||
$postParams = [PSCustomObject]@{
|
||||
AutomationName = "Infra-VMware";
|
||||
Action = 'Deprovisioning';
|
||||
Units = $DiffTime;
|
||||
Platform = 'PowerShell-VMware-SnapshotRemove';
|
||||
}
|
||||
Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json)
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object]
|
||||
$WebhookData
|
||||
)
|
||||
|
||||
function Get-ITDVMwareSharePointSnapshotRequestList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail,AutoExpire,AutoDelete&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList -Credential $SharePointCredential
|
||||
$ListToUpdate = $SnapshotList | where-object { $_.Status -eq "Scheduled" } | Sort-Object DateTime
|
||||
|
||||
#$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
#If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | select -first 1).Name }
|
||||
|
||||
ForEach($SPRecord in $ListToUpdate)
|
||||
{
|
||||
$VM = $null
|
||||
$Taken = $null
|
||||
$VMName = $null
|
||||
$Duration = $null
|
||||
$Id = $null
|
||||
$VMSnapshot = $null
|
||||
$Task = $null
|
||||
|
||||
If( (($SPRecord.DateTime) -as [datetime]).ToLocalTime() -lt (Get-Date) ) # If datetime has passed
|
||||
{
|
||||
$VMName = $SPRecord.Title
|
||||
$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
$Duration = $SPRecord.Duration
|
||||
$Id = $SPRecord.Id
|
||||
|
||||
switch ($Duration) {
|
||||
{$Duration -ge 1 -and $Duration -le 7}
|
||||
{
|
||||
Write-Verbose "Duration = Snapshot"
|
||||
$VMSnapshots = $VM | Get-Snapshot | where-object Description -like "AutoSnap_$Id*"
|
||||
|
||||
If (@($VMSnapshots).count -eq 1) {
|
||||
Write-Verbose "Exactly one snapshot match found"
|
||||
$Taken = $true
|
||||
$VMSnapshot = $VMSnapshots
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoSnap_$Id*")
|
||||
}
|
||||
else {
|
||||
if (@($VMSnapshots).count -gt 1) {
|
||||
Write-Error "More than one snapshot match found, abort"
|
||||
Exit
|
||||
}
|
||||
else {
|
||||
$Taken = $false
|
||||
Write-Verbose "Snapshot Id #$Id match not found on $VMName"
|
||||
Write-Error "Snapshot $Id for $VMName not found."
|
||||
}
|
||||
}
|
||||
}
|
||||
{$Duration -ge 8}
|
||||
{
|
||||
Write-Verbose "Duration = Clone"
|
||||
$VMClones = Get-VM | Where-Object Name -eq ($VMName + "_AutoClone_" + $Id)
|
||||
|
||||
If (@($VMClones).count -eq 1) {
|
||||
Write-Verbose "Exactly one clone match found"
|
||||
$Taken = $true
|
||||
$VMClone = $VMClones
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoClone_$Id*")
|
||||
}
|
||||
else {
|
||||
if (@($VMClones).count -gt 1) {
|
||||
Write-Error "More than one VM clone match found, abort"
|
||||
Exit
|
||||
}
|
||||
else {
|
||||
$Taken = $false
|
||||
Write-Verbose "Clone Id #$Id match not found for $VMName"
|
||||
Write-Error "Clone $Id for $VMName not found."
|
||||
}
|
||||
}
|
||||
}
|
||||
Default {
|
||||
Write-Error "Duration less than zero."
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
write-verbose "Updating SharePoint fields named Status and SnapshotTaken"
|
||||
$UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($Id)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
#Status = 'Taken';
|
||||
Status = If ($Taken -eq $true) {'Taken'} Else {'Errored'};
|
||||
SnapshotTaken = $Task.PrevRunTime;
|
||||
AutoExpire = ($Task.Description -split '[\r\n]+')[1].split('_')[1];
|
||||
AutoDelete = ($Task.Description -split '[\r\n]+')[2].split('_')[1];
|
||||
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
}
|
||||
}
|
||||
|
||||
$postParams = [PSCustomObject]@{
|
||||
AutomationName = "Infra-VMware";
|
||||
Action = 'Provisioning';
|
||||
Units = 1;
|
||||
Platform = 'PowerShell-VMware-SnapshotUpdateStatus';
|
||||
}
|
||||
Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json)
|
||||
|
||||
Disconnect-VIServer * -Confirm:$false -ErrorAction SilentlyContinue
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
[
|
||||
{
|
||||
"Id": "575",
|
||||
"Hostname":"itdfmauditp1.nd.gov"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"WebhookName": "rh-VMware-UpdateVMSnapshotStatus-prd",
|
||||
"RequestBody": "[\n {\n \"Id\": \"68\",\n \"HostName\": \"itddeqappt1.nd.gov\",\n \"DateTime\": \"2/5/2020 7:00 PM\",\n \"Duration\": \"8\",\n \"NotifyEmail\": \"\"\n }\n]",
|
||||
"RequestHeader": {
|
||||
"Connection": "Close",
|
||||
"Expect": "100-continue",
|
||||
"Host": "s25events.azure-automation.net",
|
||||
"ITD": "PJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5svBxbnq2g9M7cQJtFN3iGU4kD4p",
|
||||
"x-ms-request-id": "5ee3253c-5bb4-4aea-a950-6149ddb0436e"
|
||||
}
|
||||
}
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object] $WebhookData
|
||||
)
|
||||
|
||||
function Get-ITDVMwareSharePointSnapshotRequestList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://testshare.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'w3gVRLEq2Yi7yzWW8fpKNCPTKqtHssnNGBref5BDtxXkr3mZA3NB5gUcnHfr9sdhXC53y7gWHAKpueFYU4L3NMXV7DszCWy63znqPGh3AJ2bn43uP7GjzfLcgqYLQRkirpR3kjiLgi3FpRPgUWus9Zx') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$Id = $InputParams.Id
|
||||
$VMName = $InputParams.Hostname
|
||||
|
||||
$SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList -Credential $SharePointCredential
|
||||
$Request = $SnapshotList | where-object ID -eq $id
|
||||
$SnapName = "AutoSnap_" + $Id
|
||||
|
||||
$SnapshotToRemove = Get-Snapshot -Name $SnapName -VM $VMName
|
||||
$Datastore = Get-VM $VMName | Get-Datastore
|
||||
$ViServer = $SnapshotToRemove.uid.split('@')[1].split(':')[0]
|
||||
|
||||
write-warning ($SnapshotToRemove.Name + " for " + $SnapshotToRemove.VM + " on " + $Datastore + " on " + $ViServer)
|
||||
|
||||
|
||||
#try {
|
||||
$SnapshotTaskCount = @(Get-Task -Server $ViServer | Where-Object {$_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running"}).count
|
||||
write-warning $SnapshotTaskCount
|
||||
while ($SnapshotTaskCount -ge 1) {
|
||||
$timestamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, pausing 60 seconds."
|
||||
Start-Sleep -Seconds 60
|
||||
|
||||
$timestamp = $null
|
||||
$SnapshotTaskCount = @(Get-Task | Where-Object {$_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running"}).count
|
||||
write-warning $SnapshotTaskCount
|
||||
}
|
||||
$timestamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, starting removal."
|
||||
$SnapshotToRemove | Remove-Snapshot -Confirm:$false -RunAsync
|
||||
<#}
|
||||
catch {
|
||||
Write-Error "Snapshot Removal failed";
|
||||
Write-Error $Error[1];
|
||||
exit
|
||||
}#>
|
||||
|
||||
#update SharePoint field
|
||||
Write-Verbose "Exactly one match found, updating SharePoint fields named Status and SnapshotTaken"
|
||||
$UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one result, stopping"; break }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Removed';
|
||||
SnapshotRemoved = [datetime](Get-Date);
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
Disconnect-VIServer -Server * -Confirm:$false
|
||||
}
|
||||
Else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object]
|
||||
$WebhookData
|
||||
)
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'vBxbnq2g9M7cQJtFN3iGU4kD4pPJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5s') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$VMName = $InputParams.HostName
|
||||
$Id = $InputParams.Id
|
||||
$Duration = $InputParams.Duration
|
||||
|
||||
#$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
|
||||
Write-Verbose "Duration = Clone"
|
||||
$VMClones = Get-VM | Where-Object Name -eq ($VMName + "_AutoClone_" + $Id)
|
||||
|
||||
If (@($VMClones).count -eq 1) {
|
||||
$Taken = $true
|
||||
$VMClone = $VMClones
|
||||
}
|
||||
else {
|
||||
if (@($VMClones).count -gt 1) {
|
||||
Write-Error "More than one VM clone match found, abort"
|
||||
Exit
|
||||
}
|
||||
else { Write-Verbose "Clone Id #$Id match not found for $VMName" }
|
||||
}
|
||||
|
||||
If (@($VMClones).count -eq 1) {
|
||||
$VMClone = $VMClones
|
||||
Write-Verbose "Exactly one clone match found, updating SharePoint fields named Status and SnapshotTaken"
|
||||
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoClone_$Id*")
|
||||
|
||||
If ($Taken -eq $true) {
|
||||
$UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one record, stopping"; break }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Taken';
|
||||
SnapshotTaken = $Task.PrevRunTime;
|
||||
AutoExpire = ($Task.Description -split '[\r\n]+')[1].split('_')[1];
|
||||
AutoDelete = ($Task.Description -split '[\r\n]+')[2].split('_')[1];
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
Disconnect-VIServer * -Confirm:$false
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object]
|
||||
$WebhookData
|
||||
)
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'vBxbnq2g9M7cQJtFN3iGU4kD4pPJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5s') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$VMName = $InputParams.HostName
|
||||
$Id = $InputParams.Id
|
||||
$Duration = $InputParams.Duration
|
||||
|
||||
$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | sort-object Name | select -first 1).Name }
|
||||
|
||||
|
||||
Write-Verbose "Duration = Snapshot"
|
||||
$VMSnapshots = $VM | Get-Snapshot | where-object Description -like "AutoSnap_$Id*"
|
||||
|
||||
If (@($VMSnapshots).count -eq 1) {
|
||||
$Taken = $true
|
||||
$VMSnapshot = $VMSnapshots
|
||||
}
|
||||
else {
|
||||
if (@($VMSnapshots | where-object Description -like "AutoSnap_$Id*").count -gt 1) {
|
||||
Write-Error "More than one snapshot match found, abort"
|
||||
Exit
|
||||
}
|
||||
else { Write-Verbose "Snapshot Id #$Id match not found on $VMName" }
|
||||
}
|
||||
|
||||
If (@($VMSnapshots).count -eq 1) {
|
||||
Write-Verbose "Exactly one snapshot match found, updating SharePoint fields named Status and SnapshotTaken"
|
||||
|
||||
If ($Taken -eq $true) {
|
||||
$UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one record, stopping"; break }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Taken';
|
||||
SnapshotTaken = $VMSnapshot.Created;
|
||||
AutoExpire = ($VMSnapshot.Description -split '[\r\n]+')[1].split('_')[1];
|
||||
AutoDelete = ($VMSnapshot.Description -split '[\r\n]+')[2].split('_')[1];
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
Disconnect-VIServer * -Confirm:$false
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object] $WebhookData
|
||||
)
|
||||
|
||||
function Get-ITDVMwareSharePointSnapshotRequestList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://testshare.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL
|
||||
Method = "Get"
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'HAKpueFYU4L3NMXTKqtHssnNGBrew3gVRLEq2Yi7yzWW8fpKNCPB5gUcnHfr9sdhXC53y7gWf5BDtxXkr3mZA3NV7DszpR3kjiLgi3FpRPgUWus9ZxCWy63znqPGh3AJ2bn43uP7GjzfLcgqYLQRkir') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
|
||||
$UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List2 = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,NotifyEmail&$expand=Author/Id'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$SPListItem = $ListItems | Where-object Id -eq $InputParams.Id
|
||||
If ($SPListItem.Title -ne $InputParams.HostName) {
|
||||
Write-Error ("Web request JSON does not match SharePoint Record for SPListItem.Hostname " + $SPListItem.HostName + " and InputParams.Hostname " + $InputParams.Hostname)
|
||||
Exit
|
||||
}
|
||||
|
||||
$VMName = $InputParams.HostName
|
||||
$SnapTime = ([DateTime]$SPListItem.DateTime).AddMinutes($Duration * 3)
|
||||
|
||||
$NotifyEmail = $SPListItem.Author.Email
|
||||
If ($SPListItem.NotifyEmail) { $NotifyEmail = $NotifyEmail + ',' + $SPListItem.NotifyEmail }
|
||||
|
||||
$tryCount = 0
|
||||
# while ($tryCount -lt 5) {
|
||||
try {
|
||||
$tryCount++
|
||||
Write-Warning ("SharePoint: " + $SnapTime)
|
||||
If ($SnapTime -lt (Get-Date)) {
|
||||
$SnapTime = (Get-Date).AddSeconds(30)
|
||||
}
|
||||
Write-Warning ("PowerShell: " + $SnapTime)
|
||||
|
||||
$SnapName = "AutoSnap_" + $SPListItem.ID
|
||||
$SnapExpireDateTime = $SnapTime.AddMinutes($SPListItem.Duration * 3)
|
||||
$SnapDeleteDateTime = $SnapExpireDateTime.AddMinutes(30)
|
||||
|
||||
$SnapDescription = "AutoSnap_" + $InputParams.ID + "`r" + "AutoExpire_$SnapExpireDateTime" + "`r" + "AutoDelete_$SnapDeleteDateTime"
|
||||
$snapMemory = $false
|
||||
$snapQuiesce = $false
|
||||
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | Select-Object -First 1).Name }
|
||||
|
||||
$VIServer = $VM.Uid.split('@')[1].split(':')[0]
|
||||
|
||||
$si = Get-View ServiceInstance -Server $VIServer
|
||||
$scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager -Server $VIServer
|
||||
|
||||
$spec = New-Object VMware.Vim.ScheduledTaskSpec
|
||||
$spec.Name = $SnapName, $VMname -join '_'
|
||||
$spec.Description = "$SnapDescription"
|
||||
$spec.Enabled = $true
|
||||
$spec.Notification = $NotifyEmail
|
||||
|
||||
$spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler
|
||||
$spec.Scheduler.runat = $SnapTime
|
||||
|
||||
$spec.Action = New-Object VMware.Vim.MethodAction
|
||||
$spec.Action.Name = "CreateSnapshot_Task"
|
||||
|
||||
@($SnapName, $SnapDescription, $SnapMemory, $SnapQuiesce) | ForEach-Object {
|
||||
$arg = New-Object VMware.Vim.MethodActionArgument
|
||||
$arg.Value = $_
|
||||
$spec.Action.Argument += $arg
|
||||
}
|
||||
|
||||
# prep for update SharePoint record status
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one result, stopping"; Exit }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $SharePointCredential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
# Create vCenter scheduled task
|
||||
$scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)
|
||||
Start-Sleep -Seconds 3
|
||||
}
|
||||
catch [System.Management.Automation.MethodInvocationException] {
|
||||
If ($tryCount -lt 4) {
|
||||
If ($Error[1].Exception -like "*You have attempted to schedule the scheduler at a time*in the past*") {
|
||||
Write-Warning ((Get-Date))# + ": Attempted schedule in past @ $SnapTime, trying again")
|
||||
}
|
||||
write-warning $trycount
|
||||
}
|
||||
Else {
|
||||
write-error "vCenter Snapshot Scheduled Task Creation failed"
|
||||
write-error $error[1]
|
||||
Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov
|
||||
$Status = "Errored"
|
||||
exit
|
||||
}
|
||||
}
|
||||
catch {
|
||||
write-error "vCenter Snapshot Scheduled Task Creation failed default message"
|
||||
write-error $error[1]
|
||||
Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed Default Message - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov
|
||||
$Status = "Errored"
|
||||
exit
|
||||
}
|
||||
#}
|
||||
|
||||
# update SharePoint record status
|
||||
If ($Status -ne "Errored") { $Status = "Scheduled" }
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = $Status;
|
||||
}
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
Disconnect-VIServer -Server * -Confirm:$false
|
||||
}
|
||||
Else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
|
||||
)
|
||||
|
||||
function Get-ITDVMwareSharePointSnapshotRequestList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://testshare.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail,AutoExpire,AutoDelete&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'w3gVRLEq2Yi7yzWW8fpKNCPTKqtHssnNGBref5BDtxXkr3mZA3NB5gUcnHfr9sdhXC53y7gWHAKpueFYU4L3NMXV7DszCWy63znqPGh3AJ2bn43uP7GjzfLcgqYLQRkirpR3kjiLgi3FpRPgUWus9Zx') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList -Credential $SharePointCredential
|
||||
$ListToRemove = $SnapshotList | where-object { $_.Status -eq "Expired, Delete Approved" } | Sort-Object AutoDelete
|
||||
|
||||
ForEach ($SPRecord in $ListToRemove) {
|
||||
$Id = $null
|
||||
$VMName = $null
|
||||
$SnapName = $null
|
||||
|
||||
$Id = $SPRecord.ID
|
||||
$VMName = $SPRecord.Title
|
||||
$SnapName = "AutoSnap_" + $Id
|
||||
|
||||
$SnapshotToRemove = Get-Snapshot -Name $SnapName -VM $VMName
|
||||
$Datastore = Get-VM $VMName | Get-Datastore
|
||||
$ViServer = $SnapshotToRemove.uid.split('@')[1].split(':')[0]
|
||||
|
||||
Write-Warning ($SnapshotToRemove.Name + " for " + $SnapshotToRemove.VM + " on " + $Datastore + " on " + $ViServer)
|
||||
|
||||
try {
|
||||
$SnapshotTaskCount = @(Get-Task -Server $ViServer | Where-Object { $_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running" }).count
|
||||
Write-Warning $SnapshotTaskCount
|
||||
while ($SnapshotTaskCount -ge 1) {
|
||||
$timestamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, pausing 60 seconds."
|
||||
Start-Sleep -Seconds 60
|
||||
|
||||
$timestamp = $null
|
||||
$SnapshotTaskCount = @(Get-Task | Where-Object { $_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running" }).count
|
||||
Write-Warning $SnapshotTaskCount
|
||||
}
|
||||
$timestamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, starting removal."
|
||||
$SnapshotToRemove | Remove-Snapshot -Confirm:$false
|
||||
}
|
||||
catch {
|
||||
Write-Error "Snapshot Removal failed";
|
||||
Write-Error $Error[1];
|
||||
exit
|
||||
}
|
||||
|
||||
#update SharePoint field
|
||||
Write-Verbose "Exactly one match found, updating SharePoint fields named Status and SnapshotTaken"
|
||||
$UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
#$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
#If (@($RecordToModify).count -gt 1) { Write-Error "More than one result, stopping"; break }
|
||||
#$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($Id)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Removed';
|
||||
SnapshotRemoved = [datetime](Get-Date);
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
}
|
||||
Disconnect-VIServer -Server * -Confirm:$false
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object]
|
||||
$WebhookData
|
||||
)
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'vBxbnq2g9M7cQJtFN3iGU4kD4pPJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5s') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$VMName = $InputParams.HostName
|
||||
$Id = $InputParams.Id
|
||||
$Duration = $InputParams.Duration
|
||||
|
||||
$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | sort-object Name | select -first 1).Name }
|
||||
|
||||
switch ($Duration) {
|
||||
{$Duration -ge 1 -and $Duration -le 7}
|
||||
{
|
||||
Write-Verbose "Duration = Snapshot"
|
||||
$VMSnapshots = $VM | Get-Snapshot | where-object Description -like "AutoSnap_$Id*"
|
||||
|
||||
If (@($VMSnapshots).count -eq 1) {
|
||||
Write-Verbose "Exactly one snapshot match found"
|
||||
$Taken = $true
|
||||
$VMSnapshot = $VMSnapshots
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoSnap_$Id*")
|
||||
}
|
||||
else {
|
||||
if (@($VMSnapshots | where-object Description -like "AutoSnap_$Id*").count -gt 1) {
|
||||
Write-Error "More than one snapshot match found, abort"
|
||||
Exit
|
||||
}
|
||||
else { Write-Verbose "Snapshot Id #$Id match not found on $VMName" }
|
||||
}
|
||||
}
|
||||
{$Duration -ge 8}
|
||||
{
|
||||
Write-Verbose "Duration = Clone"
|
||||
$VMClones = Get-VM | Where-Object Name -eq ($VMName + "_AutoClone_" + $Id)
|
||||
|
||||
If (@($VMClones).count -eq 1) {
|
||||
Write-Verbose "Exactly one clone match found"
|
||||
$Taken = $true
|
||||
$VMClone = $VMClones
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoClone_$Id*")
|
||||
}
|
||||
else {
|
||||
if (@($VMClones).count -gt 1) {
|
||||
Write-Error "More than one VM clone match found, abort"
|
||||
Exit
|
||||
}
|
||||
else { Write-Verbose "Clone Id #$Id match not found for $VMName" }
|
||||
}
|
||||
}
|
||||
Default {
|
||||
Write-Error "Duration less than zero."
|
||||
}
|
||||
}
|
||||
|
||||
If ($Taken -eq $true) {
|
||||
write-verbose "Updating SharePoint fields named Status and SnapshotTaken"
|
||||
$UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one record, stopping"; break }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Taken';
|
||||
SnapshotTaken = $Task.PrevRunTime;
|
||||
AutoExpire = ($Task.Description -split '[\r\n]+')[1].split('_')[1];
|
||||
AutoDelete = ($Task.Description -split '[\r\n]+')[2].split('_')[1];
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
Disconnect-VIServer * -Confirm:$false
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"Id": "{ItemProperty:ID}",
|
||||
"HostName": "{ItemProperty:HostName}",
|
||||
"DateTime": "{ItemProperty:DateTime}",
|
||||
"Duration": "{ItemProperty:Duration}"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,6 @@
|
||||
[
|
||||
{
|
||||
"Id": "566",
|
||||
"HostName": "itdscmt1.nd.gov"
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user