Functions/Get.ps1
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).LinaVersion Get current installed version of Lina sofware. #> Write-Verbose "Getting global stats" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($global:INT_LINA_API_VERSION -lt 60) { $request = CallAPI -Path "/info.json" $stats = $request } else { $request = CallAPI -Path "/ADE/info.json" $stats = $request } # Extract version number of Lina if ($stats.aln_version.IndexOf(' ') -gt 2) { # Extract version number $version_number=$stats.aln_version.Substring(0,$stats.aln_version.IndexOf(' ')) $second_part = $stats.aln_version.Substring($stats.aln_version.IndexOf(' ')+1) if ($second_part.IndexOf(' ') -gt 2) { # version is like "5.1.10.39537 Beta (51, 3a9e34b38, Feb 2 2021 11:14:06)" $version_qualifier = $second_part.Substring(0,$second_part.IndexOf(' ')) # Should not exist. Missing qualifier in new versions # Example : "5.1.10.39537 (51, 3a9e34b38, Feb 2 2021 11:14:06)" if ($version_qualifier -like "*(*") { $version_qualifier = "GA" } }else { # Version is like "5.1.10.39537 Beta" $version_qualifier = $second_part } }else { # Version is like "5.1.10.39537" $version_number=$stats.aln_version $version_qualifier="GA" } $LinaVersion = [version]$version_number if ($version_qualifier -ilike "*DEV*") { $LinaVersionType = "Beta" }elseif ($version_qualifier -ilike "*RC*") { $LinaVersionType = "Release Candidate" }elseif ($version_qualifier -ilike "*GA*") { $LinaVersionType = "Generally Available" }else { $LinaVersionType = "Special Version ($version_qualifier)" } <# <hss_version>5.2.1.12663 RC</hss_version> <aln_version>5.2.1.12663 RC</aln_version> <apr_version>1.7.0</apr_version> <db_version>sqlite 3.28.0</db_version> <hss_uuid>f27737b8-bf72-11ea-895e-43673f98433c</hss_uuid> <create_date>1594031100</create_date> <uptime>1623918111</uptime> <time_t>1623937989</time_t> <vol_read>1322777547974</vol_read> <vol_transfered>0</vol_transfered> <vol_written>73132294256</vol_written> <vol_restored>0</vol_restored> <vol_protected>56172007547</vol_protected> <vol_stored>22828584752</vol_stored> <vol_meta>46492939</vol_meta> <disk_avail>67324133376</disk_avail> <disk_use_byte>22875077691</disk_use_byte> <disk_use>25.36 %</disk_use> <disk_full>-1</disk_full> <last_week>31538518955</last_week> <nb_stream>5</nb_stream> <nb_block>557448</nb_block> <nb_block_unref>58250</nb_block_unref> <nb_client>1</nb_client> <nb_client_reached>1</nb_client_reached> <nb_max_client>256</nb_max_client> <nb_thread>72</nb_thread> <nb_max_thread>74</nb_max_thread> <net_bandwith>0.00</net_bandwith> <cpr_ratio>2.33:1</cpr_ratio> <dedup_ratio_real>2.45:1</dedup_ratio_real> <dedup_ratio>2.79:1</dedup_ratio> <cpu_usage>4</cpu_usage> <ram_usage>180</ram_usage> </infolist> #> $LinaStats = [PSCustomObject]@{ PSTypeName = 'LinaStats' LinaVersion = $LinaVersion ServerType = $stats.server_type LinaVersionType = $LinaVersionType PercentDiskUse = $stats.disk_use DiskFullForecastInDays = $stats.disk_full DedupRatio = $stats.dedup_ratio CompressionRatio = $stats.cpr_ratio DiskAvailableGB = [math]::Round(($stats.disk_avail) / (1024 * 1024 * 1024), 2) DiskSavingGB = [math]::Round(($stats.vol_protected - $stats.vol_stored) / (1024 * 1024 * 1024), 1) VolumeProtectedGB = [math]::Round(($stats.vol_protected) / (1024 * 1024 * 1024), 1) VolumeRestoredGB = [math]::Round(($stats.vol_restored) / (1024 * 1024 * 1024), 1) VolumeStoredGB = [math]::Round(($stats.vol_stored) / (1024 * 1024 * 1024), 1) VolumeProtectedMB = [math]::Round(($stats.vol_protected) / (1024 * 1024)) VolumeRestoredMB = [math]::Round(($stats.vol_restored) / (1024 * 1024)) VolumeStoredMB = [math]::Round(($stats.vol_stored) / (1024 * 1024)) LinaVersionFull = $stats.aln_version } Return $LinaStats } function Get-LinaSystemInfos { <# .SYNOPSIS Retrieves the system informations of the current Lina server. .DESCRIPTION Retrieves the system informations of the current Lina server such as the Operating system details and Hardware informations .INPUTS None .OUTPUTS LinaSysteminfo Object .EXAMPLE Get-LinaSystemInfo Retrieve system informations of current Lina Server .EXAMPLE (Get-LinaSystemInfo).PercentUsageRAM Get current usage of RAM on the server .EXAMPLE (Get-LinaSystemInfo).PercentUsageCPU Get current usage of CPU on the server #> Write-Verbose "Getting system informations" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($global:INT_LINA_API_VERSION -lt 60) { $request = CallAPI -Path "/sys.xml" $sysinfo = ([xml]$request).sysinfo } else { $request = CallAPI -Path "/ADE/sys.json" $sysinfo = $request.sysinfo } $machine_type = switch ($sysinfo.vm_type) { 1 {"Physical"; break} 2 {"VM (VMware)"; break} 3 {"VM (VirtualBox)"; break} 4 {"VM (KVM)"; break} 5 {"VM (Hyper-V)"; break} 6 {"VM (Xen)"; break} 7 {"VM (Windows Subsystem for Linux)"; break} default {"Unknown"; break} } # Avoid division by zero when there is no swap if ($sysinfo.swap_size -gt 0) { $PercentUsageSwap = [math]::Round($sysinfo.swap_free/$sysinfo.swap_size,2)*100 }else { $PercentUsageSwap = 0 } $LinaSysinfo = [PSCustomObject]@{ PSTypeName = 'LinaSysteminfo' CPUName = $sysinfo.cpu_name CPUCores = $sysinfo.cpu_count CPUClockMHz = $sysinfo.cpu_clock MemorySizeGB = [math]::Round($sysinfo.mem_size/1024,1) MemoryFreeGB = [math]::Round($sysinfo.mem_free/1024,1) SwapSizeGB = [math]::Round($sysinfo.swap_size/1024,1) SwapFreeGB = [math]::Round($sysinfo.swap_free/1024,1) OSArchitecture = $sysinfo.arch_name OSName = $sysinfo.os_name OSRelease = $sysinfo.os_release MachineType = $machine_type PercentUsageCPU = $sysinfo.cpu_usage PercentUsageRAM = [math]::Round($sysinfo.mem_free/$sysinfo.mem_size,2)*100 PercentUsageSwap = $PercentUsageSwap } Return $LinaSysinfo } function Get-LinaAgent { <# .SYNOPSIS Retrieves the agents. .DESCRIPTION Retrieves the agents. Returns a set of agents that correspond to the filter criteria provided .INPUTS None .OUTPUTS Array of LinaAgent Objects .PARAMETER Name Name of the agent(s) to retrieve. Wilcards are allowed. For example : *DESKTOP* .PARAMETER ID ID of the agent to retrieve. For example : 134. .PARAMETER Tag Exact tag of the agents to retrieve. For example : "MyTag". Must match exactly a Tag. .EXAMPLE Get-LinaAgent -Name "TEST" Retrieves the agent named "TEST" and display its properties. .EXAMPLE $agents_desktop = Get-LinaAgent -Name "*DESKTOP*" Retrieves all the agents with DESKTOP inside their names. The list returned can be passed to other functions. .EXAMPLE Get-LinaAgent | Where {$_.LastSyncTime -le ((Get-Date).AddDays(-14)) } | Select Name,Email,LastBackup,LastSyncTime | ft Retrieves all the agents without backups since last 14 days. .EXAMPLE $agents_desktop = Get-LinaAgent -Tag "MyLinuxAgents" Retrieves all the agents having a "MyLinuxAgents" tag assigned. 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", Position = 0)] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID, [Parameter(ParameterSetName = "ByTag")] [ValidateNotNullOrEmpty()] [string]$Tag ) Write-Verbose "Getting list of agents" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } $Tenants = Get-LinaTenant $LinaItems = @() if ($global:INT_LINA_API_VERSION -le 50 ) { $agentstats = Get-LinaAgentStats # Using API 5.0 (XML and dissociated agent and AgentStats) $request = CallAPI -Path "/lst_clients.xml?type=agent" $Items = ([xml]$request).HNConfig.ClientArray.Client foreach ($Item in $Items) { <# Filtering on ID or Name (only if provided) #> $Name_encoded = [System.Text.Encoding]::UTF8.GetString([System.Text.Encoding]::GetEncoding(28591).GetBytes($Item.Name)) if ((!$Name -AND !$ID) -OR ( $Item.Name -like "$Name" -OR $Name_encoded -like "$Name" -OR $Item.ID -eq $ID)) { $current_agentstat = $agentstats | where-object { $_.ID -eq $Item.ID } $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaAgent' Name = $Name_encoded ID = $Item.ID Tenant = $Tenants | where-object { $_.ID -eq $Item.DomainID } | Select-Object -ExpandProperty Name AgentGroup = Translate($Item.AttachementArray.Attachement.Group.Name) Strategy = Translate($Item.ServiceProfile.Name) Protection = Translate($Item.DataProfile.Name) ComputerName = $current_agentstat.ComputerName System = $current_agentstat.System SystemCategory = TranslateSystemCategories($current_agentstat.SystemCategory) AgentVersion = $current_agentstat.AgentVersion LastLogon = $current_agentstat.LastLogon Email = $current_agentstat.Email CdpType = $current_agentstat.CdpType Alert = $current_agentstat.Alert # LastBackup = LastSync. LastCompleted session update even when there are some errors LastBackup = $current_agentstat.LastBackup LastSessionStart = $current_agentstat.LastSessionStart LastSessionComplete = $current_agentstat.LastSessionComplete LastConnection = $current_agentstat.LastConnection LastSync = $current_agentstat.LastSync LastStartedSession = $current_agentstat.LastStartedSession LastCompletedSession = $current_agentstat.LastCompletedSession LastConnectionTime = $current_agentstat.LastConnectionTime LastSyncTime = $current_agentstat.LastSyncTime TenantID = $Item.DomainID AgentGroupID = $Item.AttachementArray.Attachement.Group.ID StrategyID = $Item.ServiceProfile.ID ProtectionID = $Item.DataProfile.ID StrategyInternalName = $Item.ServiceProfile.Name ProtectionInternalName = $Item.DataProfile.Name } $LinaItems += $CurrentLinaItem } } } else { # Using API 5.1+ (JSON containing agent and agentStats) $request = CallAPI -Path "/stats_clients.json?inactiveTime=604800" $Items = $request.ClientArray foreach ($Item in $Items) { #$Name_encoded = [System.Text.Encoding]::UTF8.GetString([System.Text.Encoding]::GetEncoding(28591).GetBytes($Item.AdminInfos.Name)) $Name_encoded = FixEncoding($Item.AdminInfos.Name) <# Filtering on ID or Name (only if provided) #> if ((!$Name -AND !$ID -AND !$Tag) -OR ( $Item.AdminInfos.Name -like "$Name" -OR $Name_encoded -like "$Name" -OR $Item.AdminInfos.ID -eq $ID -OR $Item.Tags.Name -contains "$Tag" )) { # Avoid divisions by zero if ($Item.AdminInfos.Quotas.MaxProtSize -gt 0) { $MaxProtSize = (($Item.ServerInfos.Backup.ProtSize) / ($Item.AdminInfos.Quotas.MaxProtSize)) * 100 } else { $MaxProtSize = $null } if ($Item.AdminInfos.Quotas.MaxHistSize -gt 0) { $MaxHistSize = (($Item.ServerInfos.Backup.HistSize) / ($Item.AdminInfos.Quotas.MaxHistSize)) * 100 } else { $MaxHistSize = $null } if ($Item.AdminInfos.Quotas.MaxProtObjs -gt 0) { $MaxProtObjs = (($Item.ServerInfos.Backup.ProtObjs) / ($Item.AdminInfos.Quotas.MaxProtObjs)) * 100 } else { $MaxProtObjs = $null } if ($Item.AdminInfos.Quotas.MaxHistObjs -gt 0) { $MaxHistObjs = (($Item.ServerInfos.Backup.HistObjs) / ($Item.AdminInfos.Quotas.MaxHistObjs)) * 100 } else { $MaxHistObjs = $null } # Alerts $alert_reasons = New-Object System.Collections.Generic.List[System.Object] if ($Item.ServerInfos.Alerts.Alert -eq $True) { $alert_reasons.Add("BackupAlert") } if ($Item.ServerInfos.Alerts.QuotaAlert -eq $True) { $alert_reasons.Add("QuotaAlert") } if ($Item.ServerInfos.Alerts.Deletion -eq $True) { $alert_reasons.Add("MarkedForDeletion") } if ($Item.ServerInfos.Alerts.Inactive -eq $True) { $alert_reasons.Add("Inactive") } if ($Item.ServerInfos.Alerts.ObsoleteVersion -eq $True) { $alert_reasons.Add("ObsoleteVersion") } # Checking if agent is local if ($Item.AdminInfos.SourceID -eq "@") { $isLocal=$True } else { $isLocal = $False } # Blocking status if ($global:INT_LINA_API_VERSION -ge 53 ) { $AgentBlockStatus=TranslateBlockStatuses($Item.BlockListInfos.Reason) } else { $AgentBlockStatus = "" } if ($global:INT_LINA_API_VERSION -ge 53 ) { $AgentActivityStatusIntName=TranslateBlockStatusesIntName($Item.BlockListInfos.Reason) } else { $AgentActivityStatusIntName = "" } if ($global:INT_LINA_API_VERSION -ge 60 ) { $AgentGroup=Translate ($Item.AdminInfos.AttachementArray | Where-Object { $_.Hierarchy.Name -eq 'HERIT' }).Group.Name 0 } else { $AgentGroup = Translate $Item.AdminInfos.AttachementArray.Group.Name 0 } $CurrentLinaItem = [PSCustomObject]@{ Name = $Name_encoded ID = $Item.AdminInfos.ID Tenant = $Tenants | where-object { $_.ID -eq $Item.AdminInfos.DomainID } | Select-Object -ExpandProperty Name NodeName = $Item.AdminInfos.NodeFriendlyName AgentGroup = $AgentGroup #Param 0 means encoding is already OK (UTF-8 because of JSON) Strategy = Translate $Item.AdminInfos.ServiceProfile.Name 0 #Param 0 means encoding is already OK (UTF-8 because of JSON) Protection = Translate $Item.AdminInfos.DataProfile.Name 0 #Param 0 means encoding is already OK (UTF-8 because of JSON) Tags = if ($global:INT_LINA_API_VERSION -ge 60 ) { $Item.Tags.Name } else {$Null } ComputerName = $Item.AgentInfos.ComputerName FQDN = $Item.AgentInfos.Hostname System = $Item.AgentInfos.System SystemCategory = TranslateSystemCategories($Item.AgentInfos.SystemCategory) AgentVersion = $Item.AgentInfos.AgentVersion LastLogon = $Item.AgentInfos.LastLogon Email = $Item.AgentInfos.Email CdpType = $Item.AgentInfos.CdpType Alerts = $alert_reasons # New feature of Lina 5.3 (previously called Block List) ActivityStatus = $AgentBlockStatus ProtectedSizeMB = [math]::Round(($Item.ServerInfos.Backup.ProtSize) / (1024 * 1024)) HistorySizeMB = [math]::Round(($Item.ServerInfos.Backup.HistSize) / (1024 * 1024)) ProtectedObjects = $Item.ServerInfos.Backup.ProtObjs HistoryObjects = $Item.ServerInfos.Backup.HistObjs QuotaMaxProtSize = $Item.AdminInfos.Quotas.MaxProtSize QuotaMaxHistSize = $Item.AdminInfos.Quotas.MaxHistSize QuotaMaxProtObjs = $Item.AdminInfos.Quotas.MaxProtObjs QuotaMaxHistObjs = $Item.AdminInfos.Quotas.MaxHistObjs QuotaPercentUsedProtSize = [math]::Round($MaxProtSize) QuotaPercentUsedHistSize = [math]::Round($MaxHistSize) QuotaPercentUsedProtObjs = [math]::Round($MaxProtObjs) QuotaPercentUsedHistObjs = [math]::Round($MaxHistObjs) isLocal = $isLocal isMarkedforDeletion = $Item.AdminInfos.Deletion # LastBackup = LastSync. LastCompleted session update even when there are some errors LastBackup = HumanFriendlyTimeSpan (LinaToLocalTime $Item.NetworkInfos.SyncTime) LastSessionStart = HumanFriendlyTimeSpan (LinaToLocalTime $Item.NetworkInfos.LastStartedSession) LastSessionComplete = HumanFriendlyTimeSpan (LinaToLocalTime $Item.NetworkInfos.LastCompletedSession) LastConnection = HumanFriendlyTimeSpan (LinaToLocalTime $Item.NetworkInfos.LastConnectionTime) LastSync = HumanFriendlyTimeSpan (LinaToLocalTime $Item.NetworkInfos.SyncTime) #add repli info (vivien) RepliSrcName = FixEncoding($Item.RepliInfos.RepliSrcName) RepliDestName = FixEncoding($Item.RepliInfos.RepliDestName) RepliLastPIT = HumanFriendlyTimeSpan (LinaToLocalTime $Item.RepliInfos.RepliLastPIT) RepliLag = $Item.RepliInfos.RepliLag # Same info as before but displayed as datetime instead of TimeSpan (ex: 22 days ago) LastStartedSession = LinaToLocalTime $Item.NetworkInfos.LastStartedSession LastCompletedSession = LinaToLocalTime $Item.NetworkInfos.LastCompletedSession LastConnectionTime = LinaToLocalTime $Item.NetworkInfos.LastConnectionTime LastSyncTime = LinaToLocalTime $Item.NetworkInfos.SyncTime RepliLastPointInTime = LinaToLocalTime $Item.RepliInfos.RepliLastPIT TenantID = $Item.AdminInfos.DomainID NodeID = $Item.AdminInfos.ServerID AgentGroupID = $Item.AdminInfos.AttachementArray.Group.ID StrategyID = $Item.AdminInfos.ServiceProfile.ID ProtectionID = $Item.AdminInfos.DataProfile.ID TagsID = if ($global:INT_LINA_API_VERSION -ge 60 ) { $Item.Tags.ID } else {$Null } StrategyInternalName = $Item.AdminInfos.ServiceProfile.Name ProtectionInternalName = $Item.AdminInfos.DataProfile.Name ActivityStatusValue = $Item.BlockListInfos.Reason ActivityStatusInternalName = $AgentActivityStatusIntName # Here for to avoid script beaking changes, renamed to ActivityStatus in module version 6.1.0.2 (Sept 2023) BlockStatusValue = $Item.BlockListInfos.Reason BlockStatus = $AgentBlockStatus } $LinaItems += $CurrentLinaItem } } } if ($LinaItems.Count -eq 0) { Write-Host2 "No agent found." Return $Null } Return $LinaItems } function Get-LinaWaitingAgent { <# .SYNOPSIS Retrieves the waiting agents. .DESCRIPTION Retrieves the agents waiting to be declared when auto-create is not enabled. Returns a list of agents that correspond to the filter criteria provided. Note : Waiting agents are available in the default tenant if it is set or in all tenants if there is no default tenant. .INPUTS None .OUTPUTS Array of LinaAgent Objects .PARAMETER ComputerName ComputerName of the agent(s) to retrieve. Wilcards are allowed. For example : *DESKTOP* .EXAMPLE Get-LinaWaitingAgent -ComputerName "TEST" Retrieves the waiting agent named "TEST" and display its properties. .EXAMPLE $agents_desktop = Get-LinaWaitingAgent -ComputerName "*DESKTOP*" Retrieves all the waiting agents with DESKTOP inside their computer names. The list returned can be passed to other functions. .EXAMPLE $agents = Get-LinaWaitingAgent foreach ($agent in $agents) { New-LinaAgent -Name $agent.ComputerName } Retrieves all the waiting agents and add (declare) them in the default tenant. #> [cmdletbinding(DefaultParameterSetName = "ByComputerName")] Param( [Parameter(ParameterSetName = "ByComputerName", Position = 0)] [ValidateNotNullOrEmpty()] [string]$ComputerName ) Write-Verbose "Getting list of waiting agents" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } $current_tenant_id = Get-LinaCurrentTenantID 6>$null $DefaultTenant = Get-LinaTenant -Default if ($DefaultTenant.ID) { # Waiting agents are only in default Tenant ifthere is one $void = Set-LinaCurrentTenant -ID $DefaultTenant.ID 6>$null } $LinaItems = @() if ($global:INT_LINA_API_VERSION -lt 60) { # Lina < 6.0 $request = CallAPI -Path "/stats_clientswaiting.xml" $Items = ([xml]$request).Stats.ClientArray.Client } else { # Lina > 6.0 $request = CallAPI -Path "/stats_clientswaiting.json" $Items = $request.WaitingAgents } # Go back to the current tenant after switching to default one to get waiting agents $void = Set-LinaCurrentTenant -ID $current_tenant_id 6>$null foreach ($Item in $Items) { #$Name_encoded = [System.Text.Encoding]::UTF8.GetString([System.Text.Encoding]::GetEncoding(28591).GetBytes($Item.AdminInfos.Name)) $ComputerName_enc = FixEncoding($Item.ComputerName) <# Filtering on ID or Name (only if provided) #> if ((!$ComputerName) -OR ( $Item.ComputerName -like "$ComputerName" -OR $ComputerName_enc -like "$ComputerName")) { # Checking if agent is local => not sure if necessary in waiting agents # if ($Item.SourceID -eq "@") { $isLocal=$True } else { $isLocal = $False } $CurrentLinaItem = [PSCustomObject]@{ Tenant = $DefaultTenant.Name ComputerName = $Item.ComputerName System = $Item.System SystemCategory = TranslateSystemCategories($Item.SystemCategory) #isLocal = $isLocal LastConnection = HumanFriendlyTimeSpan (LinaToLocalTime ([Int64]$Item.LastConnection*1000)) TenantID = $DefaultTenant.ID } $LinaItems += $CurrentLinaItem } } if ($LinaItems.Count -eq 0) { Write-Host2 "No waiting agent found." Return $Null } Return $LinaItems } function Get-LinaStrategy { <# .SYNOPSIS Retrieves the strategies. .DESCRIPTION Retrieves the strategies. Returns a set of strategies that correspond to the filter criteria provided. If TenantID = 0, it is a global strategy across tenants. .INPUTS None .OUTPUTS Array of LinaStrategy Objects .PARAMETER Name Optional : Name of the strategy to retrieve. Wilcards are allowed. For example : *STRAT* .PARAMETER ID Optional : ID of the strategy to retrieve. .EXAMPLE Get-LinaStrategy Retrieves all the strategies. .EXAMPLE Get-LinaStrategy -Name "*STRAT*" Retrieves 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(DefaultParameterSetName = "ByName")] Param( [Parameter(ParameterSetName = "ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID ) Write-Verbose "Getting list of strategies" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($global:INT_LINA_API_VERSION -lt 60) { # Lina < 6.0 $request = CallAPI -Path "/lst_serviceprofiles.xml" $Items = ([xml]$request).HNConfig.ServiceProfileArray.ServiceProfile } else { # Lina > 6.0 $request = CallAPI -Path "/lst_serviceprofiles.json" $Items = $request.ServiceProfileArray } $Tenants = LinaTenantShort $LinaItems = @() foreach ($Item in $Items) { if ($global:INT_LINA_API_VERSION -lt 60) { # Lina < 6.0 $translated_name = Translate $Item.Name } else { # Lina > 6.0 $translated_name = Translate $Item.Name 0 } if ((!$Name -AND !$ID) -OR ( $Item.Name -like "$Name" -OR $Item.ID -eq $ID -OR $translated_name -like "$Name") ) { if ([int]$Item.RepliTarget.ID -eq 0) { $replitarget = "None" } else { $replitarget = $Item.RepliTarget.Name } $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaStrategy' Name = $translated_name ID = $Item.ID Tenant = ($Tenants | where-object { $_.ID -eq $Item.DomainID }).Name RPOInMinutes = ($Item.ParamSchedule / 60) RetentionInDays = $Item.ParamDataAging AlertAfterDays = ($Item.ParamAlertTime / (24 * 3600)) ThroughputLimitKBps = $Item.ParamThroughputLimit ReplicationTarget = $replitarget AlwaysEncrypt = ![bool][int]$Item.ParamEncryptionActivated WanMode = [bool][int]$Item.ParamWanActivated CompressionAlgo = $Item.ParamCompression AllowClientRPO = [bool][int]$Item.ParamAllowClientRPO AllowClientRules = [bool][int]$Item.ParamAllowClientRules AllowClientPause = [bool][int]$Item.ParamAllowClientPause AllowClientBoost = [bool][int]$Item.ParamAllowClientBoost AllowClientNetworkParams = [bool][int]$Item.ParamAllowClientNetworkParams AllowWebAccess = [bool][int]$Item.ParamAllowWebAccess QuotaMaxProtSizeMB = [math]::Round(($Item.ParamQuotaMaxProtSize) / (1024 * 1024)) QuotaMaxProtObjs = $Item.ParamQuotaMaxProtObjs QuotaMaxHistSizeMB = [math]::Round(($Item.ParamQuotaMaxHistSize) / (1024 * 1024)) QuotaMaxHistObjs = $Item.ParamQuotaMaxHistObjs ReplicationTargetID = $Item.RepliTarget.ID TenantID = $Item.DomainID InternalName = $Item.Name } $LinaItems += $CurrentLinaItem } } if ($LinaItems.Count -eq 0) { Write-Host2 "No strategy found." Return $Null } Return $LinaItems } function Get-LinaTag { <# .SYNOPSIS Retrieves the tags. .DESCRIPTION Retrieves the tags. Returns a set of tags that correspond to the filter criteria provided. .INPUTS None .OUTPUTS Array of LinaTag Objects .PARAMETER Name Optional : Name of the Tag to retrieve. Wilcards are allowed. For example : *MyTag* .PARAMETER ID Optional : ID of the Tag to retrieve. .EXAMPLE Get-LinaTag Retrieves all the tags. .EXAMPLE Get-LinaTag -Name "*MyTag*" Retrieves all the tags with MyTag inside their names. .EXAMPLE Get-LinaTag -Name "*MyTag*" Displays the list of tags. #> [cmdletbinding(DefaultParameterSetName = "ByName")] Param( [Parameter(ParameterSetName = "ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID ) Write-Verbose "Getting list of tags" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($global:INT_LINA_API_VERSION -lt 60) { Write-Warning "Tags are not available in Lina version below 6.0" return } else { # Lina > 6.0 $request = CallAPI -Path "/ADE/tag/list.json" $Items = $request.tags } $Tenants = LinaTenantShort $LinaItems = @() foreach ($Item in $Items) { if ($global:INT_LINA_API_VERSION -lt 60) { # Lina < 6.0 $translated_name = Translate $Item.name } else { # Lina > 6.0 $translated_name = Translate $Item.name 0 } if ((!$Name -AND !$ID) -OR ( $Item.name -like "$Name" -OR $Item.ID -eq $ID -OR $translated_name -like "$Name") ) { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaTag' Name = $translated_name ID = $Item.id Colors = $Item.color Tenant = ($Tenants | where-object { $_.ID -eq $Item.domain_id }).Name TenantID = $Item.domain_id } $LinaItems += $CurrentLinaItem } } if ($LinaItems.Count -eq 0) { Write-Host2 "No tag found." Return $Null } Return $LinaItems } function Get-LinaProtection { <# .SYNOPSIS Retrieves the protection policies. .DESCRIPTION Retrieves the protection policies. Returns a set of protections that correspond to the filter criteria provided. .INPUTS None .OUTPUTS Array of LinaProtection Objects .PARAMETER Name Optional : Name of the protection to retrieve. Wilcards are allowed. For example : *PROT* .PARAMETER ID Optional : ID of the protection to retrieve. .PARAMETER ProtectionZone Optional : Filter by Protection zone name used in subrules. No wildcard allowed. .PARAMETER ProtectionRule Optional : Filter by Protection rule name used in subrules. No wildcard allowed. .EXAMPLE Get-LinaProtection Retrieves all the protections. .EXAMPLE Get-LinaProtection -Name "*PROT*" Retrieves all the protection with PROT inside their names. .EXAMPLE Get-LinaProtection -ID 15 Retrieves the protection with ID 15 .EXAMPLE Get-LinaProtection -ProtectionZone "The entire computer" Retrieves the protection with a subrule containing the protection zone named "MyProtection" .EXAMPLE Get-LinaProtection -ProtectionRule "Protect all objects" Retrieves the protection with a subrule containing the protection rule named "MyProtection" #> [cmdletbinding(DefaultParameterSetName = "ByName")] Param( [Parameter(ParameterSetName = "ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID, [Parameter(ParameterSetName = "ByProtRule")] [ValidateNotNullOrEmpty()] [string]$ProtectionRule, [Parameter(ParameterSetName = "ByProtZone")] [ValidateNotNullOrEmpty()] [string]$ProtectionZone ) Write-Verbose "Getting list of protection policies" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($global:INT_LINA_API_VERSION -lt 60) { # Lina < 6.0 $request = CallAPI -Path "/lst_dataprofiles.xml" $Items = ([xml]$request).HNConfig.DataProfileArray.DataProfile } else { # Lina > 6.0 $request = CallAPI -Path "/lst_dataprofiles.json" $Items = $request.DataProfileArray } $Tenants = LinaTenantShort $protection_rules = Get-LinaProtectionRule $protection_zones = Get-LinaProtectionZone $LinaItems = @() if ($ProtectionRule) { $protection_rule_id_filter = ($protection_rules | Where-Object { $_.Name -eq $ProtectionRule }).ID if (!$protection_rule_id_filter) { Write-Host2 "No protection rule found with name $ProtectionRule. Please provide the exact name" return } } else { $protection_rule_id_filter = -1 } if ($ProtectionZone) { $protection_zone_id_filter = ($protection_zones | Where-Object { $_.Name -eq $ProtectionZone }).ID if (!$protection_zone_id_filter) { Write-Host2 "No protection zone found with name $ProtectionZone. Please provide the exact name" return } } else { $protection_zone_id_filter = -1 } foreach ($Item in $Items) { if ((!$Name -AND !$ID -AND !$ProtectionRule -AND !$ProtectionZone ) -OR ( $Item.Name -like "$Name" -OR $Item.ID -eq $ID -OR (Translate($Item.Name)) -like "$Name" -OR $Item.RuleArray.RulePredef.FilterRuleID -contains $protection_rule_id_filter -OR $Item.RuleArray.RulePredef.PredefinedPathID -contains $protection_zone_id_filter) ) { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaProtection' Name = Translate($Item.Name) ID = $Item.ID Tenant = ($Tenants | where-object { $_.ID -eq $Item.DomainID }).Name OS = $Item.OS BareMetalRestore = [bool][int]$Item.BMR BuiltIn = [bool]($null -eq $Item.CustomRef) TenantID = $Item.DomainID InternalName = $Item.Name } $i = 1 foreach ($subrule in $Item.RuleArray.RulePredef) { $subrule_protection = $protection_rules | where-object { $_.ID -eq $subrule.FilterRuleID } $subrule_path = $protection_zones | where-object { $_.ID -eq $subrule.PredefinedPathID } $CurrentLinaItem | add-member -membertype noteproperty -name "Rule#$i" -value ($subrule_path.Name + " ( " + $subrule_path.Path + " ) >> " + $subrule_protection.Name) $i++ } $LinaItems += $CurrentLinaItem } } if ($LinaItems.Count -eq 0) { Write-Host2 "No protection found." Return $Null } Return $LinaItems } function Get-LinaProtectionZone { <# .SYNOPSIS Retrieves the protection zones. .DESCRIPTION Retrieves the protection zones. Returns a set of protection zones that correspond to the filter criteria provided. .INPUTS None .OUTPUTS Array of LinaProtectionZone Objects .PARAMETER Name Optional : Name of the protection zone to retrieve. Wilcards are allowed. For example : *Mac* .PARAMETER ID Optional : ID of the protection zone to retrieve. .PARAMETER Path Optional : Return protection containing this exact path. Wildcards character (*) will be considered only as stars. .PARAMETER MatchingPath Optional : Return protection matching this path. Wilcards are allowed. .EXAMPLE Get-LinaProtectionZone Retrieves all the protection zones. .EXAMPLE Get-LinaProtectionZone -Name "*Mac*" Retrieves all the protection zones with Mac inside their names. .EXAMPLE Get-LinaProtectionZone -Path "\*\Users\*\" Retrieves the protection zones matching this exact path. .EXAMPLE Get-LinaProtectionZone -MatchingPath "\*\Users\*\" Retrieves all the protection zones matching this path (stars are considered as wildcards) #> [cmdletbinding(DefaultParameterSetName = "ByName")] Param( [Parameter(ParameterSetName = "ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID, [Parameter(ParameterSetName = "ByPath")] [ValidateNotNullOrEmpty()] [string]$Path, [Parameter(ParameterSetName = "ByMatchingPath")] [ValidateNotNullOrEmpty()] [string]$MatchingPath ) Write-Verbose "Getting list of protection zones" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($global:INT_LINA_API_VERSION -lt 60) { # Lina < 6.0 $request = CallAPI -Path "/lst_predefinedpaths.xml" $Items = ([xml]$request).HNConfig.PredefinedPathArray.PredefinedPath } else { # Lina > 6.0 $request = CallAPI -Path "/lst_predefinedpaths.json" $Items = $request.PredefinedPathArray } $Tenants = LinaTenantShort $LinaItems = @() foreach ($Item in $Items) { if ((!$Name -AND !$ID -AND !$Path -AND !$MatchingPath) -OR ( $Item.Name -like "$Name" -OR $Item.ID -eq $ID -OR (Translate($Item.Name)) -like "$Name" -OR $Item.Path -eq "$Path" -OR $Item.Path -like "$MatchingPath" ) ) { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaProtectionZone' Name = Translate($Item.Name) ID = $Item.ID Tenant = ($Tenants | where-object { $_.ID -eq $Item.DomainID }).Name OS = $Item.OS Path = $Item.Path BuiltIn = [bool]($null -eq $Item.CustomRef) TenantID = $Item.DomainID } $LinaItems += $CurrentLinaItem } } if ($LinaItems.Count -eq 0) { Write-Host2 "No protection zone found." Return $Null } Return $LinaItems } function Get-LinaFileCategory { <# .SYNOPSIS Retrieves the file categories. .DESCRIPTION Retrieves the file categories. Returns a set of file categories that correspond to the filter criteria provided. .INPUTS None .OUTPUTS Array of LinaFileCategory Objects .PARAMETER Name Optional : Name of the file category to retrieve. Wilcards are allowed. For example : *FILECAT* .PARAMETER ID Optional : ID of the file category to retrieve. .EXAMPLE Get-LinaFileCategory Retrieves all the file categories. .EXAMPLE Get-LinaFileCategory -Name "*Text*" Retrieves all the file categories with Text inside their names. #> [cmdletbinding(DefaultParameterSetName = "ByName")] Param( [Parameter(ParameterSetName = "ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID ) Write-Verbose "Getting list of file categories" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($global:INT_LINA_API_VERSION -lt 60) { # Lina < 6.0 $request = CallAPI -Path "/lst_filetypes.xml" $Items = ([xml]$request).HNConfig.FileTypeArray.FileType } else { # Lina > 6.0 $request = CallAPI -Path "/lst_filetypes.json" $Items = $request.FileTypeArray } $Tenants = LinaTenantShort $LinaItems = @() foreach ($Item in $Items) { if ((!$Name -AND !$ID) -OR ( $Item.Name -like "$Name" -OR $Item.ID -eq $ID -OR (Translate($Item.Name)) -like "$Name" ) ) { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaFileCategory' Name = Translate($Item.Name) ID = $Item.ID Tenant = ($Tenants | where-object { $_.ID -eq $Item.DomainID }).Name FileExtensions = if ($global:INT_LINA_API_VERSION -lt 60) { $Item.ExtArray.Ext } else { $Item.ExtArray } BuiltIn = [bool]($null -eq $Item.CustomRef) TenantID = $Item.DomainID } $LinaItems += $CurrentLinaItem } } if ($LinaItems.Count -eq 0) { Write-Host2 "No file category found." Return $Null } Return $LinaItems } function TranslateBehaviors ($to_translate) { switch ( $to_translate ) { "INCL" { $result = "Include / No Agent modification allowed" } "EXCL" { $result = "Exclude / No Agent modification allowed" } "ADVINCL" { $result = "Include / Allow agents modifications" } "ADVEXCL" { $result = "Exclude / Allow agents modifications" } } return $result } function Get-LinaProtectionRule { <# .SYNOPSIS Retrieves the protection rules. .DESCRIPTION Retrieves the protection rules. Returns a set of file categories that correspond to the filter criteria provided. .INPUTS None .OUTPUTS Array of LinaProtectionRules Objects .PARAMETER Name Optional : Name of the protection rule to retrieve. Wilcards are allowed. For example : *FILECAT* .PARAMETER ID Optional : ID of the protection rule to retrieve. .EXAMPLE Get-LinaProtectionRule Retrieves all the protection rules. .EXAMPLE Get-LinaProtectionRule -Name "*Office*" Retrieves all the protection rules with Office inside their names. #> [cmdletbinding(DefaultParameterSetName = "ByName")] Param( [Parameter(ParameterSetName = "ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID ) Write-Verbose "Getting list of protection rules" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($global:INT_LINA_API_VERSION -lt 60) { # Lina < 6.0 $request = CallAPI -Path "/lst_filters.xml" $Items = ([xml]$request).HNConfig.FilterRuleArray.FilterRule } else { # Lina > 6.0 $request = CallAPI -Path "/lst_filters.json" $Items = $request.FilterRuleArray } $Tenants = LinaTenantShort $FileCategories = Get-LinaFileCategory $LinaItems = @() foreach ($Item in $Items) { if ((!$Name -AND !$ID) -OR ( $Item.Name -like "$Name" -OR $Item.ID -eq $ID -OR (Translate($Item.Name)) -like "$Name" ) ) { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaProtectionRule' Name = Translate($Item.Name) ID = $Item.ID Tenant = ($Tenants | where-object { $_.ID -eq $Item.DomainID }).Name DefaultBehavior = TranslateBehaviors($Item.DefaultBehavior) BuiltIn = [bool]($null -eq $Item.CustomRef) TenantID = $Item.DomainID } $i = 1 foreach ($subrule in $Item.SubRuleArray.SubRule) { $filecat_name = ($FileCategories | where-object { $_.ID -eq $subrule.FileType.ID }).Name $rule_behavior = TranslateBehaviors($subrule.Behavior) $CurrentLinaItem | add-member -membertype noteproperty -name "Rule#$i" -value ($rule_behavior + ' : ' + $filecat_name) $i++ } $LinaItems += $CurrentLinaItem } } if ($LinaItems.Count -eq 0) { Write-Host2 "No protection rule found." Return $Null } Return $LinaItems } function TranslatePermissions($permissions, $perm_category) { $perms_filtered = $permissions | Where-Object { $_ -like "*$perm_category" } | ForEach-Object { $_ -replace "$perm_category", "" } $short_perms = "" ForEach ($perm in $perms_filtered) { $short_perms += $perm + "," } # Trimming last character , $short_perms = $short_perms -replace ",$" Switch ($perm_category) { { 'UserProfiles', 'Users', 'Replications', 'AlnAgent', 'AlnStrategy', 'AlnProtection', 'AlnProtectionRule', 'AlnProtectionZone', 'AlnFileCategory', 'Domains' -contains $_ } { if ($short_perms -eq "View,Create,Delete,Set") { Return "Full" } else { Return $short_perms } } { 'Alerts', 'Services', 'BMR', 'License', 'Smtp', 'Ldap', 'Config' -contains $_ } { if ($short_perms -eq "View,Set") { Return "Full" } else { Return $short_perms } } { 'Support', 'Files', 'Smtp', 'Ldap', 'Config' -contains $_ } { if ($short_perms -eq "View") { Return "Full" } else { Return $short_perms } } { 'Snapshot' -contains $_ } { if ($short_perms -eq "View,Create,Delete") { Return "Full" } else { Return $short_perms } } { 'Tunables' -contains $_ } { if ($short_perms -eq "View,Set,ViewAdvanced") { Return "Full" } else { Return $short_perms } } { 'Statistics' -contains $_ } { if ($short_perms -eq "View,Recompute") { Return "Full" } else { Return $short_perms } } { 'AlnDefaultConfiguration', 'AlnGlobalDefaultConfiguration' -contains $_ } { if ($short_perms -eq "Set") { Return "Full" } else { Return $short_perms } } { 'Service' -contains $_ } { if ($short_perms -eq "Restart") { Return "Full" } else { Return $short_perms } } Default { Return $short_perms } } if ($short_perms -like "*View,Create,Delete,Set*" -OR $short_perms -like "*ViewAll,Create,Delete,Set*") { Return "ALL" } Return $short_perms } function Get-LinaUserProfile { <# .SYNOPSIS (Deprecated in Lina 6.1+, use Get-LinaUserGroup instead) Retrieves the user profiles .DESCRIPTION Retrieves the user profiles. By default only show Lina permissions (corresponds to Lina tab in Web interface). Use the -ShowAllPermissions to also displays Users tab and Server Tab permissions. "Full" means that the user have all the possible permissions in the category. Note : Requires PowerShell 5.0 or greater. .INPUTS None .OUTPUTS Array of LinaUserProfile Objects .PARAMETER Name Optional : Name of the user profile to retrieve. Wilcards are allowed. For example : *UserProfile* .PARAMETER ID Optional : ID of the user profile to retrieve. .PARAMETER Tenant Optional : Tenant of the user profile to retrieve. .EXAMPLE Get-LinaUserProfile Retrieves all the user profiles and shows only Lina permissions .EXAMPLE Get-LinaUserProfile -ShowAllPermissions Retrieves all the user profiles and shows all permissions Lina + Users + Server .EXAMPLE Get-LinaUserProfile -Name "MyProfile" Retrieves MyProfile Lina permissions .EXAMPLE Get-LinaUserProfile -Tenant "MyTenant" | Where {$_.BuiltIn -eq $False -AND $_.Name -ne "Default"} Retrieves all custom profiles from Tenant MyTenant #> [cmdletbinding(DefaultParameterSetName = "ByName")] Param( [Parameter(ParameterSetName = "ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID, [Parameter(Mandatory = $False)] [ValidateNotNullOrEmpty()] [string]$Tenant, [Parameter(Mandatory = $False)] [Switch]$ShowAllPermissions ) Write-Verbose "Getting list of user profiles" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($PSVersionTable.PSVersion.Major -lt 5) { Write-Host2 "ERROR : This cmdlet requires PowerShell 5.0 or greater in order to work" Return } if ($global:INT_LINA_API_VERSION -ge 61) { Write-Warning "UserProfiles are deprecated and have been merged with User Groups. Use Get-LinaUserGroup instead." return } $request = CallAPI -Path "/ADM/list_profile.json" $Items = $request.profiles $Tenants = LinaTenantShort $LinaItems = @() # Filter on Tenant if ($Tenant) { $domain = $Tenants | Where-Object { $_.Name -eq $Tenant } $domain_id = [int]$domain.ID } foreach ($Item in $Items) { # Fixing name of default Administrator Profile if ($Item.name -eq "Admin" -AND $Item.custom -eq $False) { $translated_name = FixEncoding(Translate "USER_PROFILE_NAME_ADMIN") } else { # Only one item is builtin, all others are custom $translated_name = FixEncoding($Item.name) } # Filtering specific accounts SuperAdmin and Guest if ((!$Name -AND !$ID -AND $Item.name -notin ("Guest")) -OR ( $Item.name -like "$Name" -OR $Item.id -eq $ID -OR $translated_name -like "$Name") ) { # When Roles are negatives, means we have to use highest value less this one (+1 but i don't know why ..) # Negative values are used by default profiles only if ($Item.roles1 -lt 0) { # Signed int with negative value $roles1_value = $ROLES1_MAX + $Item.roles1 + 1 }elseif ($Item.roles1 -gt $ROLES1_MAX ) { # Value is higher than max => it is an unsigned value. Converting it to signed value $roles1_value = $ROLES1_MAX + 1 + ( $Item.roles1 + [Math]::Pow(2, 31) ) % [Math]::Pow(2, 32) - [Math]::Pow(2, 31) }else { # Value is withing range (should be signed int) $roles1_value = $Item.roles1 } if ($Item.roles2 -lt 0) { $roles2_value = $ROLES2_MAX + $Item.roles2 + 1 } elseif ($Item.roles2 -gt $ROLES2_MAX ) { $roles2_value = $ROLES2_MAX + 1 + ( $Item.roles2 + [Math]::Pow(2, 31) ) % [Math]::Pow(2, 32) - [Math]::Pow(2, 31) } else { $roles2_value = $Item.roles2 } if ($Item.roles3 -lt 0) { $roles3_value = $ROLES3_MAX + $Item.roles3 + 1 } elseif ($Item.roles3 -gt $ROLES3_MAX ) { $roles3_value = $ROLES3_MAX + 1 + ( $Item.roles3 + [Math]::Pow(2, 31) ) % [Math]::Pow(2, 32) - [Math]::Pow(2, 31) } else { $roles3_value = $Item.roles3 } if ($Item.roles4 -lt 0) { # Getting negative (signed) values $roles4_value = $ROLES4_MAX + $Item.roles4 + 1 } elseif ($Item.roles4 -gt $ROLES4_MAX ) { # Getting positive (unsigned) values $roles4_value = $ROLES4_MAX + 1 + ( $Item.roles4 + [Math]::Pow(2, 31) ) % [Math]::Pow(2, 32) - [Math]::Pow(2, 31) } else { # Getting positive (signed) values $roles4_value = $Item.roles4 } $roles1_list = [ROLES1_LIST]$roles1_value -split ", " $roles2_list = [ROLES2_LIST]$roles2_value -split ", " $roles3_list = [ROLES3_LIST]$roles3_value -split ", " $roles4_list = [ROLES4_LIST]$roles4_value -split ", " $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaUserProfile' Name = $translated_name ID = $Item.id Tenant = ($Tenants | where-object { $_.ID -eq $Item.domain_id }).Name # Because is not in use in the Web interface #Comment = $Item.comment Lina_Agents = TranslatePermissions $roles3_list "AlnAgent" Lina_Strategies = TranslatePermissions $roles3_list "AlnStrategy" Lina_Protections = TranslatePermissions $roles3_list "AlnProtection" Lina_ProtectionRules = TranslatePermissions $roles3_list "AlnProtectionRule" Lina_ProtectionZones = TranslatePermissions $roles4_list "AlnProtectionZone" Lina_FileCategories = TranslatePermissions $roles4_list "AlnFileCategory" Lina_Preferences = TranslatePermissions $roles4_list "AlnDefaultConfiguration" Lina_GlobalDefaultSettings = TranslatePermissions $roles4_list "AlnGlobalDefaultConfiguration" # Lina_CrossRestore = TranslatePermissions $roles1_list "CrossResto" # Lina_BMRRestore = TranslatePermissions $roles1_list "BMRResto" } if ($ShowAllPermissions) { $CurrentLinaItem | add-member -membertype noteproperty -name "Users_Users" -value ( TranslatePermissions $roles1_list "Users" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Users_UserProfiles" -value ( TranslatePermissions $roles1_list "UserProfiles" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Users_SMTP" -value ( TranslatePermissions $roles2_list "Smtp" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Users_LDAP" -value ( TranslatePermissions $roles2_list "Ldap" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Replications" -value ( TranslatePermissions $roles1_list "Replications" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Snapshot" -value ( TranslatePermissions $roles2_list "Snapshot" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Configuration" -value ( TranslatePermissions $roles2_list "Config" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Alerts" -value ( TranslatePermissions $roles1_list "Alerts" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Services" -value ( TranslatePermissions $roles1_list "Services" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_License" -value ( TranslatePermissions $roles2_list "License" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Maintenance" -value ( TranslatePermissions $roles1_list "Support" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Files" -value ( TranslatePermissions $roles2_list "Files" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_FineTuning" -value ( TranslatePermissions $roles2_list "Tunables" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Statistics" -value ( TranslatePermissions $roles2_list "Statistics" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_ServiceRestart" -value ( TranslatePermissions $roles2_list "Service" ) #Streams = TranslatePermissions $roles2_list "Streams" } $CurrentLinaItem | add-member -membertype noteproperty -name "BuiltIn" -value ( [bool](!$Item.custom) ) $CurrentLinaItem | add-member -membertype noteproperty -name "UUID" -value ( $Item.uuid ) $CurrentLinaItem | add-member -membertype noteproperty -name "InternalRoles1" -value ( $roles1_value ) $CurrentLinaItem | add-member -membertype noteproperty -name "InternalRoles2" -value ( $roles2_value ) $CurrentLinaItem | add-member -membertype noteproperty -name "InternalRoles3" -value ( $roles3_value ) $CurrentLinaItem | add-member -membertype noteproperty -name "InternalRoles4" -value ( $roles4_value ) $CurrentLinaItem | add-member -membertype noteproperty -name "TenantID" -value ( $Item.domain_id ) $CurrentLinaItem | add-member -membertype noteproperty -name "InternalName" -value ( $Item.name ) # Filtering User profiles by tenant when tenant is provided if (!$Tenant -OR $CurrentLinaItem.TenantID -eq $domain_id) { $LinaItems += $CurrentLinaItem } } } if ($LinaItems.Count -eq 0) { Write-Host2 "No user profile found." return $null } Return $LinaItems } function Get-LinaUser { <# .SYNOPSIS Retrieves the users. .DESCRIPTION Retrieves the users. .INPUTS None .OUTPUTS Array of LinaUser Objects .PARAMETER Name Optional : Name of the user to retrieve. Wilcards are allowed. For example : *Jon* .PARAMETER ID Optional : ID of the user to retrieve. .EXAMPLE Get-LinaUser Retrieves all the users. .EXAMPLE Get-LinaUser -Name "*Jon*" Retrieves all the users with Jon inside their names. #> [cmdletbinding(DefaultParameterSetName = "ByName")] Param( [Parameter(ParameterSetName = "ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID ) Write-Verbose "Getting list of users" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } $request = CallAPI -Path "/ADM/user.json" $Items = $request.users $request2 = CallAPI -Path "/ADM/list_user_ug_relation.json" $User_to_UserGroup = $request2.relations $Tenants = LinaTenantShort $UserGroups = Get-LinaUserGroup $LinaItems = @() foreach ($Item in $Items) { if ((!$Name -AND !$ID -AND $Item.name -notin ("superadmin", "guest")) -OR ( $Item.name -like "$Name" -OR $Item.id -eq $ID -OR (FixEncoding($Item.name)) -like "$Name" ) ) { $UserGroupID= ($User_to_UserGroup | where-object {$_.user_id -eq $Item.id}).ug_id $UserGroupObject = $UserGroups | where-object { $_.ID -eq $UserGroupID } $UserProfile = $UserGroupObject.UserProfile $UserProfileID = $UserGroupObject.UserProfileID $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaUser' Name = FixEncoding($Item.name) ID = $Item.id Tenant = ($Tenants | where-object { $_.ID -eq $Item.domain_id }).Name UserGroup = $UserGroupObject.Name Disabled = [bool]($Item.disabled) Type = $global:INT_USER_TYPES[[int]$Item.type] TwoFactorAuthEnabled = [bool]($Item.totp) Email = $Item.email BuiltIn = [bool](!$Item.custom) TenantID = $Item.domain_id UserGroupID = $UserGroupObject.ID } if ($global:INT_LINA_API_VERSION -lt 61) { $CurrentLinaItem | add-member -membertype noteproperty -name "UserProfile" -value ( $UserProfile ) $CurrentLinaItem | add-member -membertype noteproperty -name "UserProfileID" -value ( $UserProfileID ) } $LinaItems += $CurrentLinaItem } } if ($LinaItems.Count -eq 0) { Write-Host2 "No user found." Return $Null } Return $LinaItems } function Get-LinaUserGroup { <# .SYNOPSIS Retrieves the user groups. .DESCRIPTION Retrieves the user groups. .INPUTS None .OUTPUTS Array of LinaUserGroup Objects .PARAMETER Name Optional : Name of the user group to retrieve. Wilcards are allowed. For example : *Admin* .PARAMETER ID Optional : ID of the user group to retrieve. .PARAMETER ShowAllPermissions Optional : Switch to show all permissions with details .EXAMPLE Get-LinaUserGroup Retrieves all the user groups. .EXAMPLE Get-LinaUserGroup -Name "*Admin*" Retrieves all the user groups with Admin inside their names. .EXAMPLE Get-LinaUserGroup -ShowAllPermissions Retrieves all the user groups and detailed (human-readable) permissions #> [cmdletbinding(DefaultParameterSetName = "ByName")] Param( [Parameter(ParameterSetName = "ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID, [Parameter(Mandatory = $False)] [Switch]$ShowAllPermissions ) Write-Verbose "Getting list of user groups" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } $request = CallAPI -Path "/ADM/list_user_group.json" $Items = $request.user_groups $Tenants = LinaTenantShort $LinaItems = @() if ($global:INT_LINA_API_VERSION -lt 61) { # In version below 6.1 user groups and user profiles are two different objects $request2 = CallAPI -Path "/ADM/list_prof_ug_relation.json" $UserProfiles = Get-LinaUserProfile $UserGroup_to_UserProfile = $request2.relations foreach ($Item in $Items) { if ($Item.custom) { $ug_name=FixEncoding($Item.name) }else { $name_upper=$Item.name.ToUpper() $ug_name=Translate("USER_GROUP_NAME_$name_upper") } if ((!$Name -AND !$ID -AND $Item.name -notin ("SuperAdmin", "Guest")) -OR ( $Item.name -like "$Name" -OR $Item.id -eq $ID -OR $ug_name -like "$Name" ) ) { $UserProfileID= ($UserGroup_to_UserProfile | where-object {$_.ug_id -eq $Item.id}).prof_id $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaUserGroup' Name = $ug_name ID = $Item.id Tenant = ($Tenants | where-object { $_.ID -eq $Item.domain_id }).Name UserProfile = ($UserProfiles | where-object { $_.ID -eq $UserProfileID }).Name BuiltIn = [bool](!$Item.custom) TenantID = $Item.domain_id UserProfileID = $UserProfileID InternalName = $Item.name } $LinaItems += $CurrentLinaItem } } } else { # Lina version 6.1+ (userprofiles merged with usergroups) $request2 = CallAPI -Path "/ADM/list_user_group.json" foreach ($Item in $Items) { if ($Item.custom) { $ug_name=FixEncoding($Item.name) }else { $name_upper=$Item.name.ToUpper() $ug_name=Translate("USER_GROUP_NAME_$name_upper") } if ((!$Name -AND !$ID -AND $Item.name -notin ("SuperAdmin", "Guest")) -OR ( $Item.name -like "$Name" -OR $Item.id -eq $ID -OR $ug_name -like "$Name" ) ) { # When Roles are negatives, means we have to use highest value less this one (+1 but i don't know why ..) # Negative values are used by default profiles only if ($Item.roles1 -lt 0) { # Signed int with negative value $roles1_value = $ROLES1_MAX + $Item.roles1 + 1 }elseif ($Item.roles1 -gt $ROLES1_MAX ) { # Value is higher than max => it is an unsigned value. Converting it to signed value $roles1_value = $ROLES1_MAX + 1 + ( $Item.roles1 + [Math]::Pow(2, 31) ) % [Math]::Pow(2, 32) - [Math]::Pow(2, 31) }else { # Value is withing range (should be signed int) $roles1_value = $Item.roles1 } if ($Item.roles2 -lt 0) { $roles2_value = $ROLES2_MAX + $Item.roles2 + 1 } elseif ($Item.roles2 -gt $ROLES2_MAX ) { $roles2_value = $ROLES2_MAX + 1 + ( $Item.roles2 + [Math]::Pow(2, 31) ) % [Math]::Pow(2, 32) - [Math]::Pow(2, 31) } else { $roles2_value = $Item.roles2 } if ($Item.roles3 -lt 0) { $roles3_value = $ROLES3_MAX + $Item.roles3 + 1 } elseif ($Item.roles3 -gt $ROLES3_MAX ) { $roles3_value = $ROLES3_MAX + 1 + ( $Item.roles3 + [Math]::Pow(2, 31) ) % [Math]::Pow(2, 32) - [Math]::Pow(2, 31) } else { $roles3_value = $Item.roles3 } if ($Item.roles4 -lt 0) { # Getting negative (signed) values $roles4_value = $ROLES4_MAX + $Item.roles4 + 1 } elseif ($Item.roles4 -gt $ROLES4_MAX ) { # Getting positive (unsigned) values $roles4_value = $ROLES4_MAX + 1 + ( $Item.roles4 + [Math]::Pow(2, 31) ) % [Math]::Pow(2, 32) - [Math]::Pow(2, 31) } else { # Getting positive (signed) values $roles4_value = $Item.roles4 } $roles1_list = [ROLES1_LIST]$roles1_value -split ", " $roles2_list = [ROLES2_LIST]$roles2_value -split ", " $roles3_list = [ROLES3_LIST]$roles3_value -split ", " $roles4_list = [ROLES4_LIST]$roles4_value -split ", " $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaUserGroup' Name = $ug_name ID = $Item.id UUID = $Item.uuid Comment = $Item.comment Tenant = ($Tenants | where-object { $_.ID -eq $Item.domain_id }).Name BuiltIn = [bool](!$Item.custom) NbUsers = $Item.nb_user } $Lina_Agents = TranslatePermissions $roles3_list "AlnAgent" $Lina_Strategies = TranslatePermissions $roles3_list "AlnStrategy" $Lina_Protections = TranslatePermissions $roles3_list "AlnProtection" # Deprecated in 6.1+ $Lina_ProtectionRules = TranslatePermissions $roles3_list "AlnProtectionRule" # Deprecated in 6.1+ $Lina_ProtectionZones = TranslatePermissions $roles4_list "AlnProtectionZone" # Deprecated in 6.1+ $Lina_FileCategories = TranslatePermissions $roles4_list "AlnFileCategory" $Lina_Preferences = TranslatePermissions $roles4_list "AlnDefaultConfiguration" $Lina_GlobalDefaultSettings = TranslatePermissions $roles4_list "AlnGlobalDefaultConfiguration" # Lina_CrossRestore = TranslatePermissions $roles1_list "CrossResto" # Lina_BMRRestore = TranslatePermissions $roles1_list "BMRResto" if ($ShowAllPermissions) { $CurrentLinaItem | add-member -membertype noteproperty -name "Users_Users" -value ( TranslatePermissions $roles1_list "Users" ) # Deprecated $CurrentLinaItem | add-member -membertype noteproperty -name "Users_UserProfiles" -value ( TranslatePermissions $roles1_list "UserProfiles" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Users_SMTP" -value ( TranslatePermissions $roles2_list "Smtp" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Users_LDAP" -value ( TranslatePermissions $roles2_list "Ldap" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Replications" -value ( TranslatePermissions $roles1_list "Replications" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Snapshot" -value ( TranslatePermissions $roles2_list "Snapshot" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Configuration" -value ( TranslatePermissions $roles2_list "Config" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Alerts" -value ( TranslatePermissions $roles1_list "Alerts" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Services" -value ( TranslatePermissions $roles1_list "Services" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_License" -value ( TranslatePermissions $roles2_list "License" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Maintenance" -value ( TranslatePermissions $roles1_list "Support" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Files" -value ( TranslatePermissions $roles2_list "Files" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_FineTuning" -value ( TranslatePermissions $roles2_list "Tunables" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_Statistics" -value ( TranslatePermissions $roles2_list "Statistics" ) $CurrentLinaItem | add-member -membertype noteproperty -name "Server_ServiceRestart" -value ( TranslatePermissions $roles2_list "Service" ) #Streams = TranslatePermissions $roles2_list "Streams" } $CurrentLinaItem | add-member -membertype noteproperty -name "InternalRoles1" -value ( $roles1_value ) $CurrentLinaItem | add-member -membertype noteproperty -name "InternalRoles2" -value ( $roles2_value ) $CurrentLinaItem | add-member -membertype noteproperty -name "InternalRoles3" -value ( $roles3_value ) $CurrentLinaItem | add-member -membertype noteproperty -name "InternalRoles4" -value ( $roles4_value ) $CurrentLinaItem | add-member -membertype noteproperty -name "TenantID" -value ( $Item.domain_id ) $CurrentLinaItem | add-member -membertype noteproperty -name "InternalName" -value ( $Item.name ) $LinaItems += $CurrentLinaItem } } } if ($LinaItems.Count -eq 0) { Write-Host2 "No user group found." Return $Null } Return $LinaItems } function Get-LinaTenant { <# .SYNOPSIS Retrieves the tenants (entities). .DESCRIPTION Retrieves the tenants (entities). 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. Wilcards are allowed. For example : *Tenant* .PARAMETER ID Optional : ID of the tenant to retrieve. .PARAMETER Default Get the default tenant if any .EXAMPLE Get-LinaTenant Retrieve all tenants .EXAMPLE Get-LinaTenant -Name "BaasCustomer1" Retrieve Tenant named BaasCustomer1 .EXAMPLE Get-LinaTenant -ID 2 Retrieve Tenant with ID 2 .EXAMPLE Get-LinaTenant -Default Retrieve the default tenant (if any) #> [cmdletbinding(DefaultParameterSetName = "ByName")] Param( [Parameter(Mandatory = $false, Position = 0, ParameterSetName = "ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(Mandatory = $True, ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID, [Parameter(Mandatory = $True, ParameterSetName = "Default")] [switch]$Default ) if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($global:INT_LINA_API_VERSION -lt 60) { # Lina < 6.0 $request = CallAPI -Path "/ADE/check_session.xml" $request_type = [string]$request.GetType() if ( $request_type -like "*Xml*") { $current_tenant_id = [int](([xml]$request).session.effective_domain_id) }else { Write-Host2 "ERROR : Type is not XML. Found $request_type instead." $request | Format-List exit } } else { # Lina > 6.0 $request = CallAPI -Path "/ADE/check_session.json" $current_tenant_id = [int]($request.effective_domain_id) } if ($current_tenant_id -gt 1) { Write-Host2 "WARNING : to list tenants you should be logged with superadmin privileges and be in the global view (using Set-LinaCurrentTenant -All). Current tenant ID is : $current_tenant_id" return "" } Write-Verbose "Getting list of tenants" $request = CallAPI -Path "/ADM/list_domain.json" $Items = $request.domains if ($global:INT_LINA_API_VERSION -lt 60) { # Lina < 6.0 $request2 = CallAPI -Path "/lst_globals.xml?domain_id=0" $prefs_global = ([xml]$request2).HNConfig.Globals $prefs_tenants = ([xml]$request2).HNConfig.Globals.DomainGlobalsArray.DomainGlobals } else { # Lina > 6.0 $request2 = CallAPI -Path "/lst_globals.json?domain_id=0" $prefs_global = $request2 $prefs_tenants = $request2.DomainGlobalsArray } $cache_strategies = Get-LinaStrategy $cache_protections = Get-LinaProtection $LinaItems = @() foreach ($Item in $Items) { $name_encoded = FixEncoding($Item.name) if ((!$Name -AND !$ID) -OR $Item.name -like "$Name" -OR $name_encoded -like "$Name" -OR $Item.id -eq $ID ) { if ($prefs_tenants.DomainID -contains [int]$Item.id) { $DefaultStrategyID = ($prefs_tenants | where-object { $_.DomainID -eq [int]$Item.id }).WinDefaultServiceProfileID $WindowsDefaultProtectionID = ($prefs_tenants | where-object { $_.DomainID -eq [int]$Item.id }).WinDefaultDataProfileID $MacDefaultProtectionID = ($prefs_tenants | where-object { $_.DomainID -eq [int]$Item.id }).MacDefaultDataProfileID $LinuxDefaultProtectionID = ($prefs_tenants | where-object { $_.DomainID -eq [int]$Item.id }).LinuxDefaultDataProfileID } else { $DefaultStrategyID = ($prefs_tenants | where-object { $_.DomainID -eq [int]$Item.id }).WinDefaultServiceProfileID $WindowsDefaultProtectionID = ($prefs_tenants | where-object { $_.DomainID -eq [int]$Item.id }).WinDefaultDataProfileID $MacDefaultProtectionID = ($prefs_tenants | where-object { $_.DomainID -eq [int]$Item.id }).MacDefaultDataProfileID $LinuxDefaultProtectionID = ($prefs_tenants | where-object { $_.DomainID -eq [int]$Item.id }).LinuxDefaultDataProfileID } # These ones are always shared across tenants $AutoCreateClients = [bool][int]$prefs_global.AutoCreateClients $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaTenant' Name = $name_encoded ID = $Item.id # Had to reencode to UTF-8 because of a bug or maybe to bad return type Comment = FixEncoding($Item.comment) IsDefault = [bool][int]$Item.def_domain AutoCreateClients = $AutoCreateClients WindowsDefaultProtection = ($cache_protections | Where-Object { $WindowsDefaultProtectionID -eq $_.ID }).Name MacDefaultProtection = ($cache_protections | Where-Object { $MacDefaultProtectionID -eq $_.ID }).Name LinuxDefaultProtection = ($cache_protections | Where-Object { $LinuxDefaultProtectionID -eq $_.ID }).Name DefaultStrategy = ($cache_strategies | Where-Object { $DefaultStrategyID -eq $_.ID }).Name # Need to check if this one is always global or not # WebRestoreEnabled = $tenant_config.WebRestoreEnabled WindowsDefaultProtectionID = $WindowsDefaultProtectionID MacDefaultProtectionID = $MacDefaultProtectionID LinuxDefaultProtectionID = $LinuxDefaultProtectionID DefaultStrategyID = $DefaultStrategyID UUID = $Item.uuid } $LinaItems += $CurrentLinaItem } } if ($LinaItems.Count -eq 0) { Write-Host2 "No tenant found." Return $null } if ($Default) { Return ($LinaItems | Where-Object { $_.IsDefault }) } else { Return $LinaItems } } function LinaTenantShort { <# .SYNOPSIS Retrieves the tenants (entities). .DESCRIPTION Retrieves the tenants (entities). 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. Wilcards are allowed. For example : *Tenant* .PARAMETER ID Optional : ID of the tenant to retrieve. .PARAMETER Default Get the default tenant if any .EXAMPLE Get-LinaTenant Retrieve all tenants .EXAMPLE Get-LinaTenant -Name "BaasCustomer1" Retrieve Tenant named BaasCustomer1 .EXAMPLE Get-LinaTenant -ID 2 Retrieve Tenant with ID 2 .EXAMPLE Get-LinaTenant -Default Retrieve the default tenant (if any) #> [cmdletbinding(DefaultParameterSetName = "ByName")] Param( [Parameter(Mandatory = $false, Position = 0, ParameterSetName = "ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(Mandatory = $True, ParameterSetName = "ByID")] [ValidateRange(-1, 2147483647)] [int]$ID, [Parameter(Mandatory = $True, ParameterSetName = "Default")] [switch]$Default ) Write-Verbose "Getting list of tenants (short)" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } $request = CallAPI -Path "/ADM/list_domain.json" $Items = $request.domains $LinaItems = @() foreach ($Item in $Items) { $name_encoded = FixEncoding($Item.name) if ((!$Name -AND !$ID) -OR $Item.name -like "$Name" -OR $name_encoded -like "$Name" -OR $Item.id -eq $ID ) { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaTenant' Name = FixEncoding($Item.name) ID = $Item.id # Had to reencode to UTF-8 because of a bug or maybe to bad return type Comment = FixEncoding($Item.comment) IsDefault = [bool][int]$Item.def_domain UUID = $Item.uuid } $LinaItems += $CurrentLinaItem } } if ($LinaItems.Count -eq 0) { Write-Host2 "No tenant found." Return $Null } if ($Default) { Return ($LinaItems | Where-Object { $_.IsDefault }) } else { Return $LinaItems } } function Get-LinaAgentStats { <# .SYNOPSIS Retrieves the agents statistics and advanced information. .DESCRIPTION Retrieves the agents statistics and advanced information. Statistics are only available for agent that have been online at least one time. .INPUTS None .OUTPUTS Array of LinaAgentStats Objects .PARAMETER Name Name of the agent(s) to retrieve. Wilcards are allowed. 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 ) if ($global:INT_LINA_API_VERSION -ge 51) { Write-Host2 "WARNING : Get-LinaAgentStats is deprecated with Lina 5.1, use Get-LinaAgent instead. Commands have been merged" return } Write-Verbose "Getting agents Statistics (only available if has been online)" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } $request = CallAPI -Path "/stats_clients.xml" $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 = 'LinaAgentStats' Name = $Item.AdminName ID = $Item.AdminID ComputerName = $Item.ComputerName System = $Item.System SystemCategory = TranslateSystemCategories($Item.SystemCategory) AgentVersion = $Item.AgentVersion Strategy = Translate($Item.AdminServiceProfileName) Protection = Translate($Item.AdminDataProfileName) LastLogon = $Item.LastLogon Email = $Item.Email CdpType = $Item.CdpType Alert = $Item.Alert LastBackup = HumanFriendlyTimeSpan (LinaToLocalTime $Item.SyncTime) LastSessionStart = HumanFriendlyTimeSpan (LinaToLocalTime $Item.LastStartedSession) LastSessionComplete = HumanFriendlyTimeSpan (LinaToLocalTime $Item.LastCompletedSession) LastConnection = HumanFriendlyTimeSpan (LinaToLocalTime $Item.LastConnectionTime) LastSync = HumanFriendlyTimeSpan (LinaToLocalTime $Item.SyncTime) LastStartedSession = LinaToLocalTime $Item.LastStartedSession LastCompletedSession = LinaToLocalTime $Item.LastCompletedSession LastConnectionTime = LinaToLocalTime $Item.LastConnectionTime LastSyncTime = LinaToLocalTime $Item.SyncTime StrategyInternalName = $Item.AdminServiceProfileName ProtectionInternalName = $Item.AdminDataProfileName } $LinaItems += $CurrentLinaItem } } if ($LinaItems.Count -eq 0) { Write-Verbose "No agent statistics found." Return $Null } Return $LinaItems } function Get-LinaAgentGroup { <# .SYNOPSIS Retrieves the agent groups .DESCRIPTION Retrieves the agent groups (Main view of agents) .INPUTS None .OUTPUTS Array of LinaAgentGroup Objects .PARAMETER Name Name of the Group to retrieve. Wilcards are allowed. For example : *UNCATEGOR* .PARAMETER ID ID of the group retrieve. For example : 4. .PARAMETER Tenant Name of the Tenant hosting the groups Can also be used in conjunction with -Name to filter by name AND Tenant. Can be useful if multiple groups have the same name in multiple tenants. .EXAMPLE Get-LinaAgentGroup Retrieve all agent groups .EXAMPLE Get-LinaAgentGroup -ID 131 Retrieve agent group by it ID. Will return a unique object. .EXAMPLE Get-LinaAgentGroup -Name "Group1" Retrieve agent group by its Name. Wilcards are allowed. Warning : result may not be unique even without using wildcards. Group names may not be unique across tenants. .EXAMPLE Get-LinaAgentGroup -Tenant "MyTenant" Retrieve agent groups of the Tenant MyTenant .EXAMPLE Get-LinaAgentGroup -Name "Group1" -Tenant "BaasCustomer1" Filter agent group by name and by Tenant MyTenant. If not using wildcards in name, return will be unique. #> [cmdletbinding(DefaultParameterSetName = 'ByNothing')] Param( [Parameter(Mandatory = $true, ParameterSetName = "ByName")] [Parameter(Mandatory = $True, ParameterSetName = "ByNameAndTenant")] [Parameter(Mandatory = $false, ParameterSetName = "ByNothing")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(Mandatory = $true, ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID, [Parameter(Mandatory = $True, ParameterSetName = "ByTenant")] [Parameter(Mandatory = $True, ParameterSetName = "ByNameAndTenant")] [Parameter(Mandatory = $false, ParameterSetName = "ByNothing")] [ValidateNotNullOrEmpty()] [string]$Tenant ) if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($Tenant) { $TenantID = (LinaTenantShort -Name $Tenant).ID Write-Verbose "Getting agent groups for Tenant $Tenant (ID $TenantID)" } else { Write-Verbose "Getting agent groups" } if ($global:INT_LINA_API_VERSION -lt 60) { # Lina < 6.0 $request = CallAPI -Path "/lst_hierarchies.xml" $Items = ([xml]$request).HNConfig.HierarchyArray.Hierarchy.GroupArray.Group } else { # Lina > 6.0 => taking only Agent group used for inheritance, not legacy groups $request = CallAPI -Path "/lst_hierarchies.json" $Items = ($request.HierarchyArray | Where-Object { $_.Name -eq 'HERIT' } ).GroupArray } $Tenants = LinaTenantShort $LinaItems = @() if ($global:INT_LINA_API_VERSION -lt 60) { # Lina < 6.0 foreach ($Item in $Items) { # PreFiltering By Tenant (Groups in tenant 0 are for all Tenants, example : Unsorted agents) if (!$TenantID -OR $Item.DomainID -eq $TenantID -OR $Item.DomainID -eq 0 ) { <# Filtering on ID or Name (only if provided) #> $name_translation = Translate($Item.Name) $View = $Item.ParentNode.ParentNode.Name # Default view name should be translated if ($View -eq "DEF") { $ViewTranslated = Translate "AGENT_VIEW_BY_AGENT_GROUP_LABEL" }else { $ViewTranslated = Translate $view } if ((!$Name -AND !$ID) -OR ( $name_translation -like "$Name" -OR $Item.ID -eq $ID) ) { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaAgentGroup' Name = $name_translation ID = $Item.ID View = $ViewTranslated Strategy = Translate($Item.ServiceProfile.Name) Protection = Translate($Item.DataProfile.Name) Tenant = $Tenants | where-object { $_.ID -eq $Item.DomainID } | Select-Object -ExpandProperty Name NbAgents = $Item.NbRefs InternalName = $Item.Name TenantID = $Item.DomainID ViewID = $Item.ParentNode.ParentNode.ID StrategyInternalID = $Item.ServiceProfile.ID ProtectionInternalID = $Item.DataProfile.ID } $LinaItems += $CurrentLinaItem } } } } else { foreach ($Item in $Items) { # PreFiltering By Tenant (Groups in tenant 0 are for all Tenants, example : Unsorted agents) if (!$TenantID -OR $Item.DomainID -eq $TenantID -OR $Item.DomainID -eq 0 ) { <# Filtering on ID or Name (only if provided) #> $name_translation = Translate $Item.Name 0 if ((!$Name -AND !$ID) -OR ( $name_translation -like "$Name" -OR $Item.ID -eq $ID) ) { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaAgentGroup' Name = $name_translation ID = $Item.ID Strategy = Translate($Item.ServiceProfile.Name) Protection = Translate($Item.DataProfile.Name) Tenant = $Tenants | where-object { $_.ID -eq $Item.DomainID } | Select-Object -ExpandProperty Name NbAgents = $Item.NbRefs InternalName = $Item.Name TenantID = $Item.DomainID StrategyInternalID = $Item.ServiceProfile.ID ProtectionInternalID = $Item.DataProfile.ID } $LinaItems += $CurrentLinaItem } } } } if ($LinaItems.Count -eq 0) { Write-Host2 "No agent group found." Return $Null } Return $LinaItems } function Get-LinaCurrentTenantID { <# .SYNOPSIS Get the current tenant .DESCRIPTION Get the current tenant. If current tenant is the Global View (no tenant selected), it will return -1. .INPUTS None .OUTPUTS Current tenant ID .EXAMPLE $current_tenant_id = Get-LinaCurrentTenantID Get the current tenant ID. #> Write-Verbose "Getting current tenant" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($global:INT_LINA_API_VERSION -le 60) { $request = CallAPI -Path "/ADE/check_session.xml" $current_tenant_id = [int](([xml]$request).session.effective_domain_id) }else { $request = CallAPI -Path "/ADE/check_session.json" $current_tenant_id = $request.effective_domain_id } if ($current_tenant_id -eq -1 -OR $current_tenant_id -eq 1) { # Notes on tenant numbers : -1 and 0 => Global View, 1 = Root (first level tenant invisible/ contains superadmin and guest). >1 : Second level tenants Write-Host2 "No current tenant selected (ID = -1 or 1). Global view on all tenants." Return -1 } elseif ($current_tenant_id -gt 1) { $current_tenant = LinaTenantShort -ID $current_tenant_id $current_tenant_name = $current_tenant.Name Write-Host2 "Current tenant is $current_tenant_name (ID $current_tenant_id)" Return $current_tenant_id } else { TranslateErrorCode -LinaError $request -FailedAction "get current tenant" Return $null } } function Get-LinaCrossRestoreToken { <# .SYNOPSIS Retrieves the cross restore tokens .DESCRIPTION Retrieves the cross restore tokens. Returns a set of tokens that correspond to the filter criteria provided .INPUTS None .OUTPUTS Array of LinaCrossRestoreToken Objects .PARAMETER ID Optional : ID of the cross restore token to retrieve. For example : 134. .PARAMETER Code Optional Code of the cross restore token to retrieve. Wilcards are allowed. For example : 1T7ZF8O56V3JXMKE. .PARAMETER Tenant Optional : Get tokens for specific tenant only .EXAMPLE Get-LinaCrossRestoreToken Get the complete list of cross restore tokens for all tenants .EXAMPLE Get-LinaCrossRestoreToken -Code "1T7ZF8O56V3JXMKE" Get cross restore token(s) matching this code. .EXAMPLE (Get-LinaCrossRestoreToken -Code "1T7ZF8O56V3JXMKE").AgentNames Get list of agent names configured in this token .EXAMPLE Get-LinaCrossRestoreToken -ID 12 Get cross restore token with ID 12 .EXAMPLE Get-LinaCrossRestoreToken -Tenant "MyTenant" Get the list of cross restore tokens for tenant MyTenant #> [cmdletbinding(DefaultParameterSetName = "ByCode")] Param( [Parameter(ParameterSetName = "ByCode", Position = 0)] [ValidateNotNullOrEmpty()] [string]$Code, [Parameter(ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID, [Parameter(Mandatory = $false, Position = 1)] [ValidateNotNullOrEmpty()] [string]$Tenant ) Write-Verbose "Getting cross restore token" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($global:INT_LINA_API_VERSION -lt 52 ) { Write-Error "This feature is only available on Lina 5.2+" return } $current_tenant_id = Get-LinaCurrentTenantID 6>$null if (!$Tenant) { $tenant_list = LinaTenantShort 6>$null }else { $tenant_list = LinaTenantShort -Name $Tenant 6>$null if ( !$tenant_list) { Write-Host2 "ERROR : No tenant found with name $Tenant. Please input the exact name of the Tenant" Return } } $LinaItems = @() # Cross restore tokens are listed by tenants by default foreach ($lina_tenant in $tenant_list) { $void = Set-LinaCurrentTenant -ID $lina_tenant.ID 6>$null $request = CallAPI -Path "/security_cross_listtokens.json" $Items = $request.tokens foreach ($Item in $Items) { if ( (!$ID -AND !$Code) -OR ( $Item.code -like "$Code" -OR $Item.id -eq $ID) ) { if ($Item.expire -eq 0) { $token_expiration_date = "None" }else { $token_expiration_date = LinaToLocalTime $Item.expire } if ($Item.lastlist -eq 0) { $token_lastuse_date = "None" }else { $token_lastuse_date = LinaToLocalTime $Item.lastlist } $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaCrossRestoreToken' ID = $Item.id Tenant = $lina_tenant.Name Code = $Item.code ExpiresIn = HumanFriendlyTimespanFuture (LinaToLocalTime $Item.expire) ExpirationDate = $token_expiration_date AgentNames = $Item.agents.Name NumberUse = $Item.nblist LastUseDate = $token_lastuse_date AgentDetails = $Item.agents TenantID = $lina_tenant.ID } $LinaItems += $CurrentLinaItem } } } # Setting back the current tenant to what it was before the Get command $void = Set-LinaCurrentTenant -ID $current_tenant_id 6>$null if ($LinaItems.Count -eq 0) { Write-Host2 "No cross restore token found." Return $Null } Return $LinaItems } function Get-LinaNode { <# .SYNOPSIS Retrieves the server nodes .DESCRIPTION Retrieves the server nodes .INPUTS None .OUTPUTS Array of LinaNode Objects .PARAMETER Name Optional : Name of the Lina server node to retrieve. Wilcards are allowed. For example : *node1* .PARAMETER ID Optional : ID of the Lina server node to retrieve. .EXAMPLE Get-LinaNode Retrieves all the Lina server nodes. .EXAMPLE Get-LinaNode -Name "*node1*" Retrieves all the lina server nodes containing "node1" in their names. #> [cmdletbinding(DefaultParameterSetName = "ByName")] Param( [Parameter(ParameterSetName = "ByName")] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(ParameterSetName = "ByID")] [ValidateRange(0, 2147483647)] [int]$ID ) Write-Verbose "Getting list of nodes" if ($global:GLOBAL_LINA_CONNECTED -eq $False) { Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" return } if ($global:INT_LINA_API_VERSION -lt 60) { Write-Host2 "ERROR : Get-LinaNode requires a Lina Server with version 6.x or Later" return } if ($GLOBAL_LINA_SERVERTYPE -ne "master") { Write-Host2 "ERROR : Get-LinaNode requires a Lina Server operating in master node." return } $request = CallAPI -Path "/ADE/node/list.json" $Items = $request.nodes $LinaItems = @() foreach ($Item in $Items) { if ((!$Name -AND !$ID -AND $Item.friendly_name) -OR ( $Item.friendly_name -like "$Name" -OR $Item.id -eq $ID ) ) { $CurrentLinaItem = [PSCustomObject]@{ PSTypeName = 'LinaNode' Name = $Item.friendly_name ID = $Item.uuid HostName = $Item.name NbAgents = $Item.nb_agent Port = $Item.port AccessInfo = $Item.access_info Version = $Item.version OS = $Item.os HSSPort = $Item.hss_port AdminPort = $Item.admin_port FreeSpaceGB = [math]::Round(($item.free_space_volume) / (1024 * 1024 * 1024), 2) LastIP = $Item.last_ip LastSeen = HumanFriendlyTimeSpan (LinaToLocalTime ([Int64]$Item.last_seen*1000)) LastSeenDate = LinaToLocalTime ([Int64]$Item.last_seen*1000) IsOffline = [bool]$Item.offline internalID = $Item.id } $LinaItems += $CurrentLinaItem } } if ($LinaItems.Count -eq 0) { Write-Host2 "No node found." Return $Null } Return $LinaItems } |