Atempo.Lina.psm1
<#
.Synopsis Provides basic management CLI for Atempo Lina continuous data protection solution .Description Provides basic management CLI for Atempo Lina continuous data protection solution .Example # You may have to set the execution policy before using the module Set-ExecutionPolicy Unrestricted Connect-LinaServer -Server "https://10.0.0.1:8181" -User "superadmin" -Password "MyPassword" Get-LinaGlobalStats Get-LinaAgent Get-LinaAgentStats Get-LinaCurrentTenant Get-LinaStrategy Get-LinaTenant New-LinaAgent -Name "TEST-QA-API" Set-LinaAgent -Name "TEST-QA-API" -NewName "TEST-QA-API-RENAMED" Get-LinaAgent -Name "TEST-QA-API-RENAMED" | Remove-LinaAgent Get-LinaTenant -Name "BaasCustomer1" | Set-LinaCurrentTenant Get-LinaCurrentTenant Disconnect-LinaServer #> <# TODO improve global stats and agent stats manage display of replications missing objects (groups, paths, rules etc) Ability to pipe commands => should be done everywhere Improved error reporting (get error codes ?) #> <# Other URLS : Global stats / info.xml : Objects in infolist Protection / lst_dataprofiles.xml : Objects in HNConfig.DataProfileArray.DataProfile Protection rules / lst_filters.xml : Objects in HNConfig.FilterRuleArray.FilterRule Paths / lst_predefinedpaths.xml : Objects in HNConfig.PredefinedPathArray.PredefinedPath File Types / lst_filetypes.xml : Objects in HNConfig.FileTypeArray.FileType Agent groups / lst_hierarchies.xml : Objects in HNConfig.HierarchyArray.Hierarchy User groups / ADM/list_user_group.json : Objects in user_groups Groups to users / ADM/list_prof_ug_relation.json : Objects in relations #> # Needed for URLEncode Add-Type -AssemblyName System.Web $global:LoggedSession = $null $global:GLOBAL_LINA_SERVER = $null $global:LINA_TRANSLATIONS = $null $global:GLOBAL_IGNORE_CERTIFICATES = $True function Get-LinaHelp() { <# .SYNOPSIS Opens the HTML help of this module. .DESCRIPTION Opens the HTML help file located in the module folder with default browser. .INPUTS None .OUTPUTS None .EXAMPLE Get-LinaHelp Opens the HTML help file located in the module folder with default browser. #> $current_modulepath = Split-Path $script:MyInvocation.MyCommand.Path Start-Process "$current_modulepath\help.html" } function Disable-SslVerification { if (-not ([System.Management.Automation.PSTypeName]"TrustEverything").Type) { Add-Type -TypeDefinition @" using System.Net.Security; using System.Security.Cryptography.X509Certificates; public static class TrustEverything { private static bool ValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; } public static void SetCallback() { System.Net.ServicePointManager.ServerCertificateValidationCallback = ValidationCallback; } public static void UnsetCallback() { System.Net.ServicePointManager.ServerCertificateValidationCallback = null; } } "@ } [TrustEverything]::SetCallback() } function Enable-SslVerification { if (([System.Management.Automation.PSTypeName]"TrustEverything").Type) { [TrustEverything]::UnsetCallback() } } function CallAPI(){ [cmdletbinding()] Param( [Parameter(Mandatory=$True,Position=0)] [ValidateNotNullOrEmpty()] [string]$Path, [Parameter(Mandatory=$False,Position=1)] [ValidateNotNullOrEmpty()] [string]$ContentType, [Parameter(Mandatory=$False,Position=2)] [ValidateNotNullOrEmpty()] [string]$Body, [Parameter()] [switch]$FirstConnection ) if ($Path -like "*.json*") { $ContentType="application/json" }else { # most content is XML so this is default $ContentType="application/xml" } if ($FirstConnection) { if ($PSVersionTable.PSVersion.Major -lt 6 -AND $GLOBAL_IGNORE_CERTIFICATES) { <# Disable Certificate checking for WebRequest (Pre-PowerShell 6.0) #> Disable-SslVerification $request = Invoke-RestMethod -Uri $GLOBAL_LINA_SERVER$Path -SessionVariable Currentsession } elseif ($GLOBAL_IGNORE_CERTIFICATES) { <# Disable Certificate checking for WebRequest (PowerShell >= 6.0) #> $request = Invoke-RestMethod -Uri $GLOBAL_LINA_SERVER$Path -SessionVariable Currentsession -SkipCertificateCheck }else { # Certificate check is enabled $request = Invoke-RestMethod -Uri $GLOBAL_LINA_SERVER$Path -SessionVariable Currentsession } Set-Variable -name LoggedSession -Scope global -Value $Currentsession } else { # Next connections reuse the Session Cookie set globally if ($PSVersionTable.PSVersion.Major -ge 6 -AND $GLOBAL_IGNORE_CERTIFICATES) { <# Disable Certificate checking for WebRequest (PowerShell >= 6.0) #> $request = Invoke-RestMethod -Uri $GLOBAL_LINA_SERVER$Path -ContentType $ContentType -Method "Post" -Body $Body -WebSession $LoggedSession -SkipCertificateCheck }else { # Same request if enabled or not. Checkingt is disabled globally on PowerShell > 6.0 $request = Invoke-RestMethod -Uri $GLOBAL_LINA_SERVER$Path -ContentType $ContentType -Method "Post" -Body $Body -WebSession $LoggedSession } } Return $request } function LinaToLocalTime ($lina_time) { <# Lina Times are UTC based ? Not GMT ?#> $date=(Get-Date 01.01.1970)+([System.TimeSpan]::fromseconds($lina_time/1000)) $oFromTimeZone = [System.TimeZoneInfo]::FindSystemTimeZoneById("UTC") $oToTimeZone = [System.TimeZoneInfo]::FindSystemTimeZoneById([System.TimeZoneInfo]::Local.Id) $utc = [System.TimeZoneInfo]::ConvertTimeToUtc($date, $oFromTimeZone) $newTime = [System.TimeZoneInfo]::ConvertTime($utc,$oToTimeZone) return $newTime } function InitTranslations() { Param( [Parameter(Mandatory=$True,Position=0)] [ValidateNotNullOrEmpty()] [string]$Lang ) $request = CallAPI "/Admin/locale/$lang.js" # Web request does not like the encoding on this one ! $temp_utf = [System.Text.Encoding]::UTF8.GetString([System.Text.Encoding]::GetEncoding(28591).GetBytes($request.ToString())) $temp_split = $temp_utf -split '\n' $lines = ($temp_split | Select-String -Pattern "SERVER_NAME_","UNCAT_AGENTS_LABEL" ).line $translations = @{} foreach ($line in $lines) { $splitted = $line -split ': "' $key = $splitted[0].Trim().Replace('SERVER_NAME_','').Replace("__","_") $value = $splitted[1].Replace('",','').Trim() $translations.add($key,$value) } Set-Variable -name LINA_TRANSLATIONS -Scope global -Value $translations } function Translate() { Param( [Parameter(Mandatory=$True,Position=0)] [ValidateNotNullOrEmpty()] [string]$ToTranslate ) $ToTranslate = $ToTranslate.TrimStart("_").TrimEnd("_") if ($ToTranslate -eq "UNCAT") { $ToTranslate = "UNCAT_AGENTS_LABEL"; } $translated = $LINA_TRANSLATIONS[$ToTranslate.Replace("__","_")] if ($translated) { return $translated }else { # No translation available. Use original text. return $ToTranslate } } function LinaTimestamp { return [math]::Round((New-TimeSpan -Start (Get-Date "01/01/1970") -End (Get-Date)).TotalSeconds*1000) } function Connect-LinaServer { <# .SYNOPSIS Connects to an Atempo Lina server. .DESCRIPTION Connects to an Atempo Lina server 5.0+ usually using superadmin credentials. Select your locale using the -Locale switch. Locale is used only to display the default strategies and protections with localized names. Please note : there is no support for multiple connections to different or same server. .INPUTS None .OUTPUTS None .PARAMETER Server Specify the IP address or the DNS name of the Lina server to which you want to connect. Also specify the protocol and ports. For example : https://10.0.0.1:8181 or http://10.0.0.1:8181 .PARAMETER User Specify the user name you want to use for authenticating with the server. .PARAMETER Password Specifies the password you want to use for authenticating with the server. .PARAMETER Locale Specifies the language that will be used for default strategies and protections labels. Optional. Default value is English. Possible values are : "en","fr","es","de" .PARAMETER Tenant Select a specific tenant for actions (listing, creation will be limited to this tenant) Optional. Default value is -1 (All tenant / Global view) .EXAMPLE Connect-LinaServer -Server "https://mylinaserver.domain.com:8181" -User "superadmin" -Password "mypassword" Connection to mylinaserver.domain.com using default locale and global view (no tenant). .EXAMPLE Connect-LinaServer -Server "https://mylinaserver.domain.com:8181" -User "superadmin" -Password "mypassword" -Locale "fr" -Tenant "MyTenant" Connection to mylinaserver.domain.com using french language and filtered on the tenant MyTenant. #> [cmdletbinding()] Param( [Parameter(ParameterSetName="Server",Position=0)] [ValidateNotNullOrEmpty()] [string]$Server, [Parameter(ParameterSetName="Server",Position=1)] [ValidateNotNullOrEmpty()] [string]$User, [Parameter(ParameterSetName="Server",Position=2)] [ValidateNotNullOrEmpty()] [string]$Password, [Parameter(Mandatory=$false,ParameterSetName="Server",Position=3)] [ValidateSet("en","fr","es","de")] [string]$Locale="en", [Parameter(Mandatory=$false,ParameterSetName="Server",Position=4)] [ValidateNotNullOrEmpty()] [string]$Tenant ) Set-Variable -name GLOBAL_LINA_SERVER -Scope global -Value $Server $userenc=[System.Web.HttpUtility]::UrlEncode($User) $passenc=[System.Web.HttpUtility]::UrlEncode($Password) Write-Output "Connecting to Lina server $GLOBAL_LINA_SERVER" #$request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/ADE/login.html?user=$userenc&password=$passenc" -SessionVariable Currentsession #Set-Variable -name LoggedSession -Scope global -Value $Currentsession $request = CallAPI -Path "/ADE/login.html?user=$userenc&password=$passenc" -FirstConnection if ([string]$request -like "*- OK*") { InitTranslations($Locale) Write-Output "Successfully connected." } else { Write-Output "Error occurred trying to connect : \$request\" } } function Disconnect-LinaServer { <# .SYNOPSIS Disconnects from an Atempo Lina server. .DESCRIPTION Disconnects current session. .INPUTS None .OUTPUTS None .EXAMPLE Disconnect-LinaServer Disconnects current session. #> Write-Output "Disconnecting from Lina server $GLOBAL_LINA_SERVER" #$request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/ADE/logout.json" -WebSession $LoggedSession $request = CallAPI -Path "/ADE/logout.json" if ([string]$request -like "*- OK*") { Write-Output "Successfully disconnected." } else { Write-Output "Error occurred trying to disconnect : \$request\" } } function Get-LinaGlobalStats { <# .SYNOPSIS Retrieves the global stats and configuration of the current Lina server. .DESCRIPTION Retrieves the global stats and configuration of the current Lina server such as the server version deduplication ratio, volume stored etc .INPUTS None .OUTPUTS LinaStats Object .EXAMPLE Get-LinaGlobalStats Retrieve global infos of current Lina Server .EXAMPLE $lina_version = (Get-LinaGlobalStats).ALNVersion Get current installed version of Lina sofware. #> Write-Output "Getting global stats" $request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/info.xml" -ContentType "application/xml" -WebSession $LoggedSession $request = CallAPI -Path "/info.xml" $stats = ([xml]$request).infolist $LinaStats = [PSCustomObject]@{ PSTypeName = 'LinaStats' ALNVersion = $stats.aln_version PercentDiskUse = $stats.disk_use DedupRatio = $stats.dedup_ratio DiskAvailableGB = [math]::Round(($stats.disk_avail)/(1024*1024*1024),2) VolumeProtectedGB = [math]::Round(($stats.vol_protected)/(1024*1024*1024),2) VolumeRestoredGB = [math]::Round(($stats.vol_restored)/(1024*1024*1024),2) VolumeStoredGB = [math]::Round(($stats.vol_stored)/(1024*1024*1024),2) VolumeProtectedMB = [math]::Round(($stats.vol_protected)/(1024*1024)) VolumeRestoredMB = [math]::Round(($stats.vol_restored)/(1024*1024)) VolumeStoredMB = [math]::Round(($stats.vol_stored)/(1024*1024)) } Return $LinaStats } function Get-LinaAgent { <# .SYNOPSIS Retrieves the agents on a Lina server. .DESCRIPTION Retrieves the agents on a Lina server. Returns a set of agents that correspond to the filter criteria provided .INPUTS LinaAgent Object .OUTPUTS Array of LinaAgent Objects .PARAMETER Name Name of the agent(s) to retrieve. Wildcards can be used. For example : *DESKTOP* .PARAMETER ID ID of the agent to retrieve. For example : 134. .EXAMPLE Get-LinaAgent -Name "TEST" Will retrieve the agent named "TEST" and display its properties. .EXAMPLE $agents_desktop = Get-LinaAgent -Name "*DESKTOP*" Will retrieve all the agents with DESKTOP inside their names. The list returned can be passed to other functions. .EXAMPLE Get-LinaAgent -Name "TEST" | Remove-LinaAgent Will get the agent named TEST then pass it to the next command for deletion. #> [cmdletbinding(DefaultParameterSetName="ByName")] Param( [Parameter(ParameterSetName="ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName="ByID")] [ValidateRange(0,2147483647)] [int]$ID ) Write-Output "Getting list of agents" $timestamp = LinaTimestamp #$request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/lst_clients.xml?timestamp=$timestamp&type=agent" -ContentType "application/xml" -WebSession $LoggedSession $request = CallAPI -Path "/lst_clients.xml?timestamp=$timestamp&type=agent" $Items = ([xml]$request).HNConfig.ClientArray.Client $Tenants = Get-LinaTenant $LinaItems = @() foreach ($Item in $Items) { <# Filtering on ID or Name (only if provided) #> if ((!$Name -AND !$ID) -OR ( $Item.Name -like "$Name" -OR $Item.ID -eq $ID)) { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaAgent' Name = $Item.Name ID = $Item.ID Tenant = $Tenants | where-object {$_.TenantID -eq $Item.DomainID} | Select-Object -ExpandProperty Name AgentGroup = Translate($Item.AttachementArray.Attachement.Group.Name) Strategy = Translate($Item.ServiceProfile.Name) Protection = Translate($Item.DataProfile.Name) StrategyName = $Item.ServiceProfile.Name ProtectionName = $Item.DataProfile.Name TenantID = $Item.DomainID AgentGroupID = $Item.AttachementArray.Attachement.Group.ID StrategyID = $Item.ServiceProfile.ID ProtectionID = $Item.DataProfile.ID } $LinaItems += $CurrentLinaItem } } Return $LinaItems } function Get-LinaStrategy { <# .SYNOPSIS Retrieves the strategies on a Lina server. .DESCRIPTION Retrieves the strategies on a Lina server. Returns a set of strategies that correspond to the filter criteria provided. .INPUTS None .OUTPUTS Array of LinaStrategy Objects .PARAMETER Name Optional : Name (label) of the strategy to retrieve. Wildcards can be used. For example : *STRAT* .EXAMPLE Get-LinaStrategy Will retrieve all the strategies. .EXAMPLE Get-LinaStrategy -Name "*STRAT*" Will retrieve all the strategies with STRAT inside their names. .EXAMPLE Get-LinaStrategy -Name "*STRAT*" | Select-Object -Property Name,RPOInMinutes Displays the list of strategies and their configured RPO in minutes. #> [cmdletbinding()] Param( [Parameter(ParameterSetName="Name")] [ValidateNotNullOrEmpty()] [string]$Name ) Write-Output "Getting list of strategies" $timestamp = LinaTimestamp #$request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/lst_serviceprofiles.xml?timestamp=$timestamp" -ContentType "application/xml" -WebSession $LoggedSession $request = CallAPI -Path "/lst_serviceprofiles.xml?timestamp=$timestamp" $Items = ([xml]$request).HNConfig.ServiceProfileArray.ServiceProfile $LinaItems = @() foreach ($Item in $Items) { if (!$Name -OR $Item.name -like "$Name") { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaStrategy' Label = Translate($Item.Name) ID = $Item.ID Name = $Item.Name RPOInMinutes = ($Item.ParamSchedule/60) RetentionInDays = $Item.ParamDataAging AlertAfterDays = ($Item.ParamAlertTime/(24*3600)) ThroughputLimitKBps = $Item.ParamThroughputLimit ReplicationTargets = $Item.RepliTarget.ID Encryption = [bool]$Item.ParamEncryptionActivated WanMode = [bool]$Item.ParamWanActivated CompressionAlgo = $Item.ParamCompression AllowClientRPO = [bool]$Item.ParamAllowClientRPO AllowClientRules = [bool]$Item.ParamAllowClientRules AllowClientPause = [bool]$Item.ParamAllowClientPause AllowClientBoost = [bool]$Item.ParamAllowClientBoost AllowClientNetworkParams = [bool]$Item.ParamAllowClientNetworkParams AllowWebAccess = [bool]$Item.ParamAllowWebAccess QuotaMaxProtSizeMB = [math]::Round(($Item.ParamQuotaMaxProtSize)/(1024*1024)) QuotaMaxProtObjs = $Item.ParamQuotaMaxProtObjs QuotaMaxHistSizeMB = [math]::Round(($Item.ParamQuotaMaxHistSize)/(1024*1024)) QuotaMaxHistObjs = $Item.ParamQuotaMaxHistObjs } $LinaItems += $CurrentLinaItem } } Return $LinaItems } function Get-LinaTenant { <# .SYNOPSIS Retrieves the tenants (entities) on a Lina server. .DESCRIPTION Retrieves the tenants (entities) on a Lina server. Returns a set of tenants that correspond to the filter criteria provided. .INPUTS None .OUTPUTS Array of LinaTenant Objects .PARAMETER Name Optional : Name of the tenant to retrieve. Wildcards can be used. For example : *Tenant* .PARAMETER ID Optional : ID of the tenant to retrieve. .EXAMPLE Get-LinaTenant Retrieve all tenants .EXAMPLE Get-LinaTenant -Name "BaasCustomer1" Retrieve Tenant named BaasCustomer1 .EXAMPLE Get-LinaTenant | where {$_.IsDefault} Retrieve the default tenant. #> [cmdletbinding(DefaultParameterSetName="ByName")] Param( [Parameter(ParameterSetName="ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName="ByID")] [ValidateNotNullOrEmpty()] [int]$ID ) Write-Output "Getting list of tenants" $timestamp = LinaTimestamp #$request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/ADM/list_domain.json?timestamp=$timestamp" -ContentType "application/json" -WebSession $LoggedSession $request = CallAPI -Path "/ADM/list_domain.json?timestamp=$timestamp" $Items = $request.domains $LinaItems = @() foreach ($Item in $Items) { if ((!$Name -AND !$ID) -OR $Item.name -like "$Name" -OR $Item.ID -eq $ID ) { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaTenant' TenantID = $Item.id UUID = $Item.uuid Name = $Item.name Comment = $Item.comment IsDefault = [bool]$Item.def_domain } $LinaItems += $CurrentLinaItem } } Return $LinaItems } function Get-LinaAgentStats { <# .SYNOPSIS Retrieves the agents statistics and advanced information on a Lina server. .DESCRIPTION Retrieves the agents statistics and advanced information on a Lina server. Statistics are only available for agent that have been online at least one time. .INPUTS None .OUTPUTS Array of LinaAgentInfos Objects .PARAMETER Name Name of the agent(s) to retrieve. Wildcards can be used. For example : *DESKTOP* .PARAMETER ID ID of the agent to retrieve. For example : 134. .EXAMPLE Get-LinaAgentStats Retrieve all agent stats .EXAMPLE Get-LinaAgentStats | where {$_.LastLogon -like "*mike*"} Retrieve agent info on agents where mike is logged in. .EXAMPLE Get-LinaAgentStats | where {$_.LastCompletedSession -le (Get-Date).AddDays(-7)} Retrieve agent info on agents with no completed backups in last 7 days #> [cmdletbinding(DefaultParameterSetName="ByName")] Param( [Parameter(ValueFromPipeline)] [pscustomobject]$lina_agent, [Parameter(ParameterSetName="ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName="ByID")] [ValidateRange(0,2147483647)] [int]$ID ) Write-Output "Getting agents Statistics (only available if has been online)" $timestamp = LinaTimestamp #$request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/stats_clients.xml?timestamp=$timestamp" -ContentType "application/xml" -WebSession $LoggedSession $request = CallAPI -Path "/stats_clients.xml?timestamp=$timestamp" $Items = ([xml]$request).Stats.ClientArray.Client $LinaItems = @() foreach ($Item in $Items) { <# Filtering on ID or Name (only if provided) #> if ((!$Name -AND !$ID -AND !$lina_agent) -OR ($Item.AdminName -like "$Name" -OR $Item.AdminID -eq $ID -OR $lina_agent.ID -eq $Item.AdminID ) ) { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaAgentInfos' Name = $Item.AdminName ID = $Item.AdminID ComputerName = $Item.ComputerName System = $Item.System AgentVersion = $Item.AgentVersion Strategy = Translate($Item.AdminServiceProfileName) Protection = Translate($Item.AdminDataProfileName) LastLogon = $Item.LastLogon Alert = $Item.Alert LastStartedSession = LinaToLocalTime $Item.LastStartedSession LastCompletedSession = LinaToLocalTime $Item.LastCompletedSession LastConnectionTime = LinaToLocalTime $Item.LastConnectionTime LastSyncTime = LinaToLocalTime $Item.LastSyncTime StrategyAdminName = $Item.AdminServiceProfileName ProtectionAdminName = $Item.AdminDataProfileName } $LinaItems += $CurrentLinaItem } } Return $LinaItems } function New-LinaAgent { <# .SYNOPSIS Creates a new agent. .DESCRIPTION Creates a new agent with the provided name. .INPUTS None .OUTPUTS LinaAgent Object .PARAMETER Name Name of the agent to create .PARAMETER TenantName Optional : Name of the tenant where the agent should be created. If not provided, agent will be created in the current tenant. In global view (no tenant), agent will be created in default tenant. .EXAMPLE New-LinaAgent -Name "TEST-CREATE" Creates a new agent in current tenant. .EXAMPLE New-LinaAgent -Name "TEST-CREATE2" -TenantName "MyTenant" Creates a new agent in tenant MyTenant #> [cmdletbinding()] Param( [Parameter(Mandatory=$true,ParameterSetName="Name")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(Mandatory=$false,ParameterSetName="Name")] [ValidateNotNullOrEmpty()] [string]$TenantName ) Write-Output "Creating a Lina agent named $Name" $current_tenant = Get-LinaCurrentTenant 6>$null if (!$TenantName) { if (!$current_tenant -OR $current_tenant.TenantID -le 1) { # No current tenant (global view) => using default tenant $domain = Get-LinaTenant 6>$null | Where-Object {$_.IsDefault} $domain_id=[int]$domain.TenantID $domain_name=[string]$domain.Name Write-Output "No tenant selected, agent will be created in default tenant $domain_name (ID $domain_id)" } else { # Using Current tenant $domain = Get-LinaCurrentTenant 6>$null $domain_id=[int]$domain.TenantID $domain_name=[string]$domain.Name Write-Output "No tenant selected, agent will be created in current tenant $domain_name (ID $domain_id)" } }else { $domain = Get-LinaTenant 6>$null | Where-Object {$_.Name -eq $TenantName} $domain_id=[int]$domain.TenantID $domain_name=[string]$domain.Name if ( !($domain_id -gt 0) ) { Write-Output "Error : No tenant found with name $TenantName. Please input the exact name of the Tenant" Return } } #Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/ADM/domain_set_current.json?domain_id=$domain_id" -ContentType "application/json" -WebSession $LoggedSession | Out-Null #CallAPI -Path "/ADM/domain_set_current.json?domain_id=$domain_id" Set-LinaCurrentTenant -ID $domain_id | Out-Null $body = 'data=<?xml version="1.0" encoding="UTF-8"?><HNConfig><Func>ADD</Func><Client><Name>'+$Name+'</Name></Client></HNConfig>' #$request = Invoke-WebRequest -Uri "$GLOBAL_LINA_SERVER/mng_client.html" -Method "POST" -ContentType "application/xml" -Body $body -WebSession $LoggedSession $request = CallAPI -Path "/mng_client.html" -ContentType "application/xml" -Body $body # Setting back the current tenant to what it was before the New-LinaAgent command $current_tenant | Set-LinaCurrentTenant | Out-Null if ([string]$request -like "*[0]*") { Write-Output "Agent $Name successfully created." $agent_created = Get-LinaAgent -Name $Name | Out-Null Return $agent_created } else { Write-Output "Error occurred trying to create agent $Name : \$request\" Return $null } } function Get-LinaCurrentTenant { <# .SYNOPSIS Get the current tenant .DESCRIPTION Get the current tenant. If current tenant is the Global View (no tenant selected), it will return 1 or -1. .INPUTS None .OUTPUTS Current tenant ID .EXAMPLE $current_tenant_id = Get-LinaCurrentTenant Get the current tenant ID. #> Write-Output "Getting current tenant" $timestamp = LinaTimestamp #$request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/ADE/check_session.xml?timestamp=$timestamp" -ContentType "application/xml" -WebSession $LoggedSession $request = CallAPI -Path "/ADE/check_session.xml?timestamp=$timestamp" $current_tenant_id = [int](([xml]$request).session.effective_domain_id) if ($current_tenant_id -eq -1 -OR $current_tenant_id -eq 1) { Write-Output "No current tenant (ID = -1 or 1). Global view on all tenants." Return $current_tenant_id }elseif ($current_tenant_id -gt 1) { Write-Output "Current tenant ID is $current_tenant_id" $current_tenant = Get-LinaTenant -ID $current_tenant_id Return $current_tenant } else { Write-Output "Error occurred trying to get current tenant : \$request\" Return $null } } function Set-LinaCurrentTenant { <# .SYNOPSIS Set the current tenant .DESCRIPTION Set the current tenant. When set, all listings and actions will be executed and filtered inside this tenant. To set the global view (view across all tenants), use the -All switch. .INPUTS LinaTenant Object .OUTPUTS None .PARAMETER ID ID of the tenant to set .PARAMETER All Switch to set the global view (view across all tenants). Available for superadmin only. .EXAMPLE Get-LinaTenant -Name "MyTenant" | Set-LinaCurrentTenant Set the current tenant to MyTenant .EXAMPLE Set-LinaCurrentTenant -All Enable global view across all tenants (superadmin only) .EXAMPLE Set-LinaCurrentTenant -ID 2 Set the current tenant to Tenant with ID 2 #> [cmdletbinding(DefaultParameterSetName="ByID")] Param( [Parameter(ValueFromPipeline,ParameterSetName="ByObject")] [pscustomobject]$lina_tenant, [Parameter(Mandatory=$true,ParameterSetName="ByID")] [ValidateNotNullOrEmpty()] [string]$ID, [Parameter(Mandatory=$true,ParameterSetName="All")] [ValidateNotNullOrEmpty()] [switch]$All ) # All tenants is 1 or -1 (no tenant selected, global view) if ($All) { $ID=1 }elseif ($lina_tenant -AND $lina_tenant.TenantID -ge 1) { $ID=$lina_tenant.TenantID }elseif (!$ID) { $ID=1 } Write-Output "Setting current tenant to Tenant ID $ID" #$request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/ADM/domain_set_current.json?domain_id=$ID" -ContentType "application/json" -WebSession $LoggedSession $request = CallAPI -Path "/ADM/domain_set_current.json?domain_id=$ID" if ($request.status -eq 0) { Write-Output "Current tenant has been set to tenant ID $ID" Return } else { Write-Output "Error occurred trying to set current tenant : \$request\" Return } } function Remove-LinaAgent { <# .SYNOPSIS Deletes a Lina Agent from a Lina Server. .DESCRIPTION Deletes a Lina Agent. Unique data will be reclaimed automatically by server after some time (configurable). .INPUTS Accept pipelining of LinaAgent objects (from Get-LinaAgent for example) .OUTPUTS None .PARAMETER Name Name of the agent to delete. Wildcards are accepted (don't forget to enable Bulk mode for actions on multiple agents). .PARAMETER WhatIf No actual deletion will happen if set. It will only display what agents would be deleted. Sometimes also called "Dry Run mode" .PARAMETER Bulk Security parameter to enable deletion of multiple agents. If not set only one agent will be deleted. .EXAMPLE Remove-LinaAgent -Name "AGENT132" Real deletion of a single agent by name .EXAMPLE Remove-LinaAgent -Name "AGENT1*" -Bulk -WhatIf Simulates deletion of a multiple agents by name (WhatIf mode) .EXAMPLE Remove-LinaAgent -Name "AGENT1*" -Bulk Real deletion of a multiple agents by name .EXAMPLE Get-LinaAgent -ID 164 | Remove-LinaAgent -WhatIf Real deletion of a single agent by piping it from a Get .EXAMPLE Get-LinaAgent -Name "TEST1*" | Remove-LinaAgent -Bulk -WhatIf Simulates deletion of multiple agents by piping them from a Get (WhatIf mode) #> [cmdletbinding(DefaultParameterSetName="ByName")] Param( [Parameter(ValueFromPipeline=$True,ParameterSetName="ByPipeline")] [pscustomobject[]]$LinaAgents, [Parameter(Mandatory=$True,ParameterSetName="ByName")] [ValidateNotNullOrEmpty()] [string]$AgentName, # Do not delete, only show will be done [Parameter(Mandatory=$False,ParameterSetName="ByPipeline")] [Parameter(Mandatory=$False,ParameterSetName="ByName")] [switch]$WhatIf, # Enable deleting multiple agents [Parameter(Mandatory=$False,ParameterSetName="ByPipeline")] [Parameter(Mandatory=$False,ParameterSetName="ByName")] [switch]$Bulk ) BEGIN {} PROCESS { $nb_of_agents_deleted=0 if (!$LinaAgents) { # Agents not pipelined => populate using name argument $LinaAgents = Get-LinaAgent -Name $AgentName 6>$null if (!$LinaAgents) { # No agent found by name Write-Output "WARNING : No agent found with this name." return } # We are sure that we have some agents so we continue $names=$LinaAgents.Name Write-Output "Deleting Lina agent(s) : $names" } foreach ($lina_agent in $LinaAgents) { # I don't know why but sometimes we go in foreach but element is empty ?! If(!$lina_agent.ID) { return } if ($nb_of_agents_deleted -ge 1 -AND !$Bulk) { Write-Output "WARNING : Bulk mode has not been enabled, only one agent will be deleted for security." return } $Name = $lina_agent.Name $delete_id = $lina_agent.ID if (!$delete_id) { Write-Output "WARNING : No agent found with this name." return }else { $body = 'data=<?xml version="1.0" encoding="UTF-8"?><HNConfig><Func>DEL</Func><Client><ID>'+$delete_id+'</ID></Client></HNConfig>' if (!$WhatIf) { #$request = Invoke-WebRequest -Uri "$GLOBAL_LINA_SERVER/mng_client.html" -Method "POST" -ContentType "application/xml" -Body $body -WebSession $LoggedSession $request = CallAPI -Path "/mng_client.html" -ContentType "application/xml" -Body $body }else { # WhatIf mode enabled => does not delete agent $request = "WHATIF" } if ([string]$request -like "*[0]*") { Write-Output "Agent $Name successfully deleted." } elseif ($request -eq "WHATIF") { Write-Output "Agent $Name will be deleted if not using 'WhatIf' mode" }else { Write-Output "Error occurred trying to delete agent $Name : \$request\" } } $nb_of_agents_deleted +=1 } } END {} } function Set-LinaAgent { <# .SYNOPSIS Changes the configuration of an agent. .DESCRIPTION Changes the configuration of an agent for example its name. .INPUTS None .OUTPUTS None .PARAMETER Name Name of the agent to modify .PARAMETER Newname New name to apply to the agent .EXAMPLE Set-LinaAgent -Name "TEST1" -NewName "TEST2" Changes the name of the agent from TEST1 to TEST2 #> [cmdletbinding()] Param( [Parameter(ParameterSetName="UpdateName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName="UpdateName")] [ValidateNotNullOrEmpty()] [string]$Newname ) Write-Output "Renaming Lina agent named $Name to new name $Newname" $Items = Get-LinaAgent foreach ($Item in $Items) { if ($Item.Name -eq $Name) { $rename_id=$Item.ID Write-Output "Found agent named $Name with ID $rename_id" } } if (!$rename_id) { Write-Output "WARNING : No agent found with this name." return }else { $body = 'data=<?xml version="1.0" encoding="UTF-8"?><HNConfig><Func>REN</Func><Client><ID>'+$rename_id+'</ID><Name>'+$Newname+'</Name></Client></HNConfig>' $timestamp = LinaTimestamp #$request = Invoke-WebRequest -Uri "$GLOBAL_LINA_SERVER/mng_client.html?timestamp=$timestamp" -Method "POST" -ContentType "application/xml" -Body $body -WebSession $LoggedSession $request = CallAPI -Path "/mng_client.html?timestamp=$timestamp" -ContentType "application/xml" -Body $body if ([string]$request -like "*[0]*") { Write-Output "Agent $Name successfully renamed to $Newname." Return } else { Write-Output "Error occurred trying to delete agent $Name : \$request\" Return } } } |