FogApi.psm1
$PSModuleRoot = $PSScriptRoot $script:lib = "$PSModuleRoot\lib" $script:tools = "$PSModuleRoot\tools" function Add-FogHostMac { # .ExternalHelp FogApi-help.xml [CmdletBinding(DefaultParameterSetName='byHost')] param ( [parameter(ValueFromPipeline=$true,ParameterSetName='byHost')] $fogHost, [parameter(ParameterSetName='byId')] $hostID, [parameter(ParameterSetName='byHost')] [parameter(ParameterSetName='byId')] $macAddress, [parameter(ParameterSetName='byHost')] [parameter(ParameterSetName='byId')] [switch]$primary, [parameter(ParameterSetName='byHost')] [parameter(ParameterSetName='byId')] [switch]$ignoreMacOnClient, [parameter(ParameterSetName='byHost')] [parameter(ParameterSetName='byId')] [switch]$ignoreMacForImaging, [parameter(ParameterSetName='byHost')] [parameter(ParameterSetName='byId')] [switch]$forceUpdate ) process { if ($null -ne $_) { $fogHost = $_; $hostID = $fogHost.id; } $hostID = Resolve-HostID $hostID if ($null -ne $hostID) { if ($primary) { $primaryVal = '1' } else { $primaryVal = '0' } if ($ignoreMacForImaging) { $imageIgnoreVal = '1' } else { $imageIgnoreVal = '0' } if ($ignoreMacOnClient) { $clientIgnoreVal = '1' } else { $clientIgnoreVal = '0' } $newMac = @{ hostID = "$hostID" mac = "$macAddress" description = " " pending = '0' primary = $primaryVal clientIgnore = $clientIgnoreVal imageIgnore = $imageIgnoreVal } $macExists = Get-FogMacAddresses | Where-Object mac -eq $macAddress if ($null -ne $macExists) { if ($forceUpdate) { Write-Warning "this mac already exists in fog!, updating it to be assigned to this host instead" Write-Verbose "Old mac definition was $($macExists | out-string). Updating to $($newMac | Out-String)"; return Update-FogObject -type object -coreObject macaddressassociation -jsonData ($newMac | ConvertTo-Json) -IDofObject $macExists.id } else { Write-Warning "This mac already exists in fog! It is attached to the host named: $((get-foghost -hostID $macExists.hostID).name)" } } else { return New-FogObject -type object -coreObject macaddressassociation -jsonData ($newMac | ConvertTo-Json) } } else { Write-Error "provided hostid was invalid!" return $null; } } } function Add-FogResultData { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [Parameter()] $result ) process { #test if result has data property if ($null -ne $result) { if ($null -eq ($result | Get-Member -Name data -ea 0)) { #result doesn't have data property $property = ($result | get-member -MemberType NoteProperty | Where-Object name -notmatch 'count').name $newResult = [PSCustomObject]@{ count = $result.count; data = $result.$property; $property = $result.$property; } $result = $newResult; # $result | Add-Member -MemberType NoteProperty -Name data -Value $result.$property -Force } } return $result; } } function Approve-FogPendingMac { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [parameter(ValueFromPipeline=$true)] [object]$macObject ) process { if ($null -ne $_) { $macObject = $_; } $macObject.pending = '0'; $data = ($macObject | ConvertTo-Json); $result = Update-FogObject -type object -coreObject macaddressassociation -IDofObject $macObject.id -jsonData $data return $result; } } function Deny-FogPendingMac { # .ExternalHelp FogApi-help.xml [CmdletBinding()] [Alias('Remove-FogMac')] param ( [Parameter(Mandatory=$true,ValueFromPipeline=$true)] $macObject ) process { if ($null -ne $_) { $macObject = $_; } return Remove-FogObject -type object -coreObject macaddressassociation -IDofObject $macObject.id; } } function Disable-FogApiHTTPS { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( ) process { $fogServer = (Get-FogServerSettings).fogserver; if ($fogServer -notlike "http://*") { if ($fogServer -like "https://*") { $fogServer = $fogServer.replace("https://","http://") } else { $fogServer = "http://$fogserver" } $result = Set-FogServerSettings -fogServer $fogServer; Write-Verbose "result is $($result | out-string)"; } else { Write-Verbose "Http already enabled!" # $result = $true; } return $fogserver; } } function Dismount-WinEfi { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param () process { $mountLtr=(Get-EfiMountLetter) if ($null -eq $mountLtr) { Write-Debug "EFI Partition is not mounted"; return $null } else { $mountVol = "C:\Windows\System32\mountvol.exe"; return Start-Process -FilePath $mountVol -Wait -NoNewWindow -ArgumentList @($mountLtr, '/D'); } } } function Enable-FogApiHTTPS { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( ) process { $fogServer = (Get-FogServerSettings).fogserver; if ($fogServer -notlike "https://*") { if ($fogServer -like "http://*") { $fogServer = $fogServer.replace("http://","https://") } else { $fogServer = "https://$fogserver" } $result = Set-FogServerSettings -fogServer $fogServer; Write-Verbose "result is $($result | out-string)"; } else { Write-Verbose "Https already enabled!" # $result = $true; } return $fogserver; } } function Find-FogObject { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( # The type of object being requested, should be search [Parameter(Position=0)] [ValidateSet("search")] [string]$type = "search", # The string to search all fields for [Parameter(Position=2)] [string]$stringToSearch ) DynamicParam { $paramDict = Set-DynamicParams $type; return $paramDict;} process { $paramDict | ForEach-Object { New-Variable -Name $_.Keys -Value $($_.Values.Value);} # $paramDict; Write-Verbose "Building uri and api call for $($paramDict.keys) $($paramDict.values.value)"; switch ($type) { search { if ($coreObject -ne "unisearch") { $uri = "$coreObject/$type/$stringToSearch"; } else { $uri = "$coreObject/$stringToSearch" } } } Write-Verbose "uri for get is $uri"; $apiInvoke = @{ uriPath=$uri; Method="GET"; } $result = Invoke-FogApi @apiInvoke; #convert the output to use the data property added in fog 1.6 if ($coreObject -ne "unisearch") { $result = Add-FogResultData $result; } else { "Search Results: `n" | Out-Host; "$($result._results | out-string)" | out-host; } return $result; } } function Get-FogActiveTasks { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param () process { $result = Get-FogObject -type objectactivetasktype -coreActiveTaskObject task return $result.data; } } function Get-FogGroupAssociations { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param () process { $groupAssocs = (Get-FogObject -type object -coreObject groupassociation); return $groupAssocs.data; } } function Get-FogGroupByName { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( $groupName ) process { $group = (Find-FogObject -type search -coreobject group -stringToSearch $groupName); $group = $group.data | Where-Object name -match $groupName; return $group; } } function Get-FogGroups { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param () process { $groups = (Get-FogObject -type object -coreobject group); return $groups.data; } } function Get-FogHost { # .ExternalHelp FogApi-help.xml [CmdletBinding(DefaultParameterSetName='searchTerm')] param ( [parameter(ParameterSetName='searchTerm')] [string]$uuid, [parameter(ParameterSetName='searchTerm')] [ArgumentCompleter({ param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams) if(Test-FogVerAbove1dot6) { $r = Get-FogHosts; if ($WordToComplete) { $r.Name.Where{ $_ -match "^$WordToComplete" } } else { $r.Name } } })] [string]$hostName, [parameter(ParameterSetName='searchTerm')] [string]$macAddr, [parameter(ParameterSetName='byID',Mandatory=$true)] [string]$hostID, [parameter(ParameterSetName='serialNumber',Mandatory=$true)] [string]$serialNumber ) begin { [bool]$found = $false; Write-Verbose 'Checking for passed variables' if ($serialNumber) { $inventorys = (Get-FogObject -type object -coreObject inventory).data $hostID = $inventorys | Where-Object { $_.sysserial -eq $serialNumber -OR $_.mbserial -eq $serialNumber -OR $_.caseserial -eq $serialNumber } | Select-Object -ExpandProperty HostID #find the inventory where the serial number matches one of the serial numbers in a hosts inventory and select the host id from that } elseif (!$uuid -and !$hostName -and !$macAddr -and !$hostID) { Write-Verbose 'no params given, getting current computer variables'; try { $compSys = Get-CimInstance -ClassName win32_computersystemproduct } catch { $compSys = (Get-WmiObject Win32_ComputerSystemProduct); } if ($compSys.UUID -notmatch "12345678-9012-3456-7890-abcdefabcdef" ) { $uuid = $compSys.UUID; } else { $uuid = ($compSys.Qualifiers | Where-Object Name -match 'UUID' | Select-Object -ExpandProperty Value); } # $macAddr = ((Get-NetAdapter | Select-Object MacAddress)[0].MacAddress).Replace('-',':'); $make = Get-CimInstance -classname win32_computersystem | Select-Object -ExpandProperty manufacturer if (($Make) -notmatch "vmware" ) { $macAddr = ( Get-NetAdapter | Where-Object { $_.Status -eq 'up' -And $_.Name -notmatch 'VMware' } | Select-Object -first 1 | Select-Object -expand MacAddress ).Replace("-",":"); } else { $macAddr = ( Get-NetAdapter | Where-Object { $_.Status -eq 'up' } | Select-Object -first 1 | Select-Object -expand MacAddress ).Replace("-",":"); } $hostName = $(hostname); } else { if ($hostID) { Write-Verbose "getting host from ID $hostID directly..." } } Write-Verbose 'getting all hosts to search...'; Write-Verbose "search terms: uuid is $uuid, macAddr is $macAddr, hostname is $hostName"; } process { Write-Verbose 'finding host in hosts'; [bool]$found = $false; if ($hostID) { $hostObj = Get-FogObject -type object -coreObject host -IDofObject "$hostID"; if ($null -ne $hostObj) { $found = $true; } } else { $hosts = (Get-FogHosts) $hostObj = $hosts | Where-Object { ($uuid -ne "" -AND $_.inventory.sysuuid -eq $uuid) -OR ` ($hostName -ne "" -AND $_.name -eq $hostName) -OR ` ($macAddr -ne "" -AND $_.macs -contains $macAddr); if ($uuid -ne "" -AND $_.inventory.sysuuid -eq $uuid) { $found = $true; Write-Verbose "$($_.inventory.sysuuid) matches the uuid $uuid`! host found is $found"; } if ($macAddr -ne "" -AND $_.macs -contains $macAddr) { Write-Verbose "$($_.macs) matches the macaddress $macAddr`! host found"; $found = $true; } if ($hostName -ne "" -AND $_.name -eq $hostName) { Write-Verbose "$($_.name) matches the hostname $hostName`! host found"; $found = $true; } } } } end { if ($found){ if ($hostObj.count -gt 1) { if ($hostName) { $hostObjByName = $hostObj | Where-Object name -eq $hostName; if ($null -ne $hostObjByName) { $hostObj = $hostObjByName } else { "Multiple hosts found and none of them match given hostname! Review hosts in return object and select just one if needed" | Out-Host; } } else { "Multiple hosts found! Review hosts in return object and select just one if needed" | Out-Host; } } if ($null -eq ($hostObj | Get-Member -Name ADOU)) { Write-Verbose "Host is $($hostObj | out-string) which is missing adou, reobtaining with id" $hostID = $hostObj.id; $hostObj = (Get-Fogobject -type object -coreObject host -IDofObject "$hostID"); } return $hostObj; } return $found; #return false if host not found } } function Get-FogHostAssociatedSnapins { # .ExternalHelp FogApi-help.xml [CmdletBinding()] [Alias('Get-FogAssociatedSnapins','Get-FogHostSnapins','Get-FogHostSnapinAssociations')] param ( [parameter(ValueFromPipeline=$true,ParameterSetName='byHost')] $fogHost = (Get-FogHost), [parameter(ParameterSetName='byId')] $hostId=((Get-FogHost).id) ) process { if ($null -ne $_) { $fogHost = $_; $hostId = $fogHost.id; } # $AllAssocs = (Invoke-FogApi -Method GET -uriPath snapinassociation).snapinassociations; $AllAssocs = Get-FogSnapinAssociations $snapins = New-Object System.Collections.Generic.List[object]; # $allSnapins = Get-FogSnapins; $allsnapinIDs = (Get-FogSnapins).id | Sort-Object; $AllAssocs | Where-Object hostID -eq $hostID | ForEach-Object { $snapinID = $_.snapinID; if (($snapinID -ne 0) -and ($snapinID -in $allsnapinIDs)) { try { $snapin = Get-FogObject -type object -coreObject snapin -IDofObject $snapinID -ea stop; } catch { Write-Warning "A snapin associated to a no longer existing or invalid snapin exists for this host! Run Repair-SnapinAssociations to fix for the server!" } } else { Write-Warning "A snapin associated to a no longer existing or invalid snapin exists for this host! Run Repair-SnapinAssociations to fix for the server!" } # $snapins.add((Invoke-FogApi -uriPath "snapin\$snapinID")) $snapins.add($snapin) } return $snapins; } } function Get-FogHostGroup { # .ExternalHelp FogApi-help.xml [CmdletBinding(DefaultParameterSetName='byId')] [Alias('Get-FogGroup')] param ( [parameter(ValueFromPipeline=$true,ParameterSetName='byHost')] $fogHost, [parameter(ParameterSetName='byId')] [int]$hostId ) process { if ($null -ne $_) { $fogHost = $_; $hostId = $fogHost.id; } if (!$hostId) { $hostId = (Get-FogHost).id; } $hostGroups = (Get-FogObject -Type object -coreObject groupassociation).data $hostGroups = $hostGroups | Where-Object hostID -eq $hostId; $groups = New-Object System.Collections.Generic.list[system.object]; if ($hostGroups) { $hostGroups.groupID | ForEach-Object { $group = Get-FogObject -type object -coreObject group -IDofObject $_ $groups.add(($group)) } } else { $groups = $Null; } return $groups; } } function Get-FogHostMacs { # .ExternalHelp FogApi-help.xml [CmdletBinding()] [Alias('Get-MacsForHost')] param ( [Parameter(ParameterSetName='byHostObject',ValueFromPipeline=$true)] $hostObject = (Get-FogHost), [Parameter(ParameterSetName='byHostID')] $hostID ) process { if ($null -ne $_) { $hostObject = $_; $hostID = $hostObject.id; } $hostID = Resolve-HostID $hostID if ($null -ne $hostID) { $macs = Get-FogMacAddresses; $hostMacs = $macs | Where-Object hostID -eq $hostId return $hostMacs; } else { Write-Error "invalid input!" return $null; } } } function Get-FogHostPendingMacs { # .ExternalHelp FogApi-help.xml [Alias('Get-PendingMacsForHost')] [CmdletBinding(DefaultParameterSetName='byId')] param ( [parameter(ValueFromPipeline=$true,ParameterSetName='byHost')] $fogHost, [parameter(ParameterSetName='byId')] $hostID ) process { if ($null -ne $_) { $fogHost = $_; $hostId = $fogHost.id; } $hostID = Resolve-HostID -hostID $hostid; if ($null -ne $hostID) { $hostMacs = Get-FogHostMacs -hostid $hostID; $pendingMacs = $hostMacs | Where-Object pending -eq '1'; } else { Write-Error "provided hostid was invalid!" } return $pendingMacs; } } function Get-FogHosts { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param () process { Write-Verbose "getting fog hosts" $hosts = (Get-FogObject -type Object -CoreObject host).data return $hosts; } } function Get-FogImages { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( ) process { return (Get-FogObject -type object -coreObject image).data; } } function Get-FogInventory { # .ExternalHelp FogApi-help.xml [CmdletBinding()] [Alias('Get-FogHostInventory','Get-WinInventoryForFog')] param ( [Parameter(ValueFromPipeline=$true)] $hostObj = (Get-FogHost), [switch]$fromFog ) process { if ($null -ne $_) { $hostObj = $_; } if ($IsLinux -OR $fromFog) { if ($IsLinux) { "Not yet implemented for getting the host inventory from linux inline, returning the hosts currently set inventory object" | out-host; } if ($null -eq $hostObj.inventory) { return (Get-FogHost -hostID $hostObj.ID).inventory } else { return $hostObj.inventory; } } else { $comp = Get-CimInstance -ClassName Win32_ComputerSystem; $compSys = Get-CimInstance -ClassName Win32_ComputerSystemProduct; $cpu = Get-CimInstance -ClassName Win32_processor; $bios = Get-CimInstance -ClassName Win32_Bios; $hdd = Get-CimInstance -ClassName Win32_DiskDrive | Where-Object DeviceID -match '0'; #get just drive 0 in case of multiple drives $gpu = Get-CimInstance -ClassName Win32_VideoController | Where-Object name -notmatch 'Microsoft Remote Display Adapter'; #filter out rdp display adapter $baseBoard = Get-CimInstance -ClassName Win32_BaseBoard; $case = Get-CimInstance -ClassName Win32_SystemEnclosure; $info = Get-ComputerInfo; $hostObj.inventory.hostID = $hostObj.id; # $hostObj.inventory.primaryUser = # $hostObj.inventory.other1 = # $hostObj.inventory.other2 = $hostObj.inventory.createdTime = $((get-date -format u).replace('Z','')); # $hostObj.inventory.deleteDate = '0000-00-00 00:00:00' $hostObj.inventory.sysman = $compSys.Vendor; #manufacturer $hostObj.inventory.sysproduct = $compSys.Name; #model $hostObj.inventory.sysversion = $compSys.Version; $hostObj.inventory.sysserial = $compSys.IdentifyingNumber; if ($compSys.UUID -notmatch "12345678-9012-3456-7890-abcdefabcdef" ) { $hostObj.inventory.sysuuid = $compSys.UUID; } else { $hostObj.inventory.sysuuid = ($compSys.Qualifiers | Where-Object Name -match 'UUID' | Select-Object -ExpandProperty Value); } $hostObj.inventory.systype = $case.chassistype; #device form factor found chassistype member of $case but it references a list that hasn't been updated anywhere I can find. i.e. returns 35 for a minipc but documented list only goes to 24 $hostObj.inventory.biosversion = $bios.name; $hostObj.inventory.biosvendor = $bios.Manufacturer; $hostObj.inventory.biosdate = $(get-date $info.BiosReleaseDate -Format d); $hostObj.inventory.mbman = $baseBoard.Manufacturer; $hostObj.inventory.mbproductname = $baseBoard.Product; $hostObj.inventory.mbversion = $baseBoard.Version; $hostObj.inventory.mbserial = $baseBoard.SerialNumber; $hostObj.inventory.mbasset = $baseBoard.Tag; $hostObj.inventory.cpuman = $cpu.Manufacturer; $hostObj.inventory.cpuversion = $cpu.Name; $hostObj.inventory.cpucurrent = "Current Speed: $($cpu.currentClockSpeed) MHz"; $hostObj.inventory.cpumax = "Max Speed $($cpu.MaxClockSpeed) MHz"; $hostObj.inventory.mem = "MemTotal: $($comp.TotalPhysicalMemory) kB"; $hostObj.inventory.hdmodel = $hdd.Model; $hostObj.inventory.hdserial = $hdd.SerialNumber; $hostObj.inventory.hdfirmware = $hdd.FirmareRevision; $hostObj.inventory.caseman = $case.Manufacturer; $hostObj.inventory.casever = $case.Version; $hostObj.inventory.caseserial = $case.SerialNumber; $hostObj.inventory.caseasset = $case.SMBIOSAssetTag; $hostObj.inventory.memory = "$([MATH]::Round($(($comp.TotalPhysicalMemory) / 1GB),2)) GiB"; if ($null -ne $hostObj.inventory.gpuvendors) { $hostObj.inventory.gpuvendors = $gpu.AdapterCompatibility; } if ($null -ne $hostObj.inventory.gpuproducts) { $hostObj.inventory.gpuproducts = $gpu.VideoProcessor #below is an attempt to append the video memoery of each gpu, but it gave wrong values on some cards <# $hostObj.inventory.gpuproducts = $gpu | Foreach-Object { "$($_.VideoProcessor) - ($([math]::round($_.AdapterRAM/1GB))GB)"; } #> } $jsonData = $hostObj.inventory | ConvertTo-Json; return $jsonData; } } } function Get-FogLog { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [switch]$static, [switch]$userFogLog ) process { if ($userFogLog) { $fogLog = "$home/.fog_user.log" } else { $fogLog = 'C:\fog.log'; if (!(Test-Path $fogLog)) { $fogLog = "C:\ProgramData\fog\fog.log" } } if (!$static) { "Starting dynamic fog log in new window, Hit Ctrl+C on new window or close it to exit dynamic fog log" | Out-Host; Start-Process Powershell.exe -ArgumentList "-Command `"Get-Content $fogLog -Wait`""; } else { Get-Content $fogLog; } return $fogLog; } } function Get-FogMacAddresses { # .ExternalHelp FogApi-help.xml [CmdletBinding()] [Alias('Get-FogMacs')] param () process { $macs = Get-FogObject -type object -coreObject macaddressassociation; return $macs.data; } } function Get-FogModules { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param () process { $modules = (Get-FogObject -type object -coreObject module) return $modules.data; } } function Get-FogObject { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( # The type of object being requested [Parameter(Position=0)] [ValidateSet("objectactivetasktype","object")] [string]$type, # The json data for the body of the request [Parameter(Position=2)] [Object]$jsonData, # The id of the object to get [Parameter(Position=3)] [string]$IDofObject ) DynamicParam { $paramDict = Set-DynamicParams $type; return $paramDict;} process { $paramDict | ForEach-Object { New-Variable -Name $_.Keys -Value $($_.Values.Value);} # $paramDict; Write-Verbose "Building uri and api call for $($paramDict.keys) $($paramDict.values.value)"; switch ($type) { objectactivetasktype { $uri = "$coreActiveTaskObject/current"; } object { if ($null -eq $IDofObject -OR $IDofObject -eq "") { $uri = "$coreObject"; } else { $uri = "$coreObject/$IDofObject"; } } # search { # if ($coreObject) { # $uri = "$coreObject/$type/$stringToSearch"; # } else { # $uri = "$type/$stringToSearch" # } # } } Write-Verbose "uri for get is $uri"; $apiInvoke = @{ uriPath=$uri; Method="GET"; jsonData=$jsonData; } if ($null -eq $apiInvoke.jsonData -OR $apiInvoke.jsonData -eq "") { $apiInvoke.Remove("jsonData"); } $result = Invoke-FogApi @apiInvoke; #if the api call wasn't for a specific object, convert the output to use the data property added in fog 1.6 if (!$IDofObject) { $result = Add-FogResultData $result; } return $result; } } function Get-FogSecsSinceEpoch { # .ExternalHelp FogApi-help.xml param ( $scheduleDate = (Get-Date) ) process { $EpochDiff = New-TimeSpan "01 January 1970 00:00:00" $($scheduleDate) $EpochSecs = [INT] $EpochDiff.TotalSeconds - [timezone]::CurrentTimeZone.GetUtcOffset($(get-date)).totalseconds return $EpochSecs } } function Get-FogServerSettings { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param () process { Write-Verbose "Pulling settings from settings file" #since we updated the fog settings file path for linux and mac systems, make it auto migrate if the old settings exists $settingsFile = Get-FogServerSettingsFile; $move = $false; if ($isLinux -or $IsMacOS) { $oldsettingsFile = "$home/APPDATA/Roaming/FogApi/api-settings.json" if (Test-Path $oldsettingsFile) { $move = $true; } } if (!(Test-path $settingsFile)) { Write-Warning "Api Settings file not yet created, creating default version now!" try { #create just the parent path with built-in mkdir if (!(test-path (split-path $settingsFile -Parent))) { mkdir (split-path $settingsFile -Parent) } } catch { #error creating parent path(s), looping through full path and using pwsh methods to create each part of the full path set-location "/" (split-path $settingsFile -Parent) -split "/" | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | ForEach-Object { if (!(Test-Path $_)) { new-item -path $_ -ItemType Directory -ea 0 } Set-Location $_; } } if ($move) { Write-Host -BackgroundColor Yellow -ForegroundColor White -Object "The settings file path has changed from $oldSettingsFile to $SettingsFile. The permissions are also being updated to be more secure (rw for owner only)" $oldParentPath = Split-Path $oldsettingsFile -Parent; try { Move-Item -path $oldsettingsFile -Destination $settingsFile -ea stop } catch { Copy-Item -path $oldsettingsFile -Destination $settingsFile -ea 0 -force; Write-Warning "there was an error moving the file, it was copied instead, please remove the $oldParentPath manually" } if ( ((Get-ChildItem $oldParentPath -force).count) -eq 0) { Write-Host -BackgroundColor Yellow -ForegroundColor White -Object "The old settings parent directory is empty" Remove-Item $oldParentPath -Force -Recurse; } else { Write-Warning "The old settings path was not empty, please remove the $oldParentPath manually to stop these warnings" } Set-FogServerSettingsFileSecurity -settingsFile $settingsFile; } else { Copy-Item -path "$script:lib\settings.json" -Destination $settingsFile -Force Set-FogServerSettingsFileSecurity -settingsFile $settingsFile; } } $serverSettings = (Get-Content $settingsFile | ConvertFrom-Json); return $serverSettings; } } function Get-FogServerSettingsFile { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( ) process { if ($isLinux -or $IsMacOS) { $settingsFile = "$home/.FogApi/api-settings.json" } else { $settingsFile = "$env:APPDATA/FogApi/api-settings.json" } return $settingsFile } } function Get-FogSetting { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [Parameter()] [ArgumentCompleter({ param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams) $r = Get-FogSettings; # $r = $settings.Name.trim(); if ($WordToComplete) { $r.Name.Where{ $_ -match "^$WordToComplete" } } else { $r.Name } })] $settingName, $settingID ) process { if ((Test-FogVerAbove1dot6)) { if (($null -eq $settingID) -AND ($null -ne $settingName)) { $setting = (Get-FogSettings | Where-Object name -eq $settingName) } elseif ($null -ne $settingID) { $setting = (Get-FogObject -type object -coreObject setting -IDofObject $settingID).data } else { Write-Warning "No name or id of a setting was given!" $setting = $null; } return $setting; } else { Write-Warning "Getting fog config settings in the API is only available in FOG 1.6 and above!" return $null; } } } function Get-FogSettings { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( ) process { if (Test-FogVerAbove1dot6) { return (Get-FogObject -type object -coreObject setting).data } else { Write-Warning "Getting fog config settings in the API is only available in FOG 1.6 and above!" } } } function Get-FogSnapinAssociations { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( ) process { $AllAssocs = (Get-FogObject -type object -coreObject snapinassociation).data return $AllAssocs } } function Get-FogSnapins { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param () process { return (Get-FogObject -type object -coreObject snapin).data; } } function Get-FogVersion { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [switch]$noWarning ) process { $info = (Invoke-FogApi -uriPath "system/info" -Method Get -ea 0) if ($null -ne $info) { $versionStr = $info.version; } if ([string]::IsNullOrEmpty($versionStr)) { if ($noWarning) { Write-Warning "Error finding version on system/info pass, getting version from getversion.php" } $versionStr = (Invoke-FogApi -uriPath "service/getversion.php" -Method Get ) } return $versionStr } } function Get-LastImageTime { # .ExternalHelp FogApi-help.xml [CmdletBinding(DefaultParameterSetName="bySN")] param ( [parameter(ParameterSetName='bySN')] $serialNumber, #scan the barcode input into powershell [parameter(ParameterSetName='byHostId')] $hostId, [parameter(ValueFromPipeline=$true,ParameterSetName='byHost')] $fogHost, [parameter(ParameterSetName='byHost')] [switch]$currentHost ) process { switch ($PSCmdlet.ParameterSetName) { bySN { Write-Verbose "Getting host by serial number" if (!$serialNumber) { $serialNumber = (Read-Host -Prompt "Scan Serial Number barcode") } $fogHost = Get-FogHost -serialNumber $serialNumber; $HostID = $fogHost.id; } byHostID { Write-Verbose "Getting host by id" $fogHost = Get-FogHost -hostID $hostId; } byHost { if ($null -ne $_) { $fogHost = $_; } if ($currentHost -or ($null -eq $fogHost)) { Write-Verbose "getting host of current machine" $fogHost = (Get-FogHost) } $HostID = $fogHost.id } } $imageLog = (get-fogobject -type object -coreObject imaginglog).data # get the image history log $hostLogs = $imageLog | where-object hostid -eq $HostID # get the image history logs for the given host if (!$hostLogs) { Write-Warning "No imaging logs found for host $($fogHost.name)!" return $null; } else { $hostLog = $hostLogs[-1] # select the last/most recent log #return a string of the information about the serial number if ($serialNumber) { "Serial number $serialNumber belongs to host $($fogHost.name), it was last imaged at $($hostLog.start) with the image $($hostLog.image)" | Out-Host } else { "hostname is $($fogHost.name), it was last imaged at $($hostLog.start) with the image $($hostLog.image)" | Out-Host } return $hostLog; } } } function Get-WinBcdPxeId { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [string]$searchString, [switch]$notBootMgr ) process { if ($IsLinux -or $IsMacOS) { Write-Warning "This is currently only implemented for windows" } else { if (!(Test-StringNotNullOrEmpty $searchString)) { [object]$searchString = (Get-NetAdapter -ea 0 | Where-Object status -eq up | Where-Object name -match 'Ethernet')[0] $searchString2 = "IPV4" $searchString3 = "Network" $searchString4 = "LAN" $searchString5 = "PXE" } # $searchString; # pause; if ((Test-StringNotNullOrEmpty "$($searchString.InterfaceDescription)" -ea 0)) { #search for PXE string that doesn't match ipxe but does match the interface description of the first ethernet adapter that is currently up $searchString = $searchString.InterfaceDescription; Write-Verbose "Searching bcd firmware boot options for description that matches $searchString" $search = (bcdedit /enum firmware | Where-Object { $_ -notmatch 'ipxe'} | select-string $searchString -Context 3,0 -SimpleMatch -ea 0); Write-Verbose "Result of search: $($search | out-string)" } else { Write-Verbose "Searching bcd firmware boot options for description that matches $searchString" $search = (bcdedit /enum firmware | Where-Object { $_ -notmatch 'ipxe'} | select-string $searchString -Context 3,0 -ea 0); Write-Verbose "Result of search: $($search | out-string)" } if (($null -eq $search) -and ($null -ne $searchString2)) { #search for PXE string that doesn't match ipxe that might match 'ipv4' Write-Verbose "Searching bcd firmware boot options for description that matches $searchString2" $search2 = (bcdedit /enum firmware | Where-Object { $_ -notmatch 'ipxe'} | select-string $searchString2 -Context 3,0 -ea 0); Write-Verbose "Result of search: $($search2 | out-string)" } if (($null -eq $search) -and ($null -eq $search2) -and ($null -ne $searchString3)) { #search for PXE string that doesn't match ipxe that might match 'Network' (or 'EFI Network' on a surface go 2) Write-Verbose "Searching bcd firmware boot options for description that matches $searchString3" $search3 = (bcdedit /enum firmware | Where-Object { $_ -notmatch 'ipxe'} | select-string $searchString3 -Context 3,0 -ea 0); Write-Verbose "Result of search: $($search3 | out-string)" } if (($null -eq $search) -and ($null -eq $search2) -and ($null -eq $search3) -and ($null -ne $searchString4)) { #search for PXE string that doesn't match ipxe but does match 'LAN' Write-Verbose "Searching bcd firmware boot options for description that matches $searchString4" $search4 = (bcdedit /enum firmware | select-string $searchString4 -Context 3,0 -ea 0); Write-Verbose "Result of search: $($search4 | out-string)" # if ($null -ne $searchString4.InterfaceDescription) { # $searchString4 = $searchString4.InterfaceDescription # $search4 = (bcdedit /enum firmware | Where-Object { $_ -notmatch 'ipxe'} | select-string $searchString4 -Context 3,0 -ea 0); # } } if (($null -eq $search) -and ($null -eq $search2) -and ($null -eq $search3) -and ($null -eq $search4) -and ($null -ne $searchString5)) { #search for PXE string that doesn't match ipxe but does match 'PXE' Write-Verbose "Searching bcd firmware boot options for description that matches $searchString5" $search5 = (bcdedit /enum firmware | Where-Object { $_ -notmatch 'ipxe'} | select-string $searchString5 -Context 3,0 -ea 0); Write-Verbose "Result of search: $($search5 | out-string)" } if ($null -ne $search) { Write-verbose "Found $($search | Out-String) returning just identifier" $pxeID = ($search.Context.PreContext | Where-Object { $_ -match "identifier"}) if ($null -ne $pxeID) { $pxeID = $pxeID.trimstart("identifier").trim() $vbOut = $search; } } elseif($null -ne $search2) { Write-verbose "Found $($search2 | Out-String) returning just identifier" $pxeID = ($search2.Context.PreContext | Where-Object { $_ -match "identifier"}) if ($null -ne $pxeID) { $pxeID = $pxeID.trimstart("identifier").trim() $vbOut = $search2; } } elseif($null -ne $search3) { Write-verbose "Found $($search3 | Out-String) returning just identifier" $pxeID = ($search3.Context.PreContext | Where-Object { $_ -match "identifier"}) if ($null -ne $pxeID) { $pxeID = $pxeID.trimstart("identifier").trim() $vbOut = $search3; } } elseif($null -ne $search4) { Write-verbose "Found $($search4 | Out-String) returning just identifier" $pxeID = ($search4.Context.PreContext | Where-Object { $_ -match "identifier"}) if ($null -ne $pxeID) { $pxeID = $pxeID.trimstart("identifier").trim() $vbOut = $search4; } } elseif($null -ne $search5) { Write-verbose "Found $($search5 | Out-String) returning just identifier" $pxeID = ($search5.Context.PreContext | Where-Object { $_ -match "identifier"}) if ($null -ne $pxeID) { $pxeID = $pxeID.trimstart("identifier").trim() $vbOut = $search5; } } else { Write-Warning "no pxe boot options found in bcdedit matching $searchString!" $pxeID = $null; } if ($pxeID.count -gt 1) { if ($notBootMgr) { $pxeID = $pxeID | Where-Object { $_ -notmatch "{bootmgr}"} } else { Write-Warning "Multiple entries returned, returning only first entry`n$($pxeID | Out-String)" $pxeID = $pxeID[0]; } } else { if ($pxeID -eq "{bootmgr}" -and $notBootMgr){ Write-Warning "Pxe id is boot manager but notBootMgr is present, returning null!" $pxeID = $null } } "pxeID found is $pxeID full context is $($vbOut | Out-String)" | Out-Host; return $pxeID } } } function Get-WinEfiMountLetter { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( ) process { if ($IsLinux -or $IsMacOS) { Write-Warning "This is currently only implemented for windows" return $null } else { $mountVol = "C:\Windows\System32\mountvol.exe"; #test if mountvol already has mounted a EFI partition somewhere and dismount it $mountVolStr = (& $mountVol) $currentEfiMountStr = ($mountVolStr | Select-String "EFI System Partition is mounted at"); if ($null -ne $currentEfiMountStr) { #get the substring starting at the index of the character before ':' in the drive name $currentEfiMountLtr = $currentEfiMountStr.ToString().Substring(($currentEfiMountStr.ToString().indexOf(':'))-1,2); if ($null -ne $currentEfiMountLtr) { return $currentEfiMountLtr; } } Write-Debug "EFI partition is not currently mounted"; return $null } } } function Install-FogService { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( $fogServer = ((Get-FogServerSettings).fogServer) ) process { if ($fogServer -like "http*") { $fileUrl = "$fogServer/fog/client/download.php?newclient"; $fileUrl2 = "$fogServer/fog/client/download.php?smartinstaller"; } else { $fileUrl = "http://$fogServer/fog/client/download.php?newclient"; $fileUrl2 = "http://$fogServer/fog/client/download.php?smartinstaller"; } Write-Host "Making temp download dir"; mkdir C:\fogtemp; Write-Host "downloading installer"; Invoke-WebRequest -URI $fileUrl -UseBasicParsing -OutFile 'C:\fogtemp\fog.msi'; Invoke-WebRequest -URI $fileUrl2 -UseBasicParsing -OutFile 'C:\fogtemp\fog.exe'; "installing fog service" | out-host; try { "Attempting silent msi install..." | out-host; Start-Process -FilePath msiexec -ArgumentList @('/i','C:\fogtemp\fog,msi','/qn') -NoNewWindow -Wait; } catch { "There was an error, attempting 'smart installer' and sending keystrokes to run through the wizard..." | out-host; if ($null -eq (Get-Service FogService -EA 0)) { & "C:\fogTemp\fog.exe"; Write-Host "Waiting 10 seconds then sending 10 enter keys" Start-Sleep 10 $wshell = New-Object -ComObject wscript.shell; $wshell.AppActivate('Fog Service Setup') $wshell.SendKeys("{Enter}") $wshell.SendKeys("{Space}") $wshell.SendKeys("{Enter}") $wshell.SendKeys("{Enter}") $wshell.SendKeys("{Enter}") $wshell.SendKeys("{Enter}") Write-Host "waiting 30 seconds for service to install" Start-Sleep 30 Write-host "sending more enter keys" $wshell.SendKeys("{Enter}") $wshell.SendKeys("{Enter}") $wshell.SendKeys("{Enter}") $wshell.SendKeys("{Enter}") $wshell.SendKeys("{Enter}") } } Write-Host "removing download file and temp folder"; Remove-Item -Force -Recurse C:\fogtemp; Write-Host "Starting fogservice"; if ($null -ne (Get-Service FogService)) { Start-Service FOGService; } return; } } function Invoke-FogApi { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [string]$uriPath, [string]$Method="GET", [string]$jsonData ) process { Write-Verbose "Pulling settings from settings file" # Set-FogServerSettings; $serverSettings = Get-FogServerSettings; [string]$fogApiToken = $serverSettings.fogApiToken; [string]$fogUserToken = $serverSettings.fogUserToken; [string]$fogServer = $serverSettings.fogServer; if ($fogServer -like "http*") { $baseUri = "$fogServer/fog"; } else { $baseUri = "http://$fogServer/fog"; } # Create headers Write-Verbose "Building Headers..."; $headers = @{}; $headers.Add('fog-api-token', $fogApiToken); $headers.Add('fog-user-token', $fogUserToken); # Set the Uri Write-Verbose "Building api call URI..."; $uri = "$baseUri/$uriPath"; $uri = $uri.Replace('//','/') if ($fogServer -notlike "https://*") { $uri = $uri.Replace('http:/','http://') } else { $uri = $uri.Replace('https:/','https://') } $apiCall = @{ Uri = $uri; Method = $Method; Headers = $headers; Body = $jsonData; ContentType = "application/json" } if ($null -eq $apiCall.Body -OR $apiCall.Body -eq "") { Write-Verbose "removing body from call as it is null" $apiCall.Remove("Body"); } # } else { # if (!($apiCall.Body.GetType() -eq "string")) { # $apiCall.Body = $apiCall.Body | ConvertTo-Json; # } # } Write-Verbose "$Method`ing $jsonData to/from $uri"; try { $result = Invoke-RestMethod @apiCall -ea Stop; } catch { $result = Invoke-WebRequest @apiCall; } Write-Verbose "finished api call"; return $result; } } function Mount-WinEfi { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( $mountLtr='A:' ) process { if ($IsLinux -or $IsMacOS) { Write-Warning "This is currently only implemented for windows" return $null; } else { $mountVol = "C:\Windows\System32\mountvol.exe"; #test if mountvol already has mounted a EFI partition somewhere and dismount it $currentEfiMountLtr = Get-EfiMountLetter if ($null -ne $currentEfiMountLtr) { if ($mountLtr -match $currentEfiMountLtr) { Write-Debug "EFI partition already mounted at $currentEfiMountLtr, nothing to do"; return $null } else { Write-Debug "EFI partition already mounted at $currentEfiMountLtr, Dismounting and remounting at specifed mount letter of $mountltr"; Dismount-WinEFI; } } if ((get-psdrive | Where-Object Root -match $mountltr)) { #test is mountltr is already in use and remove if it is Write-Debug "Dismounting non EFI drive already mounted at $mountltr" Remove-PSDrive $mountLtr; } return Start-Process -FilePath $mountVol -Wait -NoNewWindow -ArgumentList @($mountLtr, '/S'); } } } function New-FogHost { # .ExternalHelp FogApi-help.xml [CmdletBinding(DefaultParameterSetName='default')] [Alias('Add-FogHost')] param ( [Parameter(Mandatory=$true,ParameterSetName='default')] [string]$name, [Parameter(Mandatory=$true,ParameterSetName='default')] [string[]]$macs, [Parameter(ParameterSetName='default')] [string[]]$modules = ((Get-FogModules | Where-Object isDefault -eq '1') | Select-Object -ExpandProperty id), [Parameter(Mandatory=$true,ParameterSetName='custom')] [object]$customHost ) process { if ($PSCmdlet.ParameterSetName -eq 'default') { if ($name -match " ") { Write-Warning "name $name includes whitespace, replacing whitespace with - if not at end of string"; $name = $name.TrimEnd(); $name = $name.Replace(" ","-"); "new name is $name" | Out-Host; } $hostObject = @{ name = $name; macs = $macs; modules = $modules; } } else { $hostObject = $customHost; "Custom host is specified, no validation being performed, object properties are $($hostObject | Out-String)" } $hostJson = $hostObject | ConvertTo-Json; if ($PSCmdlet.ParameterSetName -eq 'default') { try { Write-Verbose "Checking for existing name" $hostNameCheck = Get-FogHost -hostName $name; if ($hostNameCheck) { Write-Warning "host with name $name already exists, returning existing host object"; return $hostNameCheck; } $hostMacCheck = New-Object System.Collections.Generic.list[object]; $macs | ForEach-Object { "Checking for existings host with mac $($_)" | Out-Host; $hostMacCheckItem = (Get-FogHost -macAddr $_); if ($hostMacCheckItem) { Write-Warning "mac address $($_) already exists on host $($hostMacCheckItem.name)"; $hostMacCheck.add(($hostMacCheckItem)); } } if ($hostMacCheck.count -gt 0) { Write-Warning "some macs already exist on hosts, returning list of matching host objects"; return $hostMacCheck; } } catch { Write-Warning "Error during input validation, attempting to create new host" } } "Creating new Host $hostObject" | Out-Host; $newHost = New-FogObject -type object -coreObject host -jsonData $hostJson if ($null -ne $newHost) { return $newHost; } } } function New-FogObject { # .ExternalHelp FogApi-help.xml [CmdletBinding()] [Alias('Add-FogObject')] param ( # The type of object being requested [Parameter(Position=0)] [ValidateSet("objecttasktype","object")] [string] $type, # The json data for the body of the request [Parameter(Position=2)] [Object]$jsonData, # The id of the object when creating a new task [Parameter(Position=3)] [string]$IDofObject ) DynamicParam { $paramDict = Set-DynamicParams $type; return $paramDict;} process { $paramDict | ForEach-Object { New-Variable -Name $_.Keys -Value $($_.Values.Value);} Write-Verbose "Building uri and api call"; switch ($type) { objecttasktype { $uri = "$CoreTaskObject/$IDofObject/task"; } object { $uri = "$CoreObject"; } } $apiInvoke = @{ uriPath=$uri; Method="POST"; jsonData=$jsonData; } $result = Invoke-FogApi @apiInvoke; return $result; } } function Receive-FogImage { # .ExternalHelp FogApi-help.xml [CmdletBinding(DefaultParameterSetName='now')] [Alias('Save-FogImage','Invoke-FogImageCapture','Capture-FogImage','Pull-FogImage')] param ( [Parameter(ParameterSetName='now')] [Parameter(ParameterSetName='schedule')] $hostId, [Parameter(ValueFromPipeline=$true,ParameterSetName='now-byhost')] [Parameter(ValueFromPipeline=$true,ParameterSetName='schedule-byhost')] $fogHost, [Parameter(ParameterSetName='schedule')] [Parameter(ParameterSetName='schedule-byhost')] [datetime]$StartAtTime, [Parameter(ParameterSetName='now')] [Parameter(ParameterSetName='now-byhost')] [Parameter(ParameterSetName='schedule')] [Parameter(ParameterSetName='schedule-byhost')] [switch]$debugMode, [Parameter(ParameterSetName='now')] [Parameter(ParameterSetName='now-byhost')] [Parameter(ParameterSetName='schedule')] [Parameter(ParameterSetName='schedule-byhost')] [switch]$NoWol, [Parameter(ParameterSetName='now')] [Parameter(ParameterSetName='now-byhost')] [Parameter(ParameterSetName='schedule')] [Parameter(ParameterSetName='schedule-byhost')] [switch]$shutdown ) process { if ($null -ne $_) { $fogHost = $_; $hostId = $fogHost.id } if ($null -eq $hostId) { $hostId = $fogHost.id; } if ($null -eq $fogHost) { $fogHost = Get-FogHost -hostID $hostId; } if (Test-FogVerAbove1dot6) { $debugstr = "$($debugMode.IsPresent)" } else { if ($debugMode) { $debugStr = "0" } else { $debugStr = "1" } } if ($Nowol) { $wolstr = "0" } else { $wolStr = "1" } if ($shutdown) { $shutdownStr = "1" } else { $shutdownStr = "0" } $currentImage = $fogHost.imageName; $fogImages = Get-FogImages; $fogImage = ($fogImages | Where-Object name -match $currentImage) "Creating Capture Task for fog host of id $($hostID) named $($fogHost.name)" | Out-Host; "Will capture the assigned image $($fogImage.name) - $($fogImage.id) which will capture the os $($fogImage.osname)" | Out-host; if ($PSCmdlet.ParameterSetName -eq 'now') { "No Time was specified, queuing the task to start now" | out-host; if (Test-FogVerAbove1dot6) { $jsonData = @" { "taskTypeID": "2" "shutdown":"$shutDownStr", "debug":"$debugStr", "wol":"$wolStr", "isActive":"1" } "@ } else { $jsonData = @" { "taskTypeID": "2" "shutdown":"$shutDownStr", "other2":"$debugStr", "other4":"$wolStr", "isActive":"1" } "@ } } else { "Start time of $($StartAtTime) specified, scheduling the task to start at that time" | out-host; $scheduleTime = Get-FogSecsSinceEpoch -scheduleDate $StartAtTime $runTime = get-date $StartAtTime -Format "yyyy-M-d HH:MM" if (Test-FogVerAbove1dot6) { $jsonData = @" { "taskName":"Capture Task", "type":"S", "taskTypeID":"2", "runTime":"$runTime", "scheduleTime":"$scheduleTime", "isGroupTask":"0", "hostID":"$($hostId)", "shutdown":"$shutdownStr", "debug":"$debugStr", "wol":"$wolStr", "isActive":"1" } "@ } else { $jsonData = @" { "name":"Capture Task", "type":"S", "taskTypeID":"2", "runTime":"$runTime", "scheduleTime":"$scheduleTime", "isGroupTask":"0", "hostID":"$($hostId)", "shutdown":"0", "other2":"0", "other4":"1", "isActive":"1" } "@ } } return New-FogObject -type objecttasktype -coreTaskObject host -jsonData $jsonData -IDofObject "$hostId"; } } function Remove-FogObject { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( # The type of object being requested [Parameter(Position=0)] [ValidateSet("objecttasktype","objectactivetasktype","object")] [string]$type, # The json data for the body of the request [Parameter(Position=2)] [Object]$jsonData, # The id of the object to remove [Parameter(Position=3)] [string]$IDofObject ) DynamicParam { $paramDict = Set-DynamicParams $type; return $paramDict;} process { $paramDict | ForEach-Object { New-Variable -Name $_.Keys -Value $($_.Values.Value);} Write-Verbose "Building uri and api call"; switch ($type) { objecttasktype { $uri = "$CoreTaskObject/$IDofObject/cancel"; } object { $uri = "$CoreObject/$IDofObject/delete"; } objectactivetasktype { $uri = "$CoreActiveTaskObject/cancel" } } $apiInvoke = @{ uriPath=$uri; Method="DELETE"; jsonData=$jsonData; } if (($null -eq $apiInvoke.jsonData) -OR ($apiInvoke.jsonData -eq "")) { $apiInvoke.Remove("jsonData"); } $result = Invoke-FogApi @apiInvoke; return $result; } } function Remove-UsbMac { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [parameter(ValueFromPipeline=$true,ParameterSetName='byHost')] $hostObj, [parameter(ParameterSetName='byName')] [ArgumentCompleter({ param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams) if(Test-FogVerAbove1dot6) { $r = (Get-FogHosts).Name if ($WordToComplete) { $r.Where{ $_ -match "^$WordToComplete" } } else { $r } } })] [string]$hostName= "$(hostname)", [parameter(ParameterSetName='byName')] [parameter(ParameterSetName='byHost')] [string[]]$usbMacs # $macId ) process { if ($null -eq $usbMacs) { Write-Error "no macs to remove given"; exit; } if ($null -ne $_) { $hostObj = $_; } else { $hostObj = Get-FogHost -hostName $hostname; } Write-Verbose "remove usb ethernet adapter from host $hostname on fog server $fogServer ...."; # get the host id by getting all hosts and searching the hosts array of the returned json for the item that has a name matching the current hostname and get the host id of that item $hostId = $hostObj.id; # $hostId = ( (Invoke-FogApi -fogServer $fogServer -fogApiToken $fogApiToken -fogUserToken $fogUserToken).hosts | Where-Object name -match "$hostname" ).id; # With the host id get mac associations that match that host id. $macs = Get-FogMacAddresses | Where-Object hostID -match $hostID # Copy the return fixedsize json array collection to a new powershell list variable for add and remove functions $macList = New-Object System.Collections.Generic.List[System.Object]; try { $macs.ForEach({ $macList.add($_.mac); }); } catch { $macs | ForEach-Object{ $macList.add($_.mac); } } # Check if any usbmacs are contained in the host's macs $usbMacs | ForEach-Object { #loop through list of usbMacs if ( $macList.contains($_) ) { # check if the usbMac is contained in the mac list of the host # Remove from the list so a new primary can be picked if needed $macList.Remove($_); Write-Verbose "$_ is a $usbMac connected to $hostname, checking if it is the primary..."; $macItem = ($macs | Where-Object mac -eq $_ ); if ( $macItem.primary -eq '1' ) { Write-Verbose "It is primary, let's fix that and set $($macList[0]) to primary"; $macItem.primary = '0'; try { Update-FogObject -type object -coreObject macaddressassociation -IDofObject $macItem.id -jsonData ($macItem | ConvertToJson) } catch { $removePrimaryAttribute = @{ uriPath = "macaddressassociation/$($macItem.id)/edit"; Method = 'Put'; jsonData = ($macItem | ConvertTo-Json); } Invoke-FogApi @removePrimaryAttribute; } Write-Verbose "Primary attribute removed, setting new primary..."; $newPrimary = ($macs | Where-Object mac -eq $macList[0] ); if ($null -eq $newPrimary) { Write-Verbose "host only has usbmacs, adding first non usbmac adapter"; $physicalMacs = (get-netadapter | select-object -expand macaddress).replace("-",":") $physicalMacs = $physicalMacs | Where-Object {$_ -NotIn $usbMacs}; Add-FogHostMac -hostID $hostID -macAddress $physicalMacs[0] -primary; } else { $newPrimary.primary = '1'; $newPrimary.pending = '0'; Update-FogObject -type object -coreObject macaddressassociation -IDofObject $newPrimary.id -jsonData ($newPrimary | ConvertTo-Json) } } Write-Verbose "Remove the usb ethernet mac association"; try { $result += Remove-FogObject -type object -coreObject macaddressassociation -IDofObject $macItem.id; } catch { $removeMacAssoc = @{ uriPath = "macaddressassociation/$($macItem.id)/delete"; Method = 'Delete'; } $result += Invoke-FogApi @removeMacAssoc; } Write-Verbose "Usb macs $usbMacs have been removed from $hostname on the $fogServer"; } } if ($null -eq $result) { $result = "no usb adapters found"; #replace string if found } return $result; } } function Repair-FogSnapinAssociations { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( ) process { #get all associations on the server $AllAssocs = Get-FogSnapinAssociations; #find any that have a snapinID of 0 or -1 or any negative number that would also be invalid and find any snapin associations with an id that doesn't exist $allsnapinIDs = (Get-FogSnapins).id | Sort-Object; $invalidSnapinID = $AllAssocs | Where-Object { ($_.snapinID -le 0) -or ($_.snapinID -notin $allsnapinIDs)} if ($null -ne $invalidSnapinID) { "These snapin assoiciations have an invalid snapinID either of 0 or -1 or an id that doesn't belong to any snapins in the server and will be removed:`n$($invalidSnapinID | out-string)" | out-host; $invalidSnapinID | ForEach-Object { Write-Verbose "Removing association $($_ | out-string)" Write-Debug "Removing association $($_ | out-string)" Remove-FogObject -type object -coreObject snapinassociation -IDofObject $_.id } #refresh association list after removing some invalids $AllAssocs = Get-FogSnapinAssociations; } else { "No associations with invalid snapinID found" | out-host; } #get all current fog host IDs for testing if the hostid is a host that exists $AllHostIDs = (Get-FogHosts).id | Sort-Object #find any associations with a hostID of 0 or -1 or where the hostid is not a host $invalidHostID = $AllAssocs | Where-Object { ($_.hostID -le 0) -OR ($_.hostid -notin $AllHostIDs) } if ($null -ne $invalidHostID) { "These snapin assoiciations have an invalid hostID of either 0 or -1 or other negative number, or have a hostid that doesn't belong to any host and will be removed:`n$($invalidHostID | out-string)" | out-host; $invalidHostID | ForEach-Object { Write-Verbose "Removing association $($_ | out-string)" Write-Debug "Removing association $($_ | out-string)" Remove-FogObject -type object -coreObject snapinassociation -IDofObject $_.id } } else { "No Invalid hostid's found in snapin associations" } "Snapin Association repair complete!" | out-host; } } function Reset-HostEncryption { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [parameter(ValueFromPipeline=$true)] $fogHost = (Get-FogHost), [switch]$restartSvc ) process { if ($null -ne $_) { $fogHost = $_; } $fogHost.pub_key = ""; $fogHost.sec_tok = ""; $fogHost.sec_time = "0000-00-00 00:00:00"; try { $jsonData = $fogHost | Select-Object id,pub_key,sec_tok,sec-time -ea stop | ConvertTo-Json; } catch { #in 1.6, if you are looping through multiple hosts gotten with get-foghosts, they have summarized data, get the individual host record if the token properties don't exist $fogHOst = get-foghost -hostID $fogHost.id $jsonData = $fogHost | Select-Object id,pub_key,sec_tok,sec-time | ConvertTo-Json; } $result = Update-FogObject -type object -coreObject host -IDofObject $fogHost.id -jsonData $jsonData; if ($restartSvc) { Restart-Service fogservice -force; } return $result; } } function Resolve-HostID { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( $hostID = (Get-foghost).id ) process { if ($hostID.gettype().name -ne "Int32"){ try { $check = [int32]$hostID Write-Verbose "checking if hostid is an int: '$check' yes it is" } catch { if ($hostID.gettype().name -eq "string") { $hostID = (Get-FogHost -hostname $hostID).id } elseif($hostID.gettype().name -eq "PSCustomObject") { if ($hostID.id) { $hostID = $hostID.id } else { $hostID = $null; } } else { $hostID = $Null; } if ($null -eq $hostID) { Write-Error "Please provide a valid foghost object, hostid or hostname, returning null for hostid" } } } if ($null -ne $hostID) { if ($null -eq (Get-foghost -hostID $hostID)) { Write-Error "hostid $hostID does not exist in your fog hosts! returning null!" $hostID = $null; } } return $hostID; } } function Send-FogImage { # .ExternalHelp FogApi-help.xml [CmdletBinding(DefaultParameterSetName='now')] [Alias('Push-FogImage','Deploy-FogImage')] param ( [Parameter(ParameterSetName='now')] [Parameter(ParameterSetName='schedule')] $hostId, [Parameter(ValueFromPipeline=$true,ParameterSetName='now-byhost')] [Parameter(ValueFromPipeline=$true,ParameterSetName='schedule-byhost')] $fogHost, [Parameter(ParameterSetName='schedule')] [Parameter(ParameterSetName='schedule-byhost')] [datetime]$StartAtTime, [Parameter(ParameterSetName='now')] [Parameter(ParameterSetName='now-byhost')] [Parameter(ParameterSetName='schedule')] [Parameter(ParameterSetName='schedule-byhost')] [ArgumentCompleter({ param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams) $r = Get-FogImages; if ($WordToComplete) { $r.Name.Where{ $_ -match "^$WordToComplete" } } else { $r.Name } })] [string]$imageName, [Parameter(ParameterSetName='now')] [Parameter(ParameterSetName='now-byhost')] [Parameter(ParameterSetName='schedule')] [Parameter(ParameterSetName='schedule-byhost')] [switch]$debugMode, [Parameter(ParameterSetName='now')] [Parameter(ParameterSetName='now-byhost')] [Parameter(ParameterSetName='schedule')] [Parameter(ParameterSetName='schedule-byhost')] [switch]$NoWol, [Parameter(ParameterSetName='now')] [Parameter(ParameterSetName='now-byhost')] [Parameter(ParameterSetName='schedule')] [Parameter(ParameterSetName='schedule-byhost')] [switch]$shutdown, [Parameter(ParameterSetName='schedule')] [Parameter(ParameterSetName='schedule-byhost')] [switch]$NoSnapins ) process { if ($null -ne $_) { $fogHost = $_; $hostId = $fogHost.id } if ($null -eq $hostId) { $hostId = $fogHost.id; } if ($null -eq $fogHost) { $fogHost = Get-FogHost -hostID $hostId; } # $fogHost = Get-FogHost -hostID $hostId; if (Test-FogVerAbove1dot6) { $debugstr = "$($debugMode.IsPresent)" } else { if ($debugMode) { $debugStr = "0" } else { $debugStr = "1" } } if ($Nowol) { $wolstr = "0" } else { $wolStr = "1" } if ($shutdown) { $shutdownStr = "1" } else { $shutdownStr = "0" } if ($NoSnapins) { $deploySnapins = $false; } else { $deploySnapins = $true; } $currentImage = $fogHost.imageName; $fogImages = Get-FogImages; if ($null -ne $imageName) { if ($currentImage -eq $imageName) { Write-Verbose "Image $imageName already set on host" } else { "Host $($foghost.name) has image $currentImage set, changing image to $imageName!" | out-host; $fogHost = Set-FogImage -hostId $fogHost.id -fogImage ($fogImages | Where-Object name -eq $imageName) $currentImage = $fogHost.imageName; } } $fogImage = ($fogImages | Where-Object name -eq $currentImage) "Creating Deploy Task for fog host of id $($hostID) named $($fogHost.name)" | Out-Host; "Will deploy the assigned image $($fogImage.name) - $($fogImage.id) which will install the os $($fogImage.osname)" | Out-host; if ($PSCmdlet.ParameterSetName -eq 'now') { "No Time was specified, queuing the task to start now" | out-host; if (Test-FogVerAbove1dot6) { $jsonData = @" { "taskName":"Deploy Task for $($fogHost.name) id $($foghost.id)", "taskTypeID":"1", "shutdown":"$shutDownStr", "debug":"$debugStr", "wol":"$wolStr", "isActive":"1" } "@ } else { $jsonData = @" { "taskTypeID":"1", "shutdown":"$shutDownStr", "other2":"$debugStr", "other4":"$wolStr", "isActive":"1" } "@ } } else { "Start time of $($StartAtTime) specified, scheduling the task to start at that time" | out-host; $scheduleTime = Get-FogSecsSinceEpoch -scheduleDate $StartAtTime $runTime = get-date $StartAtTime -Format "yyyy-M-d HH:MM" if (Test-FogVerAbove1dot6) { $jsonData = @" { "taskName":"Deploy Task", "type":"S", "taskTypeID":"1", "runTime":"$runTime", "scheduleTime":"$scheduleTime", "isGroupTask":"0", "hostID":"$($hostId)", "shutdown":"$shutdownStr", "debug":"$debugStr", "wol":"$wolStr", "isActive":"1", "deploySnapins":"$deploySnapins" } "@ } else { $jsonData = @" { "name":"Deploy Task", "type":"S", "taskTypeID":"1", "runTime":"$runTime", "scheduleTime":"$scheduleTime", "isGroupTask":"0", "hostID":"$($hostId)", "shutdown":"$shutdownStr", "other2":"$debugStr", "other4":"$wolStr", "isActive":"1" } "@ } } return New-FogObject -type objecttasktype -coreTaskObject host -jsonData $jsonData -IDofObject "$hostId"; } } function Send-FogWolTask { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [Parameter(ParameterSetName='byHostObject')] $hostObj, [Parameter(ParameterSetName='byname')] [ArgumentCompleter({ param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams) if(Test-FogVerAbove1dot6) { $r = (Get-FogHosts).Name if ($WordToComplete) { $r.Where{ $_ -match "^$WordToComplete" } } else { $r } } })] [string]$computername ) process { if ($PSCmdlet.ParameterSetName -eq 'byHostObject') { if ($null -ne $_) { $hostObj = $_; } $hostID = $hostObj.id } else { $hostID= (get-foghost -hostName $computername).id } $jsonData = @{ taskTypeID = "14"; wol = "1"; other2 = "-1"; other4 = "1"; isActive = "1;" } return New-FogObject -type objecttasktype -coreTaskObject host -jsonData ($jsonData | ConvertTo-Json) -IDofObject $hostID } } function Set-FogHostImage { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [parameter(Mandatory=$true)] $hostID, [parameter(ValueFromPipeline=$true)] $fogImage ) process { $jsonImageData = $fogimage | select-object @{N="imageID";E={$_.id}} | convertto-json $updatedHost = Set-FogObject -type object -coreObject host -IDofObject "$($hostid)" -jsonData $jsonImageData return $updatedHost; } } function Set-FogInventory { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [parameter(ValueFromPipeline=$true)] $hostObj = (Get-FogHost), $jsonData ) process { if ($null -ne $_) { $hostObj = $_; } if ($null -eq $jsonData) { $jsonData = (Get-FogInventory -hostObj $hostObj) } $inventoryApi = @{ jsonData = $jsonData; Method = 'Post'; uriPath = "inventory/new"; } Invoke-FogApi @inventoryApi -verbose; $jsonData = (Get-FogInventory -hostObj $hostObj) return; } } function Set-FogServerSettings { # .ExternalHelp FogApi-help.xml [CmdletBinding(DefaultParameterSetName='prompt')] param ( [parameter(ParameterSetName='default')] [string]$fogApiToken, [parameter(ParameterSetName='default')] [string]$fogUserToken, [parameter(ParameterSetName='default')] [string]$fogServer, [parameter(ParameterSetName='prompt')] [switch]$interactive ) process { $settingsFile = Get-FogServerSettingsFile; $ServerSettings = Get-FogServerSettings; Write-Verbose "Current/old Settings are $($ServerSettings)"; $helpTxt = @{ fogApiToken = "fog API token found at http://fog-server/fog/management/index.php?node=about&sub=settings under API System"; fogUserToken = "your fog user api token found in the user settings http://fog-server/fog/management/index.php?node=user&sub=list select your api enabled used and view the api tab"; fogServer = "your fog server hostname or ip address to be used for created the url used in api calls default is fog-server or fogServer, to enforce http/https input this as https://fogserver or http://fogserver, you can also use Enable-FogApiHTTPS later"; } if($interactive -or $PSCmdlet.ParameterSetName -eq 'prompt') { if ($IsLinux) { Write-Warning "If you have issues with pasting your apikeys into these prompts (issue with read-host in some linux instances of pwsh), try again without -interactive and paste into each param. i.e. `Set-FogServerSettings -fogapiToken '12345abcdefg' -fogUserToken 'abcdefg12345' -fogServer 'fog'" } ($serverSettings.psobject.properties).Name | ForEach-Object { $var = (Get-Variable -Name $_); if ($null -eq $var.Value -OR $var.Value -eq "") { Set-Variable -name $var.Name -Value (Read-Host -Prompt "help message: $($helpTxt.($_))`nEnter the $($var.name)"); } } $serverSettings = @{ fogApiToken = $fogApiToken; fogUserToken = $fogUserToken; fogServer = $fogServer; } $serverSettings | ConvertTo-Json | Out-File -FilePath $settingsFile -Encoding oem -Force; } elseif( #if all params are passed and not null create new settings object !([string]::IsNullOrEmpty($fogApiToken)) -AND !([string]::IsNullOrEmpty($fogUserToken)) -AND !([string]::IsNullOrEmpty($fogServer)) ) { $serverSettings = @{ fogApiToken = $fogApiToken; fogUserToken = $fogUserToken; fogServer = $fogServer; } } else { #check for some setting being passed but not all and set them individually if (!([string]::IsNullOrEmpty($fogApiToken))) { $ServerSettings.fogApiToken = $fogApiToken; } if (!([string]::IsNullOrEmpty($fogUserToken))) { $ServerSettings.fogUserToken = $fogUserToken; } if (!([string]::IsNullOrEmpty($fogServer))) { $ServerSettings.fogServer = $fogServer; } $serverSettings | ConvertTo-Json | Out-File -FilePath $settingsFile -Encoding oem -Force; } # If given paras are null just pulls from settings file # If they are not null sets the object to passed value Write-Verbose "making sure all settings are set"; if ( $ServerSettings.fogApiToken -eq $helpTxt.fogApiToken -OR $ServerSettings.fogUserToken -eq $helpTxt.fogUserToken -OR $ServerSettings.fogServer -eq $helpTxt.fogServer -or ([string]::IsNullOrEmpty($ServerSettings.fogApiToken)) -OR ([string]::IsNullOrEmpty($ServerSettings.fogUserToken)) -OR ([string]::IsNullOrEmpty($ServerSettings.fogServer)) ) { Write-Host -BackgroundColor Yellow -ForegroundColor Red -Object "a fog setting is either null or still set to its default help text, opening the settings file for you to set the settings" Write-Host -BackgroundColor Yellow -ForegroundColor Red -Object "This script will close after opening settings in notepad, please re-run command after updating settings file"; if ($isLinux) { if (Get-Command nano) { $editor = 'nano'; } else { $editor = 'vi'; } } elseif($IsMacOS) { $editor = 'TextEdit'; } else { if ((Get-Command 'code.exe')) { $editor = 'code.exe'; } else { $editor = 'notepad.exe'; } } Start-Process -FilePath $editor -ArgumentList "$SettingsFile" -NoNewWindow -PassThru; return; } Write-Verbose "Writing new Settings"; $serverSettings | ConvertTo-Json | Out-File -FilePath $settingsFile -Encoding oem -Force; Write-Verbose "ensuring security is set" Set-FogServerSettingsFileSecurity $settingsFile; return (Get-Content $settingsFile | ConvertFrom-Json); } } function Set-FogServerSettingsFileSecurity { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( $settingsFile = (Get-FogServerSettingsFile) ) process { if ($isLinux -or $IsMacOS) { Write-Verbose "Setting linux permissions on api settings file so only owner has rw"; chmod 600 $settingsFile } else { Write-Verbose "Setting read/write permissions for owner only on api settings file"; #Get current ACL to file/folder $acl = Get-Acl $settingsFile #Disable inheritance and remove inherited permissions $acl.SetAccessRuleProtection($true,$false) #Remove all explict ACEs $acl.Access | ForEach-Object { $acl.RemoveAccessRule($_) } #Create ACE for owner with full control $ace = New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $acl.Owner, "FullControl", "Allow" $acl.AddAccessRule($ace) #Save ACL to file/ try { Set-Acl -Path $settingsFile -AclObject $acl } catch { icacls "$settingsFile" /reset /Q /C icacls "$settingsFile" /setowner $env:USERNAME /Q /C icacls "$settingsFile" /inheritance:r /Q /C icacls "$settingsFile" /grant "$env:USERNAME`:F" /Q /C icacls "$settingsFile" /remove 'System' /Q /C icacls "$settingsFile" /remove 'Administrators' /Q /C } } } } function Set-FogSetting { # .ExternalHelp FogApi-help.xml [CmdletBinding(DefaultParameterSetName='byname')] param ( [Parameter(ParameterSetName='byname')] [ArgumentCompleter({ param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams) $r = Get-FogSettings; # $r = $settings.Name.trim(); if ($WordToComplete) { $r.Name.Where{ $_ -match "^$WordToComplete" } } else { $r.Name } })] $settingName, [Parameter(ParameterSetName='byId')] $settingID, [Parameter(ParameterSetName='byObj',ValueFromPipeline=$true)] $settingObj, $value ) process { if ($PSCmdlet.ParameterSetName -eq 'byObj') { if ($null -ne $_) { $settingObj = $_; } } switch ($PSCmdlet.ParameterSetName) { byname { $settingID = (Get-FogSetting -settingname $settingName).ID; } byId { $settingID = $settingID; } byObj { $settingID = $settingObj.id } } $jsonData = @{ id = $settingID; value = $value; } return Update-FogObject -type object -coreObject setting -IDofObject $settingID -jsonData ($jsonData | ConvertTo-Json) } } function Set-FogSnapins { # .ExternalHelp FogApi-help.xml [CmdletBinding()] [Alias('Add-FogSnapins')] param ( [parameter(ValueFromPipeline=$true,ParameterSetName='byObject')] $hostObj, [parameter(ParameterSetName='byId')] $hostid = ((Get-FogHost).id), [parameter(ParameterSetName='byId')] [parameter(ParameterSetName='byObject')] [ArgumentCompleter({ param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams) # if(Test-FogVerAbove1dot6) { $r = (Get-FogSnapins) if ($WordToComplete) { $r.Where.Name{ $_ -match "^$WordToComplete" } } else { $r.Name } # } })] [string[]]$pkgList, [parameter(ParameterSetName='byId')] [parameter(ParameterSetName='byObject')] [switch]$exactNames, [parameter(ParameterSetName='byId')] [parameter(ParameterSetName='byObject')] [switch]$repairBeforeAdd ) process { if ($null -ne $_) { $hostObj = $_; } if ($null -ne $hostObj) { $hostid = $hostObj.id; } Write-Verbose "Association snapins from package list with host"; if ($repairBeforeAdd) { try { Repair-FogSnapinAssociations -ea stop; } catch { Write-Warning "There was an issue running the repair command, still continuing to attempt to add new snapin associations" } } $snapins = Get-FogSnapins; # $urlPath = "snapinassociation/create" $curSnapins = Get-FogHostAssociatedSnapins -hostId $hostid; $results = New-Object System.Collections.Generic.List[Object]; if ($null -ne $pkgList) { $pkgList | ForEach-Object { if ($exactNames) { $json = @{ snapinID = "$((($snapins | Where-Object name -eq "$($_)").id))"; hostID = "$hostid" }; } else { $json = @{ snapinID = "$((($snapins | Where-Object name -match "$($_)").id))"; hostID = "$hostid" }; } Write-Verbose "$_ is pkg snapin id found is $($json.snapinID)"; if (($null -ne $json.SnapinID) -AND ($json.SnapinID -notin $curSnapins.id) -AND ($json.snapinID -ge "0")) { $json = $json | ConvertTo-Json; try { $result = New-FogObject -type object -coreObject snapinassociation -jsonData $json -ea stop $results.add($result); } catch { Write-Warning "Error adding snapin for $($_)!`npassed json was $($json)" } } elseif ($json.SnapinID -in $curSnapins.id) { Write-Warning "$_ snapin of id $($json.SnapinID) is already associated with this host"; } else { Write-Warning "no snapin ID found for $_ pkg"; } # Invoke-FogApi -Method POST -uriPath $urlPath -jsonData $json; } } return $results; } } function Set-WinToBootToPxe { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( ) process { if ($IsLinux -or $IsMacOS) { Write-Warning "This is currently only implemented for windows" return $null; } else { $pxeID = Get-WinBcdPxeId; if ($Null -ne $pxeID) { $addFirst = (bcdedit /set "{fwbootmgr}" displayorder $pxeID /addfirst) $fwboot = (bcdedit /enum "{fwbootmgr}") if ($fwboot -match "bootsequence") { $removeRunOnce = (bcdedit /deletevalue "{fwbootmgr}" bootsequence); #remove any run once boot options } else { $removeRunOnce = "bootsequence value not present"; } Write-Verbose "Remove Run Once options result: $removeRunOnce" return "Setting path result: $setPath`nAdd first result: $addFirst`nRemove Run Once options result: $removeRunOnce" } else { Write-Warning "No pxe boot option was found! Nothing was done!" return $null; } } } } function Start-FogSnapin { # .ExternalHelp FogApi-help.xml [CmdletBinding(DefaultParameterSetName='byId')] param ( [parameter(ParameterSetName='byId')] [parameter(ParameterSetName='byName')] $hostID, [parameter(ValueFromPipeline=$true,ParameterSetName='byId-byobj')] [parameter(ValueFromPipeline=$true,ParameterSetName='byName-byobj')] $fogHost, [parameter(ParameterSetName='byName')] [parameter(ParameterSetName='byName-byobj')] [ArgumentCompleter({ param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams) # if(Test-FogVerAbove1dot6) { $r = (Get-FogSnapins) if ($WordToComplete) { $r.Where.Name{ $_ -match "^$WordToComplete" } } else { $r.Name } # } })] [string[]]$snapinname, [parameter(ParameterSetName='byId')] [parameter(ParameterSetName='byId-byobj')] [string[]]$snapinId ) process { if ($null -ne $_) { $fogHost = $_; $hostID = $fogHost.id; } $snapins = Get-FogSnapins; if (($PSCmdlet.ParameterSetName -eq 'byName') -OR ($PSCmdlet.ParameterSetName -eq 'byName-byObj')) { # $snapin = "$((($snapins | Where-Object name -eq "$($_)")))"; $snapinIDs = New-Object System.Collections.Generic.List[Object]; $snapinname | ForEach-Object { $snapinIds.add(("$((($snapins | Where-Object name -eq "$($_)").id))")) } # $snapinId = $snapinIDs -join "," # "$snapinID" | out-host; # $snapinname = $snapinname } else { # $snapinID | ForEach-Object { # } $snapin = $snapins | Where-Object id -in $snapinId; $snapinname = $snapin.name } if (($null -eq $snapinId) -and ($null -eq $snapinIDs)) { Write-Warning "No snapinid was found for the snapin $snapinName! not running any actions" return $null } else { if ($null -ne $snapinIDs) { $snapinID = $snapinIDs } $results = New-Object System.Collections.Generic.List[Object]; $snapinId | ForEach-Object { $json = (@{ "taskTypeID"='13'; "deploySnapins"="$_"; } | ConvertTo-Json); if ($null -eq $fogHost) { $fogHost = Get-Foghost -hostID $hostID; } $snapinname = ($snapins | Where-Object id -in $_).name "Deploying the snapin $snapinname to the host $($fogHost.name)" | out-host; $result = New-FogObject -type objecttasktype -coreTaskObject host -jsonData $json -IDofObject "$hostID"; $results.add(($result)); } return $results; } } } function Start-FogSnapins { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [parameter(ValueFromPipeline=$true,ParameterSetName='byObj')] $fogHost, [parameter(ParameterSetName='byid')] $hostid = ((Get-FogHost).id), $taskTypeid = '12' ) process { if ($null -ne $_) { $fogHost = $_; $hostid = $fogHost.id; } Write-Verbose "Stopping any queued snapin tasks"; try { $tasks = Get-FogActiveTasks; } catch { $tasks = (Invoke-FogApi -Method GET -uriPath "task/active").tasks; } $tasks = $tasks | Where-Object { $_.type.id -match $taskTypeid} #filter task list to all snapins task. $taskID = (($tasks | Where-Object hostID -match $hostid).id); if ($null -ne $taskID) { #if active snapin tasks are found for the host cancel them, otherwise do nothing to tasks Write-Verbose "Found $($taskID.count) tasks deleting them now"; $taskID | ForEach-Object{ try { Remove-FogObject -type objecttasktype -coreTaskObject task -IDofObject $_; } catch { Invoke-FogApi -Method DELETE -uriPath "task/$_/cancel"; } } } # $snapAssocs = Invoke-FogApi -uriPath snapinassociation -Method Get; # $snaps = $snapAssocs.snapinassociations | ? hostid -eq $hostid; Write-Verbose "starting all snapin task for host"; $json = (@{ "taskTypeID"=$taskTypeid; "deploySnapins"=-1; } | ConvertTo-Json); $result = New-FogObject -type objecttasktype -coreTaskObject host -jsonData $json -IDofObject $hostid; Write-Verbose "Snapin tasks have been queued on the server"; return $result; } } function Test-FogVerAbove1dot6 { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( ) process { if ((Get-FogVersion -wa 0 -ea 0 -nowarning) -notlike "1.5*") { return $true; } else { return $false; } } } function Test-StringNotNullOrEmpty { # .ExternalHelp FogApi-help.xml [CmdletBinding()] param ( [parameter(ValueFromPipeline=$true)] $str ) process { $valid = $false; if ($null -eq $str) { $isString = $false; } elseif (($str.gettype().name) -eq "String") { $isString = $true; } else { $isString = $false; } if ($isString) { $empty = [string]::IsNullOrEmpty($str) $whitespace = [string]::IsNullOrWhiteSpace($str) } else { $valid = $false; } if (!$empty -and !$whitespace -and $isString) { $valid = $True; } return $valid; } } function Update-FogObject { # .ExternalHelp FogApi-help.xml [CmdletBinding()] [Alias('Set-FogObject')] param ( # The type of object being requested [Parameter(Position=0)] [ValidateSet("object")] [string]$type, # The json data for the body of the request [Parameter(Position=2)] [Object]$jsonData, # The id of the object to remove [Parameter(Position=3)] [string]$IDofObject, [Parameter(Position=4)] [string]$uri ) DynamicParam { $paramDict = Set-DynamicParams $type; return $paramDict; } process { $paramDict | ForEach-Object { New-Variable -Name $_.Keys -Value $($_.Values.Value);} Write-Verbose "Building uri and api call"; if([string]::IsNullOrEmpty($uri)) { $uri = "$CoreObject/$IDofObject/edit"; } $apiInvoke = @{ uriPath=$uri; Method="PUT"; jsonData=$jsonData; } $result = Invoke-FogApi @apiInvoke; return $result; } } function Export-FogImageDefinitions { <# .SYNOPSIS Create an export of image definitions for later import for syncing across sites or migrating to a new server .DESCRIPTION Creates .json files of image definitions on your server .PARAMETER exportPath Parameter description .EXAMPLE An example .NOTES General notes #> [CmdletBinding()] param ( $exportPath ) process { if ($IsLinux -AND ($env:HOSTNAME -match (Get-FogServerSettings).fogserver) -AND ([string]::IsNullOrEmpty($exportPath))) { "This is linux, is the fogserver set in the api settings and no export path was given" | Out-Host; "Assuming you want to create a /images/imageDefinitions folder for migrating your fog server images to another server" | out-host; $exportPath = "/images/imageDefinitions" if (!(Test-Path $exportPath)) { mkdir $exportPath; } } #get current image definitions from fog server $images = Get-FogImages; #Get any files currently in the export path $curExportFiles = (Get-ChildItem $exportPath\*.json); $curExports = New-Object System.Collections.Generic.list[system.object]; $curExportFiles | ForEach-Object { $curExports.add((Get-content $_.FullName | ConvertFrom-Json)) } # $imagesToExport = New-Object System.Collections.Generic.list[system.object]; $images | ForEach-Object { if ($_.name -in $curExports.name) { Write-Verbose "Image of $($_.name) already has an export, checking if it is newer" $curExportDate = Get-date $curExports.deployed; $newImageDate = Get-Date $_.deployed if ($newImageDate -gt $curExportDate) { Write-Verbose "The image has been captured more recently than the export" $_ | ConvertTo-Json | Out-File -Encoding oem -FilePath "$exportPath\$($_.name).json" -force } else { Write-Verbose "no need to export $($_.name) the exported definition is up to date" } } else { $_ | ConvertTo-Json | Out-File -Encoding oem -FilePath "$exportPath\$($_.name).json" } } } } function Get-DynmicParam { <# .SYNOPSIS Gets the dynamic parameter for the main functions .DESCRIPTION Dynamically sets the correct tab completeable validate set for the coreobject, coretaskobject, coreactivetaskobject, or string to search .PARAMETER paramName the name of the parameter being dynamically set within the validate set .PARAMETER position the position to put the dynamic parameter in #> [CmdletBinding()] param ( [Parameter(Position=0)] [ValidateSet('coreObject','coreTaskObject','coreActiveTaskObject')] [string]$paramName, $position=1 ) begin { #initilzie objects $attributes = New-Object Parameter; #System.Management.Automation.ParameterAttribute; $attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute] # $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary # Set attributes $attributes.Position = $position; $attributes.Mandatory = $true; $attributeCollection.Add($attributes) if ((Get-FogVersion) -like '1.6*') { $coreObjects = @( "group", "groupassociation", "history", "hookevent", "host", "hostautologout", "hostscreensetting", "image", "imageassociation", "imagepartitiontype", "imagetype", "imaginglog", "inventory", "ipxe", "keysequence", "macaddressassociation", "module", "moduleassociation", "multicastsession", "multicastsessionassociation", "nodefailure", "notifyevent", "os", "oui", "plugin", "powermanagement", "printer", "printerassociation", "pxemenuoptions", "scheduledtask", "setting", "snapin", "snapinassociation", "snapingroupassociation", "snapinjob", "snapintask", "storagegroup", "storagenode", "task", "tasklog", "taskstate", "tasktype", "unisearch", "user", "usertracking", "setting", "user" ); } else { $coreObjects = @( "clientupdater", "dircleaner", "greenfog", "group", "groupassociation", "history", "hookevent", "host", "hostautologout", "hostscreensetting", "image", "imageassociation", "imagepartitiontype", "imagetype", "imaginglog", "inventory", "ipxe", "keysequence", "macaddressassociation", "module", "moduleassociation", "multicastsession", "multicastsessionassociation", "nodefailure", "notifyevent", "os", "oui", "plugin", "powermanagement", "printer", "printerassociation", "pxemenuoptions", "scheduledtask", "service", "setting", "snapin", "snapinassociation", "snapingroupassociation", "snapinjob", "snapintask", "storagegroup", "storagenode", "task", "tasklog", "taskstate", "tasktype", "unisearch", "user", "usercleanup", "usertracking", "virus" ); } $coreTaskObjects = @("group", "host", "multicastsession", "scheduledtask", "snapinjob", "snapintask", "task"); $coreActiveTaskObjects = @("multicastsession", "powermanagement", "scheduledtask", "snapinjob", "snapintask", "task"); } process { switch ($paramName) { coreObject { $attributeCollection.Add((New-Object ValidateSet($coreObjects)));} coreTaskObject {$attributeCollection.Add((New-Object ValidateSet($coreTaskObjects)));} coreActiveTaskObject {$attributeCollection.Add((New-Object ValidateSet($coreActiveTaskObjects)));} } $dynParam = New-Object System.Management.Automation.RuntimeDefinedParameter($paramName, [string], $attributeCollection); # $paramDictionary.Add($paramName, $dynParam); } end { return $dynParam; } } function Set-DynamicParams { <# .SYNOPSIS Sets the dynamic param dictionary .DESCRIPTION Sets dynamic parameters inside functions .PARAMETER type the type of parameter #> [CmdletBinding()] param ($type) $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary; # Sub function for setting function Set-Param($paramName) { $param = Get-DynmicParam -paramName $paramName; $paramDictionary.Add($paramName, $param); } switch ($type) { object { Set-Param('coreObject');} objectactivetasktype { Set-Param('coreActiveTaskObject');} objecttasktype {Set-Param('coreTaskObject');} search {Set-Param('coreObject');} } return $paramDictionary; } |