Skip to content

Commit

Permalink
Add import script to zed, run as service
Browse files Browse the repository at this point in the history
Signed-off-by: Jorgen Lundman <lundman@lundman.net>
  • Loading branch information
lundman committed Dec 18, 2024
1 parent 9947ebd commit e056a47
Show file tree
Hide file tree
Showing 21 changed files with 670 additions and 365 deletions.
35 changes: 35 additions & 0 deletions cmd/zed/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,38 @@ install(FILES $<TARGET_PDB_FILE:zed>
DESTINATION "${CMAKE_INSTALL_BINDIR}"
OPTIONAL
)

# Custom command to generate zed.cat
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/cmd/zed/os/windows/zed.cat"
DEPENDS
"${CMAKE_SOURCE_DIR}/cmd/zed/os/windows/zed.inf"
"${CMAKE_CURRENT_BINARY_DIR}/zed.exe"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${CMAKE_CURRENT_BINARY_DIR}/zed.exe" "${CMAKE_CURRENT_BINARY_DIR}/cmd/zed/os/windows/zed.exe"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${CMAKE_SOURCE_DIR}/cmd/zed/os/windows/zed.inf" "${CMAKE_CURRENT_BINARY_DIR}/cmd/zed/os/windows/zed.inf.temp"
COMMAND "${STAMPINF_PROGRAM}" -d "*" -a "amd64" -v "*" -f "${CMAKE_CURRENT_BINARY_DIR}\\cmd\\zed\\os\\windows\\zed.inf.temp"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${CMAKE_CURRENT_BINARY_DIR}/cmd/zed/os/windows/zed.inf.temp" "${CMAKE_CURRENT_BINARY_DIR}/cmd/zed/os/windows/zed.inf"
COMMAND "${CMAKE_COMMAND}" -E remove "${CMAKE_CURRENT_BINARY_DIR}/cmd/zed/os/windows/zed.inf.temp"
COMMAND "${INF2CAT_PROGRAM}" /verbose "/driver:${CMAKE_CURRENT_BINARY_DIR}/cmd/zed/os/windows" /os:10_19H1_X86,10_19H1_X64,ServerRS5_X64 /uselocaltime
COMMAND "${SIGNTOOL_PROGRAM}" sign /v /as /fd sha256 /td sha256 /sha1 "${OPENZFS_SIGNTOOL_SHA1}" /tr "${OPENZFS_SIGNTOOL_TSA}" "${CMAKE_CURRENT_BINARY_DIR}/cmd/zed/os/windows/zed.cat"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/cmd/zed/os/windows"
COMMENT "Generating and signing zed.cat file"
VERBATIM
)

# Custom target depending on the generated file
add_custom_target(
zed_cat
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/cmd/zed/os/windows/zed.cat"
COMMENT "Ensure zed.cat is up to date"
)

add_dependencies(zed_cat zed)

install(TARGETS OpenZFS RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}/driver")
install(FILES
"${CMAKE_SOURCE_DIR}/cmd/zed/os/windows/zed.inf"
"${CMAKE_SOURCE_DIR}/cmd/zed/os/windows/zed.cat"
"${CMAKE_CURRENT_BINARY_DIR}/driver/zed.exe"
DESTINATION "${CMAKE_INSTALL_BINDIR}/driver"
)
36 changes: 36 additions & 0 deletions cmd/zed/os/windows/zed.d/system_boot.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/powershell
# shellcheck disable=SC2154
#
# Log all environment variables to ZED_DEBUG_LOG.
#
# This can be a useful aid when developing/debugging ZEDLETs since it shows the
# environment variables defined for each zevent.

if (Test-Path "$env:ZED_ZEDLET_DIR\zed.rc") {
. "$env:ZED_ZEDLET_DIR\zed.rc"
}
if (Test-Path "$env:ZED_ZEDLET_DIR\zed-functions.ps1") {
. "$env:ZED_ZEDLET_DIR\zed-functions.ps1"
}

#
# system_boot.ps1
#

# Define the path to the zpool.cache file
$zpoolCachePath = "C:\Windows\System32\Drivers\zpool.cache"

