Atempo.Lina.psm1
<#
.Synopsis This Windows PowerShell module contains PowerCLI Cloud Infrastructure Suite cmdlets. .Description Provide basic management of Lina Agents .Example # Getting list of agents Connect-LinaServer -Server "https://10.0.0.1:8181" -User "superadmin" -Password "MyPassword" Get-LinaAgent Disconnect-LinaServer #> <# TODO Add an option for mass delete of agents and/or improve multiple objects in pipeline Set Silent returns in imbricated functions (see in New-LinaAgent for example) Get locales for default stragies names (locale/en.js for example) Ability to pipe commands Improved error reporting #> <# 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:GLOBAL_SKIP_CERT = "" <# Disable Certificate checking for WebRequest (Pre-PowerShell 6.0) #> add-type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertsPolicy : ICertificatePolicy { public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } "@ [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" <# Disable Certificate checking for WebRequest (PowerShell >= 6.0) #> if ($PSVersionTable.PSVersion.Major -ge 6) { $GLOBAL_SKIP_CERT = "-SkipCertificateCheck" } else { $GLOBAL_SKIP_CERT = "" } 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 LinaTimestamp { return [math]::Round((New-TimeSpan -Start (Get-Date "01/01/1970") -End (Get-Date)).TotalSeconds*1000) } function Connect-LinaServer { [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)] [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-Host "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 if ([string]$request -like "*- OK*") { Write-Host "Successfully connected." } else { Write-Host "Error occurred trying to connect : \$request\" } } function Disconnect-LinaServer { Write-Host "Disconnecting from Lina server $GLOBAL_LINA_SERVER" $request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/ADE/logout.json" -WebSession $LoggedSession if ([string]$request -like "*- OK*") { Write-Host "Successfully disconnected." } else { Write-Host "Error occurred trying to disconnect : \$request\" } } function Get-LinaGlobalStats { Write-Host "Getting global stats" $request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/info.xml" -ContentType "application/xml" -WebSession $LoggedSession $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 { [cmdletbinding(DefaultParameterSetName="ByName")] Param( [Parameter(ParameterSetName="ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName="ByID")] [ValidateRange(0,2147483647)] [int]$ID ) Write-Host "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 $Items = ([xml]$request).HNConfig.ClientArray.Client $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 TenantID = $Item.DomainID Strategy = $Item.ServiceProfile.Name Protection = $Item.DataProfile.Name } $LinaItems += $CurrentLinaItem } } Return $LinaItems } function Get-LinaStrategy { [cmdletbinding()] Param( [Parameter(ParameterSetName="Name")] [ValidateNotNullOrEmpty()] [string]$Name ) Write-Host "Getting list of strategies" $timestamp = LinaTimestamp $request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/lst_serviceprofiles.xml?timestamp=$timestamp" -ContentType "application/xml" -WebSession $LoggedSession $Items = ([xml]$request).HNConfig.ServiceProfileArray.ServiceProfile $LinaItems = @() foreach ($Item in $Items) { if (!$Name -OR $Item.name -like "$Name") { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaStrategy' ID = $Item.ID Name = $Item.Name RPOInMinutes = ($Item.ParamSchedule/60) RetentionInDays = $Item.ParamDataAging } $LinaItems += $CurrentLinaItem } } Return $LinaItems } function Get-LinaTenant { [cmdletbinding(DefaultParameterSetName="ByName")] Param( [Parameter(ParameterSetName="ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName="ByID")] [ValidateNotNullOrEmpty()] [int]$ID ) Write-Host "Getting list of tenants" $timestamp = LinaTimestamp $request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/ADM/list_domain.json?timestamp=$timestamp" -ContentType "application/json" -WebSession $LoggedSession $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 { [cmdletbinding(DefaultParameterSetName="ByName")] Param( [Parameter(ValueFromPipeline)] [pscustomobject]$lina_agent, [Parameter(ParameterSetName="ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName="ByID")] [ValidateRange(0,2147483647)] [int]$ID ) Write-Host "Getting agents info" $timestamp = LinaTimestamp $request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/stats_clients.xml?timestamp=$timestamp" -ContentType "application/xml" -WebSession $LoggedSession $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 = $Item.AdminServiceProfileName Protection = $Item.AdminDataProfileName LastLogon = $Item.LastLogon Alert = $Item.Alert LastStartedSession = LinaToLocalTime $Item.LastStartedSession LastCompletedSession = LinaToLocalTime $Item.LastCompletedSession LastConnectionTime = LinaToLocalTime $Item.LastConnectionTime LastSyncTime = LinaToLocalTime $Item.LastSyncTime } $LinaItems += $CurrentLinaItem } } Return $LinaItems } function New-LinaAgent { [cmdletbinding()] Param( [Parameter(Mandatory=$true,ParameterSetName="Name")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(Mandatory=$false,ParameterSetName="Name")] [ValidateNotNullOrEmpty()] [string]$TenantName ) Write-Host "Creating a Lina agent named $Name" $current_tenant = Get-LinaCurrentTenant if (!$TenantName) { <# Getting default Tenant infos #> $domain = Get-LinaTenant | Where-Object {$_.IsDefault} $domain_id=[int]$domain.TenantID $domain_name=[string]$domain.Name Write-Host "No tenant selected, agent will be created in default tenant $domain_name (ID $domain_id)" }else { $domain = Get-LinaTenant | Where-Object {$_.Name -eq $TenantName} $domain_id=[int]$domain.TenantID $domain_name=[string]$domain.Name if ( !($domain_id -gt 0) ) { Write-Host "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 $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 $going_back = $current_tenant | Set-LinaCurrentTenant if ([string]$request -like "*[0]*") { Write-Host "Agent $Name successfully created." Get-LinaAgent -Name $Name Return } else { Write-Host "Error occurred trying to create agent $Name : \$request\" Return } } function Get-LinaCurrentTenant { Write-Host "Getting current tenant" $timestamp = LinaTimestamp $request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/ADE/check_session.xml?timestamp=$timestamp" -ContentType "application/xml" -WebSession $LoggedSession $current_tenant_id = [int](([xml]$request).session.effective_domain_id) if ($current_tenant_id -eq -1 -OR $current_tenant_id -eq 1) { Write-Host "No current tenant (ID = -1 or 1). Global view on all tenants." Return $current_tenant_id }elseif ($current_tenant_id -gt 1) { Write-Host "Current tenant ID is $current_tenant_id" Return Get-LinaTenant -ID $current_tenant_id } else { Write-Host "Error occurred trying to get current tenant : \$request\" Return 0 } } function Set-LinaCurrentTenant { [cmdletbinding(DefaultParameterSetName="ByName")] Param( [Parameter(ValueFromPipeline,ParameterSetName="ByObject")] [pscustomobject]$lina_tenant, [Parameter(Mandatory=$true,ParameterSetName="ByID")] [ValidateNotNullOrEmpty()] [string]$ID, [Parameter(Mandatory=$false,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-Host "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 if ($request.status -eq 0) { Write-Host "Current tenant has been set to tenant ID $ID" Return } else { Write-Host "Error occurred trying to set current tenant : \$request\" Return } } function Remove-LinaAgent { [cmdletbinding()] Param( [Parameter(ValueFromPipeline)] [pscustomobject]$lina_agent, [Parameter(ParameterSetName="Name")] [ValidateNotNullOrEmpty()] [string]$Name ) if ($lina_agent) { $Name = $lina_agent.Name} Write-Host "Deleting Lina agent named $Name" # If Agent is provided as an object no need to search for an ID if (!$lina_agent) { $timestamp = LinaTimestamp $request = Invoke-RestMethod -Uri "$GLOBAL_LINA_SERVER/lst_clients.xml?timestamp=$timestamp" -ContentType "application/xml" -WebSession $LoggedSession $Items = ([xml]$request).HNConfig.ClientArray.Client foreach ($Item in $Items) { if ($Item.Name -eq $Name) { $delete_id=$Item.ID Write-Host "Found agent named $Name with ID $delete_id" } } } else { $delete_id = $lina_agent.ID } if (!$delete_id) { Write-Host "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>' $request = Invoke-WebRequest -Uri "$GLOBAL_LINA_SERVER/mng_client.html" -Method "POST" -ContentType "application/xml" -Body $body -WebSession $LoggedSession if ([string]$request -like "*[0]*") { Write-Host "Agent $Name successfully deleted." Return } else { Write-Host "Error occurred trying to delete agent $Name : \$request\" Return } } } function Set-LinaAgent { [cmdletbinding()] Param( [Parameter(ParameterSetName="UpdateName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName="UpdateName")] [ValidateNotNullOrEmpty()] [string]$Newname ) Write-Host "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-Host "Found agent named $Name with ID $rename_id" } } if (!$rename_id) { Write-Host "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 if ([string]$request -like "*[0]*") { Write-Host "Agent $Name successfully renamed to $Newname." Return } else { Write-Host "Error occurred trying to delete agent $Name : \$request\" Return } } } |