└── DFSR ├── HISTORY.md ├── LICENSE ├── README.md ├── README-RU.md ├── Get-DFSRObjectDiscovery.ps1 └── Get-DFSRObjectParam.ps1 /DFSR/HISTORY.md: -------------------------------------------------------------------------------- 1 |
UserParameter=dfsr.discovery[*],powershell -NoProfile -ExecutionPolicy Bypass -File "<ZabbixAgentFolder>\Get-DFSRObjectDiscovery.ps1" "$1"
34 |
35 |
37 | UserParameter=dfsr.params[*],powershell -NoProfile -ExecutionPolicy Bypass -File "<ZabbixAgentFolder>\Get-DFSRObjectParam.ps1" "$1" "$2" "$3"
38 |
39 | DFSR::ConnectionState0 ⇒ Connecting1 ⇒ Online2 ⇒ Offline3 ⇒ In ErrorDFSR::RFState0 ⇒ Uninitialized1 ⇒ Initialized2 ⇒ Initial Sync3 ⇒ Auto Recovery4 ⇒ Normal5 ⇒ In ErrorDFSR::ServiceState0 ⇒ Starting1 ⇒ Running2 ⇒ Degraded3 ⇒ Shutting Down100 ⇒ Stopped101 ⇒ Not FoundDFSR::VolumeState0 ⇒ Initialized1 ⇒ Shutting Down2 ⇒ In Error3 ⇒ Auto Recovery
The template is free. Nevertheless, if you are generous person, I will be pleased to receive your "thank$" :)
90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /DFSR/README-RU.md: -------------------------------------------------------------------------------- 1 | English version 2 |UserParameter=dfsr.discovery[*],powershell -NoProfile -ExecutionPolicy Bypass -File "<ZabbixAgentFolder>\Get-DFSRObjectDiscovery.ps1" "$1"
33 |
34 |
36 | UserParameter=dfsr.params[*],powershell -NoProfile -ExecutionPolicy Bypass -File "<ZabbixAgentFolder>\Get-DFSRObjectParam.ps1" "$1" "$2" "$3"
37 |
38 | DFSR::ConnectionState0 ⇒ Connecting1 ⇒ Online2 ⇒ Offline3 ⇒ In ErrorDFSR::RFState0 ⇒ Uninitialized1 ⇒ Initialized2 ⇒ Initial Sync3 ⇒ Auto Recovery4 ⇒ Normal5 ⇒ In ErrorDFSR::ServiceState0 ⇒ Starting1 ⇒ Running2 ⇒ Degraded3 ⇒ Shutting Down100 ⇒ Stopped101 ⇒ Not FoundDFSR::VolumeState0 ⇒ Initialized1 ⇒ Shutting Down2 ⇒ In Error3 ⇒ Auto Recovery
Шаблон распространяется бесплатно, но если Вы человек щедрый, можете поддержать материально - мне будет приятно.
90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /DFSR/Get-DFSRObjectDiscovery.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | #Какой тип объектов собираем 3 | [parameter(Mandatory=$true, Position=0)][String]$ObjectType 4 | ) 5 | 6 | [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 7 | 8 | If ($PSVersionTable.PSVersion.Major -lt 3) { 9 | "The script requires PowerShell version 3.0 or above" 10 | Break 11 | } 12 | If (!(Get-WindowsFeature FS-DFS-Replication).Installed) { 13 | "DFS Replication role not installed" 14 | Break 15 | } 16 | 17 | $ErrorActionPreference = "Continue" 18 | 19 | Set-Variable DFSNamespace -Option ReadOnly -Value "root\MicrosoftDfs" -ErrorAction Ignore 20 | 21 | $Data = @() 22 | 23 | #В зависимости от типа объекта собираем и возвращаем соответствующие данные в JSON 24 | Switch($ObjectType) { 25 | #Счетчики производительности для реплицируемых папок 26 | "RFPerfCounter" { 27 | #Находим в реестре первый номер счетчика, относящегося к объекту "Реплицированные папки DFS" (DFS Replicated Folders) 28 | #(Номера генерируются системой и индивидуальны для каждого сервера) 29 | #Этими номерами будет оперировать заббикс 30 | $PerfObjectRegKey = "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{d7b456d4-ca82-4080-a5d0-27fe1a27a851}\{bfe2736b-c79f-4f36-bd15-2897a1a91d4a}" 31 | $PerfObjectID = (Get-ItemProperty -Path $PerfObjectRegKey -Name "First Counter")."First Counter" 32 | #Получаем список экземпляров для объекта RF (т.е. список папок DFSR, для которых есть счетчики) 33 | Get-WmiObject -Class Win32_PerfFormattedData_Dfsr_DFSReplicatedFolders | ForEach-Object { 34 | #Экземпляр (в нашем случае это RF), с которого собираются данные счетчиков, имеет вид RFName-{RFID} 35 | #Вычленяем из него идентификатор и имя RF 36 | $RFName = $_.Name.Substring(0, $_.Name.IndexOf('-{')) 37 | $RFID = $_.Name.Substring($_.Name.IndexOf('-{') + 2, $_.Name.Length -$_.Name.IndexOf('-{') - 3) 38 | #Находим группу репликации, к которой относится RF 39 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderInfo WHERE ReplicatedFolderGuid = '$RFID'" 40 | $RGName = (Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).ReplicationGroupName 41 | 42 | $Entry = [PSCustomObject] @{ 43 | "{#RGNAME}" = $RGName 44 | "{#RFNAME}" = $_.Name.Substring(0, $_.Name.IndexOf('-{')) 45 | "{#RFPERFOBJECTID}" = $PerfObjectID 46 | "{#RFPERFINSTANCEID}" = $_.Name 47 | #Номера счетчиков получаем последовательным увеличением на 2 того номера, который нашли выше 48 | "{#RFPERFCOUNTER1ID}" = $PerfObjectID + 2 # Staging Files Generated 49 | "{#RFPERFCOUNTER2ID}" = $PerfObjectID + 4 # Staging Bytes Generated 50 | "{#RFPERFCOUNTER3ID}" = $PerfObjectID + 6 # Staging Files Cleaned up 51 | "{#RFPERFCOUNTER4ID}" = $PerfObjectID + 8 # Staging Bytes Cleaned up 52 | "{#RFPERFCOUNTER5ID}" = $PerfObjectID + 10 # Staging Space In Use 53 | "{#RFPERFCOUNTER6ID}" = $PerfObjectID + 12 # Conflict Files Generated 54 | "{#RFPERFCOUNTER7ID}" = $PerfObjectID + 14 # Conflict Bytes Generated 55 | "{#RFPERFCOUNTER8ID}" = $PerfObjectID + 16 # Conflict Files Cleaned up 56 | "{#RFPERFCOUNTER9ID}" = $PerfObjectID + 18 # Conflict Bytes Cleaned up 57 | "{#RFPERFCOUNTER10ID}" = $PerfObjectID + 20 # Conflict Space In Use 58 | "{#RFPERFCOUNTER11ID}" = $PerfObjectID + 22 # Conflict Folder Cleanups Completed 59 | "{#RFPERFCOUNTER12ID}" = $PerfObjectID + 24 # File Installs Succeeded 60 | "{#RFPERFCOUNTER13ID}" = $PerfObjectID + 26 # File Installs Retried 61 | "{#RFPERFCOUNTER14ID}" = $PerfObjectID + 28 # Updates Dropped 62 | "{#RFPERFCOUNTER15ID}" = $PerfObjectID + 30 # Deleted Files Generated 63 | "{#RFPERFCOUNTER16ID}" = $PerfObjectID + 32 # Deleted Bytes Generated 64 | "{#RFPERFCOUNTER17ID}" = $PerfObjectID + 34 # Deleted Files Cleaned up 65 | "{#RFPERFCOUNTER18ID}" = $PerfObjectID + 36 # Deleted Bytes Cleaned up 66 | "{#RFPERFCOUNTER19ID}" = $PerfObjectID + 38 # Deleted Space In Use 67 | "{#RFPERFCOUNTER20ID}" = $PerfObjectID + 40 # Total Files Received 68 | "{#RFPERFCOUNTER21ID}" = $PerfObjectID + 42 # Size of Files Received 69 | "{#RFPERFCOUNTER22ID}" = $PerfObjectID + 44 # Compressed Size of Files Received 70 | "{#RFPERFCOUNTER23ID}" = $PerfObjectID + 46 # RDC Number of Files Received 71 | "{#RFPERFCOUNTER24ID}" = $PerfObjectID + 48 # RDC Size of Files Received 72 | "{#RFPERFCOUNTER25ID}" = $PerfObjectID + 50 # RDC Compressed Size of Files Received 73 | "{#RFPERFCOUNTER26ID}" = $PerfObjectID + 52 # RDC Bytes Received 74 | "{#RFPERFCOUNTER27ID}" = $PerfObjectID + 54 # Bandwidth Savings Using DFS Replication 75 | } 76 | $Data += $Entry 77 | } 78 | } 79 | 80 | #Счетчики производительности для DFSR-подключений 81 | "ConPerfCounter" { 82 | #Находим в реестре первый номер счетчика, относящегося к объекту "Подключения репликации DFS" (DFS Replication Connections) 83 | #(Номера генерируются системой и индивидуальны для каждого сервера) 84 | #Этими номерами будет оперировать заббикс 85 | $PerfObjectRegKey = "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{d7b456d4-ca82-4080-a5d0-27fe1a27a851}\{a689f9be-38ad-4c17-9d62-ad60492084a7}" 86 | $PerfObjectID = (Get-ItemProperty -Path $PerfObjectRegKey -Name "First Counter")."First Counter" 87 | Get-WmiObject -Class Win32_PerfFormattedData_Dfsr_DFSReplicationConnections | ForEach-Object { 88 | #Получаем список экземпляров для объекта RC (т.е. список подключений DFSR, для которых есть счетчики) 89 | #Экземпляр (в нашем случае это подключение), с которого собираются данные счетчиков, имеет вид SendingParnerFQDN-{RCID} 90 | #Вычленяем из него имя отправляющего сервера-партнера и ID подключения 91 | $SendingPartner = $_.Name.Substring(0, $_.Name.IndexOf('-{')) 92 | $RCID = $_.Name.Substring($_.Name.IndexOf('-{') + 2, $_.Name.Length -$_.Name.IndexOf('-{') - 3) 93 | #Находим группу репликации, к которой относится RC 94 | $WMIQuery = "SELECT * FROM DfsrConnectionInfo WHERE ConnectionGuid = '$RCID'" 95 | $RGName = (Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).ReplicationGroupName 96 | 97 | $Entry = [PSCustomObject] @{ 98 | "{#RGNAME}" = $RGName 99 | "{#RCPARTNER}" = $SendingPartner 100 | "{#RCPERFOBJECTID}" = $PerfObjectID 101 | "{#RCPERFINSTANCEID}" = $_.Name 102 | #Номера счетчиков получаем последовательным увеличением на 2 того номера, который нашли выше 103 | "{#RCPERFCOUNTER1ID}" = $PerfObjectID + 2 # Total Bytes Received 104 | "{#RCPERFCOUNTER2ID}" = $PerfObjectID + 4 # Total Files Received 105 | "{#RCPERFCOUNTER3ID}" = $PerfObjectID + 6 # Size of Files Received 106 | "{#RCPERFCOUNTER4ID}" = $PerfObjectID + 8 # Compressed Size of Files Received 107 | "{#RCPERFCOUNTER5ID}" = $PerfObjectID + 10 # Bytes Received Per Second 108 | "{#RCPERFCOUNTER6ID}" = $PerfObjectID + 12 # RDC Number of Files Received 109 | "{#RCPERFCOUNTER7ID}" = $PerfObjectID + 14 # RDC Size of Files Received 110 | "{#RCPERFCOUNTER8ID}" = $PerfObjectID + 16 # RDC Compressed Size of Files Received 111 | "{#RCPERFCOUNTER9ID}" = $PerfObjectID + 18 # RDC Bytes Received 112 | "{#RCPERFCOUNTER10ID}" = $PerfObjectID + 20 # Bandwidth Savings Using DFS Replication 113 | } 114 | $Data += $Entry 115 | } 116 | } 117 | 118 | #Счетчики производительности для томов DFSR 119 | "VolPerfCounter" { 120 | #Находим в реестре первый номер счетчика, относящегося к объекту "Тома службы репликации DFS" (DFS Replication Service Volumes) 121 | #(Номера генерируются системой и индивидуальны для каждого сервера) 122 | #Этими номерами будет оперировать заббикс 123 | $PerfObjectRegKey = "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{d7b456d4-ca82-4080-a5d0-27fe1a27a851}\{3f1707df-6381-4287-affc-a60e109a4d30}" 124 | $PerfObjectID = (Get-ItemProperty -Path $PerfObjectRegKey -Name "First Counter")."First Counter" 125 | #Получаем список DFS Replication Service Volumes 126 | Get-WmiObject -Class Win32_PerfFormattedData_Dfsr_DFSReplicationServiceVolumes | 127 | ForEach-Object { 128 | $RV = [PSCustomObject] @{ 129 | "{#RVNAME}" = $_.Name 130 | "{#RVPERFOBJECTID}" = $PerfObjectID 131 | "{#RVPERFCOUNTER1ID}" = $PerfObjectID + 2 # USN Journal Records Read 132 | "{#RVPERFCOUNTER2ID}" = $PerfObjectID + 4 # USN Journal Records Accepted 133 | "{#RVPERFCOUNTER3ID}" = $PerfObjectID + 6 # USN Journal Unread Percentage 134 | "{#RVPERFCOUNTER4ID}" = $PerfObjectID + 8 # Database Commits 135 | "{#RVPERFCOUNTER5ID}" = $PerfObjectID + 10 # Database Lookups 136 | } 137 | $Data += $RV 138 | } 139 | } 140 | 141 | #Реплицируемые папки, расположенные на сервере 142 | "RF" { 143 | (Get-WmiObject -Namespace $DFSNamespace -Class DfsrReplicatedFolderConfig) | 144 | ForEach-Object { 145 | #Определяем имя группы репликации по ее ID 146 | $RGID = $_.ReplicationGroupGuid 147 | $WMIQuery = "SELECT * FROM DfsrReplicationGroupConfig WHERE ReplicationGroupGuid='$RGID'" 148 | $RGName = (Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).ReplicationGroupName 149 | $RF = [PSCustomObject] @{ 150 | "{#RFID}" = $_.ReplicatedFolderGuid 151 | "{#RFNAME}" = $_.ReplicatedFolderName 152 | "{#RGNAME}" = $RGName 153 | } 154 | $Data += $RF 155 | } 156 | } 157 | 158 | #Бэклог исходящих файлов для каждой из реплицируемых папок 159 | "RFBacklog" { 160 | #текст-ориентир, с помощью которого будем парсить DN подписки 161 | $ReferenceText = ",CN=DFSR-LocalSettings,CN=" 162 | $RFMembers = @() 163 | #Находим в базе AD все включенные DFSR-подписки, кроме своих 164 | (New-Object DirectoryServices.DirectorySearcher "ObjectClass=msDFSR-Subscription").FindAll() | 165 | Where-Object {($_.Properties.distinguishedname -notlike "*$ReferenceText$env:COMPUTERNAME,*") -and 166 | ($_.Properties."msdfsr-enabled" -eq $true)} | 167 | ForEach-Object { 168 | $SubscriptionDN = $_.Properties.distinguishedname 169 | #имя подписанного сервера заключено в DN-строке между текстом-ориентиром 170 | $TempText = $SubscriptionDN.Substring($SubscriptionDN.LastIndexOf($ReferenceText) + $ReferenceText.Length) 171 | #и запятой 172 | $ComputerName = $TempText.Substring(0, $TempText.IndexOf(",")) 173 | $RFMember = [PSCustomObject]@{ 174 | ComputerName = $ComputerName 175 | RFID = [String]$_.Properties.name 176 | } 177 | $RFMembers += $RFMember 178 | } 179 | #Находим группы, в которые входит локальный сервер 180 | $RGs = Get-WmiObject -Namespace $DFSNamespace -Class DfsrReplicationGroupConfig 181 | ForEach ($RG in $RGs) { 182 | $RGID = $RG.ReplicationGroupGuid 183 | $RGName = $RG.ReplicationGroupName 184 | #Находим исходящие подключения, относящиеся к группе 185 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE ReplicationGroupGuid='$RGID' AND Inbound='False'" 186 | $OutConnections = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 187 | #Находим на этом сервере папки (RF), относящиеся к группе, 188 | # кроме и отключенных и readonly-папок, т.к. у них нет бэклога исходящих файлов 189 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderConfig "+ 190 | "WHERE ReplicationGroupGuid='$RGID' AND Enabled='True' AND ReadOnly='False'" 191 | $RFs = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 192 | #Проверяем наличие этих папок на каждом из принимающих партнеров группы 193 | ForEach ($Connection in $OutConnections) { 194 | ForEach ($RF in $RFs) { 195 | $RFID = $RF.ReplicatedFolderGuid 196 | $RFName = $RF.ReplicatedFolderName 197 | #Если принимающий партнер содержит папку, будем создаем метрику для соответствующего бэклога 198 | ForEach ($RFMember in $RFMembers) { 199 | If (($RFMember.RFID -eq $RFID) -and ($RFMember.ComputerName -eq $Connection.PartnerName)) { 200 | $Entry = [PSCustomObject] @{ 201 | "{#RGNAME}" = $RGName 202 | "{#RFNAME}" = $RFName 203 | "{#RFID}" = $RFID 204 | "{#SSERVERNAME}" = $env:COMPUTERNAME 205 | "{#RSERVERID}" = $Connection.PartnerGuid 206 | "{#RSERVERNAME}" = $Connection.PartnerName 207 | } 208 | $Data += $Entry 209 | } 210 | } 211 | } 212 | } 213 | } 214 | } 215 | #Подключения для групп репликации 216 | "Connection" { 217 | Get-WmiObject -Namespace $DFSNamespace -Class DfsrConnectionConfig | 218 | ForEach-Object { 219 | #Определяем имя группы репликации по ее ID 220 | $RGID = $_.ReplicationGroupGuid 221 | $WMIQuery = "SELECT * FROM DfsrReplicationGroupConfig WHERE ReplicationGroupGuid='$RGID'" 222 | $RGName = (Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).ReplicationGroupName 223 | If ($_.Inbound) { 224 | $SendingServer = $_.PartnerName 225 | $ReceivingServer = $env:COMPUTERNAME 226 | } 227 | Else { 228 | $SendingServer = $env:COMPUTERNAME 229 | $ReceivingServer = $_.PartnerName 230 | } 231 | $Connection = [PSCustomObject] @{ 232 | "{#CONNECTIONID}" = $_.ConnectionGuid 233 | "{#RGNAME}" = $RGName 234 | "{#SSERVERNAME}" = $SendingServer 235 | "{#RSERVERNAME}" = $ReceivingServer 236 | } 237 | $Data += $Connection 238 | } 239 | } 240 | 241 | #Группы репликации 242 | "RG" { 243 | Get-WmiObject -Namespace $DFSNamespace -Class DfsrReplicationGroupConfig | 244 | ForEach-Object { 245 | $RG = [PSCustomObject] @{ 246 | "{#RGID}" = $_.ReplicationGroupGuid 247 | "{#RGNAME}" = $_.ReplicationGroupName 248 | } 249 | $Data += $RG 250 | } 251 | } 252 | 253 | #Тома, на которых хранятся реплицируемые папки 254 | "Volume" { 255 | Get-WmiObject -Namespace $DFSNamespace -Class DfsrVolumeConfig | 256 | ForEach-Object { 257 | $Volume = [PSCustomObject] @{ 258 | "{#VOLUMEID}" = $_.VolumeGuid 259 | #Путь изначально возвращается в UNC-формате, поэтому обрезаем начальные символы 260 | "{#VOLUMENAME}" = $_.VolumePath.TrimStart("\\.\") 261 | } 262 | $Data += $Volume 263 | } 264 | } 265 | 266 | #Партнеры по группам репликации 267 | "Partner" { 268 | #Находим группы репликации 269 | Get-WmiObject -Namespace $DFSNamespace -Class DfsrReplicationGroupConfig | 270 | ForEach-Object { 271 | $RGID = $_.ReplicationGroupGuid 272 | $RGName = $_.ReplicationGroupName 273 | #и в каждой группе находим партнеров 274 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE ReplicationGroupGuid='$RGID'" 275 | Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery | 276 | Select-Object PartnerGuid, PartnerName -Unique | ForEach-Object { 277 | $Partner = [PSCustomObject] @{ 278 | "{#PARTNERID}" = $_.PartnerGuid 279 | "{#PARTNERNAME}" = $_.PartnerName 280 | "{#RGNAME}" = $RGName 281 | #Учетная запись, от имени которой работает служба Zabbix Agent 282 | "{#NTACCOUNT}" = "$env:USERDOMAIN\$env:USERNAME" 283 | } 284 | $Data += $Partner 285 | } 286 | } 287 | } 288 | } 289 | 290 | $JSONOutput = @{"data" = $Data} | ConvertTo-Json -Compress 291 | [Console]::WriteLine($JSONOutput) 292 | 293 | -------------------------------------------------------------------------------- /DFSR/Get-DFSRObjectParam.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | #Объект мониторинга, для которого будем возвращать метрики 3 | [parameter(Mandatory=$true, Position=0)][String]$Object, 4 | #Дополнительные параметры, на основании которых будет возвращать метрики для объекта 5 | [parameter(Mandatory=$false, Position=1)]$Param1, 6 | [parameter(Mandatory=$false, Position=2)]$Param2 7 | ) 8 | 9 | Set-Variable DFSNamespace -Option ReadOnly -Value "root\MicrosoftDfs" -ErrorAction Ignore 10 | 11 | Set-Variable RoleNotInstalledText -Option ReadOnly -Value "DFS Replication role not installed" -ErrorAction Ignore 12 | 13 | #Параметры локализации (чтобы разделителем целой и дробной части была точка, т.к. запятую заббикс не поймет) 14 | $USCulture = [System.Globalization.CultureInfo]::GetCultureInfo("en-US") 15 | [System.Threading.Thread]::CurrentThread.CurrentCulture = $USCulture 16 | 17 | <# 18 | #Тайм-аут для получения значения (должен быть меньше таймаута в настройках заббикс-агента) 19 | С помощью этого параметра ограничиваем время опроса партнеров: 20 | Учитывая, что обычно опрос недоступного партнера занимает до 20с, 21 | а Timeout для заббикс-агента обычно меньше (3с по умолчанию), 22 | мы ограничиваем время опроса в самом скрипте, чтобы заббикс-агент не получил NoData из-за таймаута 23 | Это позволит вместо NoData вернуть значение, либо текст ошибки 24 | #> 25 | Set-Variable RequestTimeout -Option ReadOnly -Value 2 -ErrorAction Ignore 26 | 27 | If ($PSVersionTable.PSVersion.Major -lt 3) { 28 | "The script requires PowerShell version 3.0 or above" 29 | Break 30 | } 31 | 32 | $DFSRRoleInstalled = (Get-WindowsFeature FS-DFS-Replication).Installed 33 | 34 | $ErrorActionPreference = "Continue" 35 | 36 | Switch($Object) { 37 | "RoleInstalled" { 38 | $DFSRRoleInstalled 39 | } 40 | "ServiceState" { 41 | $DFSRService = Get-Service DFSR -ErrorAction Ignore 42 | If ($DFSRService) { 43 | If ($DFSRService.Status -eq "Running") { 44 | (Get-WmiObject -Namespace $DFSNamespace -Class DfsrInfo).State 45 | } 46 | Else { 47 | #Если служба остановлена 48 | [int]100 49 | } 50 | } 51 | Else { 52 | #Если служба не найдена 53 | [int]101 54 | } 55 | } 56 | 57 | #DFS Replication service version 58 | "ServiceVer" { 59 | $DFSRConfig = Get-WmiObject -Namespace $DFSNamespace -Class DfsrConfig -ErrorAction Ignore 60 | If ($DFSRConfig) { 61 | $DFSRConfig.ServiceVersion 62 | } 63 | Else { 64 | "n/a" 65 | } 66 | } 67 | 68 | #DFS Replication provider version 69 | "ProvVer" { 70 | $DFSRConfig = Get-WmiObject -Namespace $DFSNamespace -Class DfsrConfig -ErrorAction Ignore 71 | If ($DFSRConfig) { 72 | $DFSRConfig.ProviderVersion 73 | } 74 | Else { 75 | "n/a" 76 | } 77 | } 78 | 79 | #DFS Replication monitoring provider version 80 | "MonProvVer" { 81 | $DFSRInfo = Get-WmiObject -Namespace $DFSNamespace -Class DfsrInfo -ErrorAction Ignore 82 | If ($DFSRInfo) { 83 | $DFSRInfo.ProviderVersion 84 | } 85 | Else { 86 | "n/a" 87 | } 88 | } 89 | 90 | "ServiceUptime" { 91 | If (!$DFSRRoleInstalled) { 92 | $RoleNotInstalledText 93 | Break 94 | } 95 | $DFSRInfo = Get-WmiObject -Namespace $DFSNamespace -Class DfsrInfo -ErrorAction Ignore 96 | If ($DFSRInfo) { 97 | #Получаем время запуска службы в WMI-формате 98 | $WMIStartTime = $DFSRInfo.ServiceStartTime 99 | #и преобразуем его в формат DateTime 100 | $StartTime = [Management.ManagementDateTimeConverter]::ToDateTime($WMIStartTime) 101 | (New-TimeSpan -Start $StartTime -End (Get-Date)).TotalSeconds 102 | } 103 | Else { 104 | "n/a" 105 | } 106 | } 107 | 108 | #Реплицируемая папка 109 | "RF" { 110 | If (!$DFSRRoleInstalled) { 111 | $RoleNotInstalledText 112 | Break 113 | } 114 | $RFID = $Param1 115 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderConfig WHERE ReplicatedFolderGuid='$RFID'" 116 | $RFConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 117 | If (!$RFConfig) { 118 | "RF '$RFID' not found" 119 | Break 120 | } 121 | $RFName = $RFConfig.ReplicatedFolderName 122 | $RGID = $RFConfig.ReplicationGroupGuid 123 | #Статистику можно собирать только с Enabled-папок 124 | If ($RFConfig.Enabled) { 125 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderInfo WHERE ReplicatedFolderGuid='$RFID'" 126 | $RFInfo = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 127 | } 128 | $ErrorText = "Couldn't retrieve info for disabled RF" 129 | 130 | Switch($Param2) { 131 | "Enabled" { 132 | #Включена ли репликация для папки 133 | $RFConfig.Enabled 134 | } 135 | #Удалять файлы вместо перемещения в папку конфликтов 136 | "RemoveDeleted" { 137 | $RFConfig.DisableSaveDeletes 138 | } 139 | "ReadOnly" { 140 | #Папка работает в режиме "только чтение" 141 | $RFConfig.ReadOnly 142 | } 143 | #Максимальный размер, заданный для промежуточной папки, байт 144 | "StageQuota" { 145 | $RFConfig.StagingSizeInMb*1024*1024 146 | } 147 | #Максимальный размер, заданный для папки ConflictAndDeleted, байт 148 | "ConflictQuota" { 149 | $RFConfig.ConflictSizeInMb*1024*1024 150 | } 151 | "State" { 152 | If ($RFInfo) { 153 | # 0 - Uninitialized, 1 - Initialized, 2 - Initial Sync, 154 | # 3 - Auto Recovery, 4 - Normal, 5 - In Error 155 | $RFInfo.State 156 | } 157 | Else { 158 | "Couldn't retrieve info for disabled RF" 159 | } 160 | } 161 | #Текущий размер промежуточной папки, байт 162 | "StageSize" { 163 | If ($RFInfo) { 164 | $RFInfo.CurrentStageSizeInMb*1024*1024 165 | } 166 | Else { 167 | "Couldn't retrieve info for disabled RF" 168 | } 169 | } 170 | #% свободного места в промежуточной папке 171 | "StagePFree" { 172 | If ($RFInfo) { 173 | ($RFConfig.StagingSizeInMb - $RFInfo.CurrentStageSizeInMb)/ ` 174 | $RFConfig.StagingSizeInMb*100 175 | } 176 | Else { 177 | $ErrorText 178 | } 179 | } 180 | #Текущий размер папки ConflictAndDeleted, байт 181 | "ConflictSize" { 182 | If ($RFInfo) { 183 | $RFInfo.CurrentConflictSizeInMb*1024*1024 184 | } 185 | Else { 186 | $ErrorText 187 | } 188 | } 189 | #% свободного места в папке ConflictAndDeleted 190 | "ConflictPFree" { 191 | If ($RFInfo) { 192 | ($RFConfig.ConflictSizeInMb - $RFInfo.CurrentConflictSizeInMb)/ ` 193 | $RFConfig.ConflictSizeInMb*100 194 | } 195 | Else { 196 | $ErrorText 197 | } 198 | } 199 | #На скольких партнерах имеется копия папки в рабочем состоянии 200 | "Redundancy" { 201 | #Находим партнеров по группе репликации 202 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE ReplicationGroupGuid='$RGID'" 203 | $PartnersByGroup = (Get-WmiObject ` 204 | -Namespace $DFSNamespace ` 205 | -Query $WMIQuery).PartnerName | Select-Object -Unique 206 | $n = 0 207 | #Проверяем наличие папки, имеющей состояние 'Normal' (4), на каждом из партнеров 208 | ForEach ($Partner in $PartnersByGroup) { 209 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderInfo " + 210 | "WHERE ReplicatedFolderGuid='$RFID' AND State=4" 211 | #и подсчитываем общее количество таких папок 212 | $j = Get-WmiObject -ComputerName $Partner ` 213 | -Namespace $DFSNamespace ` 214 | -Query $WMIQuery ` 215 | -ErrorAction Ignore -AsJob 216 | [void](Wait-Job $j -Timeout $RequestTimeout) 217 | If ($j.State -eq "Completed") { 218 | $n += @(Receive-Job $j).Count 219 | } 220 | #Если не можем опросить хотя одного партнера, прекращаем опрос и возвращаем ошибку 221 | Else { 222 | $n = -1 223 | "Couldn't retrieve info from partner '$Partner'" 224 | Break 225 | } 226 | } 227 | #Если всё хорошо, возвращаем количество партнеров, хранящих копию папки 228 | If ($n -ge 0) { 229 | $n 230 | } 231 | } 232 | } 233 | } 234 | 235 | "RFBacklog" { 236 | If (!$DFSRRoleInstalled) { 237 | $RoleNotInstalledText 238 | Break 239 | } 240 | $RFID = $Param1 241 | $RServerID = $Param2 #ID принимающего партнера 242 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderConfig WHERE ReplicatedFolderGuid='$RFID'" 243 | $RFConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 244 | If (!$RFConfig) { 245 | "RF '$RFID' not found" 246 | Break 247 | } 248 | #Находим имя принимающего партнера по ID 249 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE PartnerGuid='$RServerID' AND Inbound='False'" 250 | $ConnectionConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 251 | If (!$ConnectionConfig) { 252 | "Outbound connection to partner '$RServerID' not found" 253 | Break 254 | } 255 | $RServerName = $ConnectionConfig.PartnerName 256 | #Зная ID папки, находим ее имя и имя группы, которой она принадлежит 257 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderInfo WHERE ReplicatedFolderGuid='$RFID'" 258 | #Запрашиваем у принимающего партнера информацию о папке 259 | $j = Get-WmiObject -ComputerName $RServerName ` 260 | -Namespace $DFSNamespace ` 261 | -Query $WMIQuery ` 262 | -ErrorAction Ignore -AsJob 263 | [void](Wait-Job $j -Timeout $RequestTimeout) 264 | If ($j.State -eq "Completed") { 265 | Try { 266 | #и пытаемся извлечь с этого партнера вектор версии 267 | $VersionVector = (Receive-Job $j).GetVersionVector().VersionVector 268 | #На отправляющем партнере (т.е. на локальном сервере) определяем размер бэклога для найденного вектора 269 | (Get-WmiObject ` 270 | -Namespace $DFSNamespace ` 271 | -Query $WMIQuery).GetOutboundBacklogFileCount($VersionVector).BacklogFileCount 272 | } 273 | Catch { 274 | If ($VersionVector) { 275 | "Couldn't retrieve backlog info for vector '$VersionVector'" 276 | } 277 | Else { 278 | "Version vector not found" 279 | } 280 | } 281 | } 282 | Else { 283 | "Couldn't retrieve info from partner '$RServerName'" 284 | } 285 | } 286 | 287 | "Connection" { 288 | If (!$DFSRRoleInstalled) { 289 | $RoleNotInstalledText 290 | Break 291 | } 292 | $ConnectionID = $Param1 293 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE ConnectionGuid='$ConnectionID'" 294 | $ConnectionConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 295 | If (!$ConnectionConfig) { 296 | "Connection '$ConnectionID' not found" 297 | Break 298 | } 299 | Switch($Param2) { 300 | "Enabled" { 301 | $ConnectionConfig.Enabled 302 | } 303 | "State" { 304 | #Статистику можно получить только с enabled-подключений 305 | If ($ConnectionConfig.Enabled) { 306 | $WMIQuery = "SELECT * FROM DfsrConnectionInfo WHERE ConnectionGuid='$ConnectionID'" 307 | $ConnectionInfo = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 308 | If ($ConnectionInfo) { 309 | #0 - Connecting, 1 - Online, 2 - Offline, 3 - In Error 310 | $ConnectionInfo.State 311 | } 312 | Else { 313 | "Coundn't retrieve connection info. Check availability of partner '$($ConnectionConfig.PartnerName)'" 314 | } 315 | } 316 | Else { 317 | "Coundn't retrieve info for disabled connection" 318 | } 319 | } 320 | #Если репликация полностью выключена по расписанию 321 | "BlankSchedule" { 322 | [Int]$s = 0 323 | $ConnectionConfig.Schedule | ForEach-Object { 324 | $s += $_ 325 | } 326 | #Если репликация отключена для каждого часа каждого дня, возвращаем True 327 | [Boolean]($s -eq 0) 328 | } 329 | } 330 | } 331 | 332 | "RG" 333 | { 334 | If (!$DFSRRoleInstalled) { 335 | $RoleNotInstalledText 336 | Break 337 | } 338 | $RGID = $Param1 339 | $WMIQuery = "SELECT * FROM DfsrReplicationGroupConfig WHERE ReplicationGroupGuid='$RGID'" 340 | $RGConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 341 | If (!$RGConfig) { 342 | "RG '$RGID' not found" 343 | Break 344 | } 345 | Switch($Param2) { 346 | #количество папок в группе 347 | "RFCount" { 348 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderConfig WHERE ReplicationGroupGuid='$RGID'" 349 | @(Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).Count 350 | } 351 | #количество входящих подключений (в т.ч. disabled) от партнеров группы 352 | "InConCount" { 353 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE ReplicationGroupGuid='$RGID' AND Inbound='True'" 354 | @(Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).Count 355 | } 356 | #количество исходящих подключений (в т.ч. disabled) от партнеров группы 357 | "OutConCount" { 358 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE ReplicationGroupGuid='$RGID' AND Inbound='False'" 359 | @(Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).Count 360 | } 361 | #Если в дефолтном расписании для группы репликация полностью выключена 362 | "BlankSchedule" { 363 | $WMIQuery = "SELECT * FROM DfsrReplicationGroupConfig WHERE ReplicationGroupGuid='$RGID'" 364 | $RGConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 365 | If ($RGConfig) { 366 | [Int]$s = 0 367 | $RGConfig.DefaultSchedule | ForEach-Object { 368 | $s += $_ 369 | } 370 | #Если репликация отключена для каждого часа каждого дня, возвращаем True 371 | [Boolean]($s -eq 0) 372 | } 373 | } 374 | } 375 | } 376 | 377 | #Количество групп репликации, в которые входит сервер 378 | "RGCount" { 379 | If (!$DFSRRoleInstalled) { 380 | $RoleNotInstalledText 381 | Break 382 | } 383 | @(Get-WmiObject -Namespace $DFSNamespace -Class DfsrReplicationGroupConfig).Count 384 | } 385 | 386 | "Partner" { 387 | If (!$DFSRRoleInstalled) { 388 | $RoleNotInstalledText 389 | Break 390 | } 391 | $PartnerID = $Param1 392 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE PartnerGuid='$PartnerID'" 393 | $ConnectionConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 394 | If (!$ConnectionConfig) { 395 | "Partner '$PartnerID' not found" 396 | Break 397 | } 398 | $PartnerName = (Get-WmiObject ` 399 | -Namespace $DFSNamespace ` 400 | -Query $WMIQuery).PartnerName | Select-Object -Unique 401 | Switch($Param2) { 402 | "PingCheckOK" { 403 | $CheckResult = Test-Connection -ComputerName $PartnerName ` 404 | -Count 1 -Delay 1 -ErrorAction Ignore 405 | [Boolean]($CheckResult -ne $Null) 406 | } 407 | "WMICheckOK" { 408 | $WMIQuery = "SELECT * FROM DfsrConfig" 409 | $j = Get-WmiObject -ComputerName $PartnerName ` 410 | -Namespace $DFSNamespace ` 411 | -Query $WMIQuery ` 412 | -ErrorAction Ignore -AsJob 413 | [void](Wait-Job $j -Timeout $RequestTimeout) 414 | [Boolean]($j.State -eq "Completed") 415 | } 416 | } 417 | } 418 | 419 | "Volume" { 420 | If (!$DFSRRoleInstalled) { 421 | $RoleNotInstalledText 422 | Break 423 | } 424 | $VolumeID = $Param1 425 | $WMIQuery = "SELECT * FROM DfsrVolumeConfig WHERE VolumeGuid='$VolumeID'" 426 | $VolumeConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 427 | If (!$VolumeConfig) { 428 | "Volume '$VolumeID' not found" 429 | Break 430 | } 431 | Switch ($Param2) { 432 | "State" { 433 | $WMIQuery = "SELECT * FROM DfsrVolumeInfo WHERE VolumeGuid='$VolumeID'" 434 | #0 - Initialized, 1 - Shutting Down, 2 - In Error, 3 - Auto Recovery 435 | (Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).State 436 | } 437 | } 438 | } 439 | 440 | "Log" { 441 | If (!$DFSRRoleInstalled) { 442 | $RoleNotInstalledText 443 | Break 444 | } 445 | $ErrorActionPreference = "Stop" 446 | Try { 447 | [String]$TimeSpanAsString = $Param2 448 | $EndTime = Get-Date 449 | #Коэффициент для перевода из исходных единиц измерения в секунды 450 | $Multiplier = 1 451 | #Определяем единицы измерения (смотрим последний символ в полученной строке) 452 | $TimeUnits = $TimeSpanAsString[$TimeSpanAsString.Length-1] 453 | #Если единицы не указаны (на конце цифра), 454 | If ($TimeUnits -match "\d") { 455 | #считаем, что получили значение в секундах 456 | $TimeValue = ($TimeSpanAsString -as [Int]) 457 | } 458 | Else { 459 | #Числовое значение получаем, отбросив последний символ строки 460 | $TimeValue = ($TimeSpanAsString.Substring(0, $TimeSpanAsString.Length - 1) -as [Int]) 461 | #Переводим из исходных единиц измерения в секунды 462 | Switch ($TimeUnits) { 463 | "m" {$Multiplier = 60} #минуты 464 | "h" {$Multiplier = 3600} #часы 465 | "d" {$Multiplier = 86400} #дни 466 | "w" {$Multiplier = 604800} #недели 467 | } 468 | } 469 | $StartTime = $EndTime.AddSeconds(-$TimeValue*$Multiplier) 470 | 471 | $Filter = @{ 472 | LogName="DFS Replication" 473 | StartTime=$StartTime 474 | EndTime=$EndTime 475 | } 476 | Switch ($Param1) { 477 | "WarnCount" {$Filter += @{Level=3}} 478 | "ErrCount" {$Filter += @{Level=2}} 479 | "CritCount" {$Filter += @{Level=1}} 480 | } 481 | @(Get-WinEvent -FilterHashtable $Filter -ErrorAction Ignore).Count 482 | } 483 | Catch { 484 | $Error[0].Exception.Message 485 | } 486 | } 487 | } 488 | --------------------------------------------------------------------------------