TisaneOnprem.psm1
#Region '.\Public\Check-ServiceCpu.ps1' 0 function Check-ServiceCpu { param ( [Parameter(Mandatory=$true)][string]$service ) $NUMBER_OF_CORES = 1 $procId = (Get-CimInstance Win32_Service | ?{$_.Name -like $service} | SELECT ProcessId).ProcessId $procPath = (Get-Counter "\Process(*)\ID Process" -ErrorAction SilentlyContinue).CounterSamples | Where-Object {$_.CookedValue -eq $procId} | Select-Object -ExpandProperty Path $procCpuUsage = [Math]::Round(((Get-Counter ($procPath -replace "\\id process$","\% Processor Time")).CounterSamples.CookedValue) / $NUMBER_OF_CORES) return $procCpuUsage } #EndRegion '.\Public\Check-ServiceCpu.ps1' 12 #Region '.\Public\Check-ServiceStatus.ps1' 0 function Check-ServiceStatus { param ( [Parameter(Mandatory=$true)][string]$hostIp, [Parameter(Mandatory=$true)][int]$timeout ) $uri = $hostIp+"parse" $response = Invoke-WebRequest -Uri $uri -Method POST -Headers $headers -ContentType 'application/json' -Body '{"language": "en", "content": "this is a test sentence to test the testing of tisane", "settings": {"parses":true,"debug":true}}' -TimeoutSec $timeout -ErrorAction SilentlyContinue if ($response.StatusCode -eq 200) { return $true } else { return $false } } # Check-IfServiceDown "http://94.237.73.126:80/" #EndRegion '.\Public\Check-ServiceStatus.ps1' 15 #Region '.\Public\Download-TisaneFromFTP.ps1' 0 function Download-TisaneFromFTP{ [CmdletBinding()] Param( [Parameter(Mandatory = $true, valueFromPipeline=$true, HelpMessage="FTP user: ")][String] $user, [Parameter(Mandatory = $true, HelpMessage="FTP password: ")][String] $password, [Parameter(Mandatory = $true, HelpMessage="FTP host: ")][String] $ftp ) $DOWNLOAD_FOLDER = "C:\Users\Administrator\Downloads\Tisane" $TISANE_ROOT = "C:\Tisane" $webclient = New-Object System.Net.WebClient if(-not(Test-Path($DOWNLOAD_FOLDER))) { # file with path $path doesn't exist mkdir $DOWNLOAD_FOLDER } $webclient.Credentials = New-Object System.Net.NetworkCredential("$user@$ftp", $password) $uri = New-Object System.Uri("ftp://ftp.$ftp/tisane_db.zip") Write-Host "Downloading Tisane data to $DOWNLOAD_FOLDER..." -ForegroundColor Green $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER\tisane_db.zip") Write-Host "Downloading Tisane Web Service to $DOWNLOAD_FOLDER..." -ForegroundColor Green $uri = New-Object System.Uri("ftp://ftp.$ftp/tisane_ws.zip") $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER\tisane_ws.zip") if(Test-Path($TISANE_ROOT)) { #mkdir $TISANE_ROOT #Remove-Item -Path "$TISANE_ROOT\" -Recurse # dir $TISANE_ROOT -Recurse | Where-Object { $_.FullName -imatch '^C:\\tisane\\([^\\]+)\\.+[.]sst' } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue } #Add-Type -AssemblyName System.IO.Compression.FileSystem #Add-Type -Assembly "System.IO.Compression.Filesystem" Add-Type -Assembly "System.Io.Compression.FileSystem" [System.IO.Compression.ZipFile]::ExtractToDirectory("$DOWNLOAD_FOLDER\tisane_db.zip", "$DOWNLOAD_FOLDER\db") } #EndRegion '.\Public\Download-TisaneFromFTP.ps1' 42 #Region '.\Public\Install-TisaneFromFTP.ps1' 0 function Install-TisaneFromFTP{ [CmdletBinding()] Param( [Parameter(Mandatory = $true, valueFromPipeline=$true, HelpMessage="FTP user: ")][String] $user, [Parameter(Mandatory = $true, HelpMessage="FTP password: ")][String] $password, [Parameter(Mandatory = $true, HelpMessage="FTP host: ")][String] $ftp, [Parameter(Mandatory = $false, HelpMessage="Install .NET? ")][boolean] $dotnet, [Parameter(Mandatory = $true, HelpMessage="Instance count: ")][int] $instances, [Parameter(Mandatory = $false, HelpMessage="Windows user: ")][String] $winuser ) if (-not($winuser)) { $winuser = 'Administrator' } $DOWNLOAD_FOLDER = "C:\Users\$winuser\Downloads\Tisane" $dotNETInstallerUrl = "https://go.microsoft.com/fwlink/?linkid=2088631" $TISANE_ROOT = "C:\Tisane" $webclient = New-Object System.Net.WebClient if(-not(Test-Path($DOWNLOAD_FOLDER))) { # file with path $path doesn't exist mkdir $DOWNLOAD_FOLDER } if ($dotnet) { Write-Host "Downloading .NET installer to $DOWNLOAD_FOLDER..." -ForegroundColor Green $webclient.DownloadFile($dotNETInstallerUrl, "$DOWNLOAD_FOLDER\dotnetinstaller.exe") Write-Host "Installing .NET..." -ForegroundColor Green Start-Process -FilePath $DOWNLOAD_FOLDER\dotnetinstaller.exe -ArgumentList "/q","/norestart" -Wait } $webclient.Credentials = New-Object System.Net.NetworkCredential("$user@tisane.ai", $password) $uri = New-Object System.Uri("ftp://$ftp/tisane_db.zip") Write-Host "Downloading Tisane data to $DOWNLOAD_FOLDER..." -ForegroundColor Green $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER\tisane_db.zip") Write-Host "Downloading Tisane Web Service to $DOWNLOAD_FOLDER..." -ForegroundColor Green $uri = New-Object System.Uri("ftp://$ftp/tisane_ws.zip") $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER\tisane_ws.zip") $uri = New-Object System.Uri("ftp://$ftp/Tisane.Runtime.Service.exe.config") $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER\Tisane.Runtime.Service.exe.config") if(Test-Path($TISANE_ROOT)) { #mkdir $TISANE_ROOT #Remove-Item -Path $TISANE_ROOT -Recurse } #Add-Type -AssemblyName System.IO.Compression.FileSystem #[System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath) Write-Host "Extracting Tisane data to $TISANE_ROOT..." -ForegroundColor Green # WE HAVE TO USE Ionic Zip because the standard compression libraries crash with very large archives [System.Reflection.Assembly]::LoadFrom("$DOWNLOAD_FOLDER\Ionic.Zip.dll") $zipFile = New-Object Ionic.Zip.ZipFile("$DOWNLOAD_FOLDER\tisane_db.zip") #Expand-Archive -LiteralPath "$DOWNLOAD_FOLDER\tisane_db.zip" -DestinationPath $TISANE_ROOT $zipFile.ExtractAll($TISANE_ROOT, 1) $portNumber = 81 For ($i=1; $i -le $instances; $i++) { $formattedI = $i | % tostring 00 $portNumber = 79 + $i Write-Host "Creating instance under $TISANE_ROOT\instance$formattedI" -ForegroundColor Green Expand-Archive -LiteralPath "$DOWNLOAD_FOLDER\tisane_ws.zip" -DestinationPath "$TISANE_ROOT\instance$formattedI" -Force $webclient.DownloadFile($uri, "$TISANE_ROOT\instance$formattedI\Tisane.Runtime.Service.exe.config") ((Get-Content -path "$TISANE_ROOT\instance$formattedI\Tisane.Runtime.Service.exe.config" -Raw) -replace 'localhost:80',"localhost:$portNumber") | Set-Content -Path "$TISANE_ROOT\instance$formattedI\Tisane.Runtime.Service.exe.config" Start-Process -FilePath "$TISANE_ROOT\instance$formattedI\Tisane.Runtime.Service.exe" -ArgumentList "-i" -Wait } # now open firewall ports netsh advfirewall firewall add rule name='Tisane ports' dir=in protocol=tcp localport="80-$portNumber" action=allow profile=any # create a quarterly update task SchTasks /Create /sc monthly /mo 3 /TN "Tisane update" /TR "$DOWNLOAD_FOLDER\UpdateTisaneFromFTP.ps1 -user $user -password $password -ftp $ftp" /ST 23:00 # start the services Start-Service "Tisane Runtime *" } #EndRegion '.\Public\Install-TisaneFromFTP.ps1' 83 #Region '.\Public\Monitor-Tisane.ps1' 0 function Monitor-Tisane { [CmdletBinding()] param ( [Parameter(Mandatory=$true, HelpMessage="Service names to monitor: ")][string[]]$services, [Parameter(Mandatory=$false, HelpMessage="Timeout for monitor (Default 120s)")][int]$interval = 120, [Parameter(Mandatory=$false, HelpMessage="Threshold for CPU consuption (Default 100)")][int]$thresholdCpu = 100, [Parameter(Mandatory=$false, HelpMessage="Timeout for the healthcheck: (Default 2s)")][int]$timeout = 2, [Parameter(Mandatory=$false, HelpMessage="Number of health checks to fail consecutively before restart : (Default 1)")][int]$failureBeforeRestart = 1 ) Write-Host "The script allows you to get email notification, Please run Setup-Email to configure the credentials" $hostName = [System.Net.Dns]::GetHostName() $Results = @{} $originalServiceNames = @{} $servicesOriginal = $services Write-Host $services $services = $servicesOriginal -replace '\[','?' -replace '\]','?' foreach ($service in $services) { $oneService = Get-CimInstance Win32_Service | ?{$_.Name -like $service} | SELECT Name , PathName if ([string]::IsNullOrEmpty($oneService)){ Write-Host "$service not found" -ForegroundColor RED Write-Host "Abortting !!" return 1 } $serviceName = $oneService.Name $configFile = $oneService.PathName -replace "\.exe", ".exe.config" -replace '\"', '' if (Test-Path $configFile) { $config = [xml](Get-Content $configFile) $AddNode = Select-Xml -Xml $config -XPath "//services/service/host/baseAddresses" $Value = $AddNode.Node.add.baseAddress $Results[$service] = $Value $originalServiceNames[$service]=$serviceName }else{ Write-Host "Config file for $service not found" -ForegroundColor Red Write-Host "Abortting !!" return 1 } } $hostIpS = $Results.Values $services = $Results.Keys # $originalNames = $originalServiceNames.Values Write-Host "Starting monitor for the following services" # Write-Host $originalServiceNames.Values -ForegroundColor Green # Write-Host "Corresponding endpoints: " # Write-Host $hostIpS -ForegroundColor Green $combinedList = for ($i = 0; $i -lt $hostIpS.Count; $i++) { [PSCustomObject]@{ Services = $services[$i] Endpoints = $Results[$services[$i]] } } $combinedList | Format-Table -AutoSize $restarting =@{} $failureCount = @{} while ($true) { foreach ($service in $services) { $hostIp = $Results[$service] if ($restarting.ContainsKey($service)) { Write-Host "$service is being restarted" if (Check-ServiceStatus -hostIp $hostIp -timeout $timeout) { Write-Host "Service on $service has restared" $restarting.Remove($service) } continue } $cpuUsage = Check-ServiceCpu $service if ((Check-ServiceStatus -hostIp $hostIp -timeout $timeout) -and ( $cpuUsage -le $thresholdCpu)) { Write-Host "$service is running, consuming $cpuUsage% cpu" $failureCount[$service] = 0 } else { $failureCount[$service]++ $oneServiceFaliurCount = $failureCount[$service] Write-Host "$service failed $oneServiceFaliurCount health checks consecutively" if ($oneServiceFaliurCount -ge $failureBeforeRestart){ $restarting[$service]=$hostIp Stop-Service -Name $service Start-Service -Name $service Write-Host "sending mail" $date = Get-Date $subject = "Tisane admin alert [$hostName]" $instanceName = $originalServiceNames[$service] $body = "[$instanceName] running on [$hostName] was restarted on [$date] after health check failed" Send-Email -body $body -subject -$subject } } } # Sleep for 120 seconds Start-Sleep -Seconds $interval } } #EndRegion '.\Public\Monitor-Tisane.ps1' 92 #Region '.\Public\Reset-EmailSettings.ps1' 0 function Reset-EmailSettings { Save-LampSetting -settingName 'emailTo' -settingValue $null Save-LampSetting -settingName 'smtpServer' -settingValue $null Save-LampSetting -settingName 'smtpPort' -settingValue '587' Save-LampSetting -settingName 'emailUsername' -settingValue $null Save-LampSetting -settingName 'emailPassword' -settingValue $null } #EndRegion '.\Public\Reset-EmailSettings.ps1' 8 #Region '.\Public\Send-Email.ps1' 0 function Send-Email() { Param( [Parameter(Mandatory=$false, HelpMessage="Body: ")][String] $body, [Parameter(Mandatory=$false, HelpMessage="Subject: " )][String] $subject ) $To = Get-LampSetting -settingName 'emailTo' -defaultValue '' $To = $To.Split(",") $smtpServer = Get-LampSetting -settingName 'smtpServer' -defaultValue 'mail.tisane.ai' $smtpPort = Get-LampSetting -settingName 'smtpPort' -defaultValue '587' $emailUsername = Get-LampSetting -settingName 'emailUsername' -defaultValue '' $encryptedEmailPassword = Get-LampSetting -settingName 'emailPassword' -defaultValue '' $secureEmailPassword = ConvertTo-SecureString -String $encryptedEmailPassword $emailCredential = New-Object System.Management.Automation.PSCredential($emailUsername, $secureEmailPassword) Send-MailMessage -To $To -From $emailUsername -Subject $subject -Body $body -Credential $emailCredential -SmtpServer $SmtpServer -Port $SmtpPort Write-Host "Email sent" } #EndRegion '.\Public\Send-Email.ps1' 19 #Region '.\Public\Setup-Email.ps1' 0 function Setup-Email { Write-Host "Comma-delimited email addresses to send alerts to:" $To = Read-Host $To = $To.Split(",") Save-LampSetting -settingName 'emailTo' -settingValue $To $smtpServer = Read-Host "SMTP server" $smtpPort = Read-Host "SMTP port (default: 587)" Save-LampSetting -settingName 'smtpServer' -settingValue $smtpServer Save-LampSetting -settingName 'smtpPort' -settingValue $smtpPort if ([string]::IsNullOrEmpty($smtpServer)) { $smtpServer = Get-LampSetting -settingName 'smtpServer' -defaultValue '' } if ([string]::IsNullOrEmpty($smtpPort)) { $smtpPort = Get-LampSetting -settingName 'smtpPort' -defaultValue '587' } $emailUsername = Get-LampSetting -settingName 'emailUsername' -defaultValue '' $encryptedEmailPassword = Get-LampSetting -settingName 'emailPassword' -defaultValue '' if ([string]::IsNullOrEmpty($emailUsername)){ # Write-Host "in if" # $credential = Get-Credential -Message "Sender email account credentials" $credential = $host.ui.PromptForCredential("Sender email account credentials", "Sender email account credentials", "", "") $emailUsername = $credential.UserName $secureEmailPassword = $credential.Password $encryptedEmailPassword = ConvertFrom-SecureString -SecureString $secureEmailPassword Save-LampSetting -settingName 'emailUsername' -settingValue $emailUsername Save-LampSetting -settingName 'emailPassword' -settingValue $encryptedEmailPassword }else{ # Write-Host "in else" $secureEmailPassword = ConvertTo-SecureString -String $encryptedEmailPassword } # $emailPassword = [System.Net.NetworkCredential]::new("", $secureEmailPassword).Password $emailCredential = New-Object System.Management.Automation.PSCredential($emailUsername, $secureEmailPassword) $date = Get-Date $subject = "Tisane admin test email" $body = "This is a test email sent by Monitor-Tisane script [ $date ]" Write-Host "Email settings : " Write-Host "To: $To" Write-Host "From: $emailUsername" Write-Host "smtpServer: $smtpServer" Write-Host "smtpPort: $smtpPort" try { Send-MailMessage -To $To -From $emailUsername -Subject $subject -Body $body -Credential $emailCredential -SmtpServer $smtpServer -Port $smtpPort } catch { Write-Host "An error occurred while sending the email:" -ForegroundColor RED Write-Host "Please reset the settings using Reset-EmailSettings, and run the Setup-Email again."-ForegroundColor RED return } Send-MailMessage -To $To -From $emailUsername -Subject $subject -Body $body -Credential $emailCredential -SmtpServer $smtpServer -Port $smtpPort Write-Host "Test Email sent" -ForegroundColor Green Write-Host "Please check your inbox, if you did not receive the email, please reset the settings using Reset-EmailSettings, and run the Setup-Email again." } #EndRegion '.\Public\Setup-Email.ps1' 55 #Region '.\Public\Update-TisaneFromFTP.ps1' 0 function Update-TisaneFromFTP{ [CmdletBinding()] Param( [Parameter(Mandatory = $true, valueFromPipeline=$true, HelpMessage="FTP user: ")][String] $user, [Parameter(Mandatory = $true, HelpMessage="FTP password: ")][String] $password, [Parameter(Mandatory = $true, HelpMessage="FTP host: ")][String] $ftp, [Parameter(Mandatory = $false, HelpMessage="Copy only, no need to reregister the service: ")][Boolean] $copyOnly ) $DOWNLOAD_FOLDER = "C:\Users\Administrator\Downloads\Tisane" $TISANE_ROOT = "C:\Tisane" $webclient = New-Object System.Net.WebClient if(-not(Test-Path($DOWNLOAD_FOLDER))) { # file with path $path doesn't exist mkdir $DOWNLOAD_FOLDER } $webclient.Credentials = New-Object System.Net.NetworkCredential("$user@$ftp", $password) $uri = New-Object System.Uri("ftp://ftp.$ftp/tisane_db.zip") Write-Host "Downloading Tisane data to $DOWNLOAD_FOLDER..." -ForegroundColor Green $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER\tisane_db.zip") Stop-Service "Tisane Runtime *" Write-Host "Downloading Tisane Web Service to $DOWNLOAD_FOLDER..." -ForegroundColor Green $uri = New-Object System.Uri("ftp://ftp.$ftp/tisane_ws.zip") $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER\tisane_ws.zip") if(Test-Path($TISANE_ROOT)) { #mkdir $TISANE_ROOT #Remove-Item -Path "$TISANE_ROOT\" -Recurse # dir $TISANE_ROOT -Recurse | Where-Object { $_.FullName -imatch '^C:\\tisane\\([^\\]+)\\.+[.]sst' } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue } #Add-Type -AssemblyName System.IO.Compression.FileSystem #Add-Type -Assembly "System.IO.Compression.Filesystem" # WE HAVE TO USE Ionic Zip because the standard compression libraries crash with very large archives [System.Reflection.Assembly]::LoadFrom("$DOWNLOAD_FOLDER\Ionic.Zip.dll") $zipFile = New-Object Ionic.Zip.ZipFile("$DOWNLOAD_FOLDER\tisane_db.zip") #[System.IO.Compression.ZipFile]::ExtractToDirectory("$DOWNLOAD_FOLDER\tisane_db.zip", $TISANE_ROOT, $true) Write-Host "Extracting Tisane data to $TISANE_ROOT..." -ForegroundColor Green #Expand-Archive -LiteralPath "$DOWNLOAD_FOLDER\tisane_db.zip" -DestinationPath $TISANE_ROOT -Force (Get-Service "Tisane *").WaitForStatus('Stopped') $zipFile.ExtractAll($TISANE_ROOT, 1) # dir $TISANE_ROOT -Recurse | Where-Object { $_.FullName -imatch '^C:\\tisane\\([^\\]+)\\LOG[.]old.+' } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $services = Get-Service "Tisane Runtime *" $instances = $services.length For ($i=1; $i -le $instances; $i++) { $formattedI = $i | % tostring 00 Write-Host "Updating instance under $TISANE_ROOT\instance$formattedI" -ForegroundColor Green Expand-Archive -LiteralPath "$DOWNLOAD_FOLDER\tisane_ws.zip" -DestinationPath "$TISANE_ROOT\instance$formattedI" -Force if (-not $copyOnly) { Start-Process -FilePath "$TISANE_ROOT\instance$formattedI\Tisane.Runtime.Service.exe" -ArgumentList "-r" -Wait } } Start-Service "Tisane Runtime *" } #EndRegion '.\Public\Update-TisaneFromFTP.ps1' 69 #Region '.\Public\Update-TisaneFromLocalZips.ps1' 0 function Update-TisaneFromLocalZips{ Stop-Service "Tisane Runtime *" $DOWNLOAD_FOLDER = "C:\Users\Administrator\Downloads\Tisane" $TISANE_ROOT = "C:\Tisane" #Add-Type -AssemblyName System.IO.Compression.FileSystem #Add-Type -Assembly "System.IO.Compression.Filesystem" # WE HAVE TO USE Ionic Zip because the standard compression libraries crash with very large archives [System.Reflection.Assembly]::LoadFrom("$DOWNLOAD_FOLDER\Ionic.Zip.dll") $zipFile = New-Object Ionic.Zip.ZipFile("$DOWNLOAD_FOLDER\tisane_db.zip") #[System.IO.Compression.ZipFile]::ExtractToDirectory("$DOWNLOAD_FOLDER\tisane_db.zip", $TISANE_ROOT, $true) Write-Host "Extracting Tisane data to $TISANE_ROOT..." -ForegroundColor Green #Expand-Archive -LiteralPath "$DOWNLOAD_FOLDER\tisane_db.zip" -DestinationPath $TISANE_ROOT -Force $zipFile.ExtractAll($TISANE_ROOT, 1) # dir $TISANE_ROOT -Recurse | Where-Object { $_.FullName -imatch '^C:\\tisane\\([^\\]+)\\LOG[.]old.+' } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $services = Get-Service "Tisane Runtime *" $instances = $services.length For ($i=1; $i -le $instances; $i++) { $formattedI = $i | % tostring 00 Write-Host "Updating instance under $TISANE_ROOT\instance$formattedI" -ForegroundColor Green Expand-Archive -LiteralPath "$DOWNLOAD_FOLDER\tisane_ws.zip" -DestinationPath "$TISANE_ROOT\instance$formattedI" -Force Start-Process -FilePath "$TISANE_ROOT\instance$formattedI\Tisane.Runtime.Service.exe" -ArgumentList "-r" -Wait } Start-Service "Tisane Runtime *" } #EndRegion '.\Public\Update-TisaneFromLocalZips.ps1' 37 |