# Check if the zpool.cache file exists
if (Test-Path $zpoolCachePath) {
Write-Host "zpool.cache found. Importing ZFS pools..."
zed_log_msg LOG_NOTICE "zpool.cache found. Importing ZFS pools"

# Import ZFS pools using the zpool command and the cache file
& "$env:ZPOOL" import -c "$zpoolCachePath" -a

# Optionally, log the result or handle any output
zed_log_msg "ZFS Pools Imported."
zed_notify "ZFS Pools Imported" "path"
} else {
zed_log_msg "zpool.cache not found. No pools imported."
}
243 changes: 188 additions & 55 deletions cmd/zed/os/windows/zed.d/zed-functions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,71 +3,109 @@
# 2024 Jorgen Lundman <lundman@lundman.net>
#

# This one doesn't need any extra PS modules, but is
# ugly.
function Show-PlainToastNotification {
# zed_log_msg (msg, ...)
#
# Write all argument strings to the system log.
#
# Globals
# ZED_SYSLOG_PRIORITY
# ZED_SYSLOG_TAG
#
# Return
# nothing
#
function zed_log_msg
{
param (
[string]$Title = "ZED Notification",
[string]$Message = "Default message"
[string]$level,
[string]$message
)

# Load the required assemblies
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# Create a form to act as a notification
$form = New-Object System.Windows.Forms.Form
$form.StartPosition = 'Manual'
$form.Location = New-Object System.Drawing.Point(0, 0)
$form.Size = New-Object System.Drawing.Size(300, 100)
$form.FormBorderStyle = 'None'
$form.BackColor = [System.Drawing.Color]::White
$form.TopMost = $true
$form.ShowInTaskbar = $false
$form.Opacity = 0.9

# Create a label for the title
$titleLabel = New-Object System.Windows.Forms.Label
$titleLabel.Text = $Title
$titleLabel.Font = New-Object System.Drawing.Font("Arial", 14, [System.Drawing.FontStyle]::Bold)
$titleLabel.AutoSize = $true
$titleLabel.Location = New-Object System.Drawing.Point(10, 10)

# Create a label for the message
$messageLabel = New-Object System.Windows.Forms.Label
$messageLabel.Text = $Message
$messageLabel.AutoSize = $true
$messageLabel.Location = New-Object System.Drawing.Point(10, 40)

# Add the labels to the form
$form.Controls.Add($titleLabel)
$form.Controls.Add($messageLabel)

# Show the form
$form.Show()

# Timer to close the notification after 5 seconds
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 5000 # milliseconds
$timer.Add_Tick({
$form.Close()
$timer.Stop()
})
$timer.Start()

# Run the form's message loop
[System.Windows.Forms.Application]::Run($form)
$eventSource = "OpenZFS_zed"
$eventLog = "Application"

# Ensure the event source exists
try {
if (-not [System.Diagnostics.EventLog]::SourceExists($eventSource)) {
[System.Diagnostics.EventLog]::CreateEventSource($eventSource, $eventLog)
}
} catch {
Write-Host "WARNING: Insufficient permissions to check or create event log source. Falling back to console output."
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Write-Host "$timestamp [$level] $message"
return
}

# Write the event log
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$fullMessage = "$timestamp [$level] $message"
try {
Write-EventLog -LogName $eventLog -Source $eventSource -EventId 0 -EntryType Information -Message $fullMessage
} catch {
Write-Host "ERROR: Unable to write to event log. Falling back to console output."
Write-Host "$timestamp [$level] $message"
}
}

# zed_log_err (msg, ...)
#
# Write an error message to the system log. This message will contain the
# script name, EID, and all argument strings.
#
# Globals
# ZED_SYSLOG_PRIORITY
# ZED_SYSLOG_TAG
# ZEVENT_EID
#
# Return
# nothing
#
function zed_log_err
{
param (
[string]$message
)

$eventSource = "OpenZFS_zed"
$eventLog = "Application"

# Ensure the event source exists
try {
if (-not [System.Diagnostics.EventLog]::SourceExists($eventSource)) {
[System.Diagnostics.EventLog]::CreateEventSource($eventSource, $eventLog)
}
} catch {
Write-Host "WARNING: Insufficient permissions to check or create event log source. Falling back to console output."
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Write-Host "$timestamp [ERROR] $message"
return
}

# Write the event log
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$fullMessage = "$timestamp [ERROR] $message"
try {
Write-EventLog -LogName $eventLog -Source $eventSource -EventId 0 -EntryType Error -Message $fullMessage
} catch {
Write-Host "ERROR: Unable to write to event log. Falling back to console output."
Write-Host "$timestamp [ERROR] $message"
}
}

# For real notifications to work, run in powershell (Admin)
# "Install-Module -Name BurntToast -Force -AllowClobber"
# Failing that, fall back to a regular MessageBox
function Show-ToastNotification {
function zed_notify_burnttoast()
{
param (
[string]$Title = "Notification",
[string]$Message = "This is a test notification."
)

if (-not $env:ZED_BURNTTOAST_NOTIFICATIONS) {
return 2
}

# Check if the BurntToast module is available
if (Get-Module -ListAvailable -Name BurntToast) {
try {
Expand All @@ -80,18 +118,23 @@ function Show-ToastNotification {
catch {
# If there's an error, fall back to a basic notification
Write-Host "BurntToast failed to create a notification: $_"
Show-MessageBox "$Message" "$Title"
}
}
else {
# Fallback if BurntToast is not installed
Write-Host "BurntToast module is not installed. Falling back to basic notification."
Show-MessageBox "$Message" "$Title"
}
}

function zed_notify_toast
{
# If the toast notification was successfully sent, return success
return 0
}

# Function to show a message box
function Show-MessageBox {
function zed_notify_messagebox
{
param (
[string]$Message,
[string]$Title
Expand All @@ -105,3 +148,93 @@ function Show-MessageBox {
}


# zed_notify (title, message)
#
# Send a notification via all available methods.
#
# Arguments
# title: notification title
# message: notification message (OPTIONAL)
#
# Return
# 0: notification succeeded via at least one method
# 1: notification failed
# 2: no notification methods configured
#
function zed_notify
{
param (
[string]$title,
[string]$message
)
$num_success=0
$num_failure=0

# Call zed_notify_toast (Windows-specific toast notification)
$rv = zed_notify_toast "$subject" "$pathname"
if ($rv -eq 0) {
$num_success += 1
} elseif ($rv -eq 1) {
$num_failure += 1
}

$rv = zed_notify_burnttoast "$subject" "$pathname"
if ($rv -eq 0) {
$num_success += 1
} elseif ($rv -eq 1) {
$num_failure += 1
}

# Additional notification methods could go here (email, pushbullet, etc.)

# If we had any success, return success code
if ($num_success -gt 0) {
return 0
} elseif ($num_failure -gt 0) {
return 1
} else {
return 2
}
}


# zed_guid_to_pool (guid)
#
# Convert a pool GUID into its pool name (like "tank")
# Arguments
# guid: pool GUID (decimal or hex)
#
# Return
# Pool name
function zed_guid_to_pool
{
param (
[Parameter(Mandatory=$true)]
[string]$guid
)

if (-not $guid) {
return # Return nothing if no GUID is provided
}

# Ensure $env:ZPOOL is set
if (-not $env:ZPOOL) {
Write-Error "Environment variable ZPOOL is not set"
return
}

try {
# Run the ZPOOL command and filter by the GUID
$poolName = & $env:ZPOOL get -H -o value,name guid 2>&1 |
Where-Object { $_ -match $guid } |
ForEach-Object { ($_ -split '\s+')[1] }

if ($poolName) {
return $poolName
} else {
Write-Error "No pool found for GUID $guid"
}
} catch {
Write-Error "Error querying pool name: $_"
}
}
13 changes: 13 additions & 0 deletions cmd/zed/os/windows/zed.d/zed.rc
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,16 @@ $env:ZED_SYSLOG_SUBCLASS_EXCLUDE="history_event"
# Gotify application associated with ZED_GOTIFY_APPTOKEN.
# Value is an integer 0 and up.
#$env:ZED_GOTIFY_PRIORITY=""

##
# Use Toast notification (optional)
# If defined, use system Toast notifications
# Value is an integer 0 and up.
# $env:ZED_TOAST_NOTIFICATIONS=1

##
# Use BurntToast notification(optional)
# If defined, use Burnt Toast notifications
# Installed with "Install-Module -Name BurntToast -Force -AllowClobber"
# Value is an integer 0 and up.
# $env:ZED_BURNTTOAST_NOTIFICATIONS=1
Loading

0 comments on commit e056a47

Please sign in to comment.