Add firmware update indicator to device detail page
- Load available firmware in DeviceLive.Show - Add firmware_update_available? and format_date helpers - Display blue indicator banner when newer firmware available - Show current vs latest version with release date - Add download link and release notes link - Support MikroTik initially, extensible to other vendors Phase 6 (final) of firmware tracking complete. All phases implemented: ✅ Database schema (firmware_releases, device_firmware_history) ✅ Version comparison logic (VersionComparator) ✅ RSS fetching worker (daily Oban cron) ✅ Firmware context with logging and PubSub ✅ Version change detection in Discovery ✅ LiveView UI indicators
This commit is contained in:
parent
61a06fc11c
commit
fcf3ce154f
2 changed files with 92 additions and 0 deletions
|
|
@ -4,6 +4,8 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
|
||||
alias Towerops.Agents
|
||||
alias Towerops.Devices
|
||||
alias Towerops.Devices.Firmware
|
||||
alias Towerops.Devices.VersionComparator
|
||||
alias Towerops.Monitoring
|
||||
alias Towerops.Repo
|
||||
alias Towerops.Snmp
|
||||
|
|
@ -233,6 +235,9 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
# Group interfaces by type for the ports tab
|
||||
interfaces_by_type = group_interfaces_by_type(snmp_data.interfaces)
|
||||
|
||||
# Check for available firmware updates
|
||||
available_firmware = get_available_firmware(snmp_data.device)
|
||||
|
||||
socket
|
||||
|> assign(:page_title, device.name)
|
||||
|> assign(:timezone, socket.assigns.current_scope.timezone)
|
||||
|
|
@ -267,6 +272,42 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
|> assign(:wireless_sensors, wireless_sensors)
|
||||
|> assign(:grouped_transceivers, grouped_transceivers)
|
||||
|> assign(:agent_info, agent_info)
|
||||
|> assign(:available_firmware, available_firmware)
|
||||
end
|
||||
|
||||
defp get_available_firmware(nil), do: nil
|
||||
|
||||
defp get_available_firmware(snmp_device) do
|
||||
vendor = determine_vendor(snmp_device.manufacturer)
|
||||
product_line = determine_product_line(snmp_device.manufacturer)
|
||||
|
||||
if vendor do
|
||||
Firmware.get_latest_firmware_release(vendor, product_line)
|
||||
end
|
||||
end
|
||||
|
||||
defp determine_vendor("MikroTik"), do: "mikrotik"
|
||||
defp determine_vendor("Cisco"), do: "cisco"
|
||||
defp determine_vendor("Ubiquiti"), do: "ubiquiti"
|
||||
defp determine_vendor(_), do: nil
|
||||
|
||||
defp determine_product_line("MikroTik"), do: "routeros"
|
||||
defp determine_product_line(_), do: nil
|
||||
|
||||
defp firmware_update_available?(nil, _), do: false
|
||||
defp firmware_update_available?(_, nil), do: false
|
||||
|
||||
defp firmware_update_available?(snmp_device, available_firmware) do
|
||||
current = snmp_device.firmware_version
|
||||
available = available_firmware.version
|
||||
|
||||
current && available && VersionComparator.newer?(current, available)
|
||||
end
|
||||
|
||||
defp format_date(nil), do: ""
|
||||
|
||||
defp format_date(date) do
|
||||
Calendar.strftime(date, "%B %-d, %Y")
|
||||
end
|
||||
|
||||
defp load_agent_info(nil, :none) do
|
||||
|
|
|
|||
|
|
@ -205,6 +205,57 @@
|
|||
<div class="mt-6">
|
||||
<%= case @active_tab do %>
|
||||
<% "overview" -> %>
|
||||
<!-- Firmware Update Indicator -->
|
||||
<%= if firmware_update_available?(@snmp_device, @available_firmware) do %>
|
||||
<div class="mb-6 rounded-md bg-blue-50 dark:bg-blue-900/20 p-4 border border-blue-200 dark:border-blue-800">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<.icon name="hero-arrow-up-circle" class="h-5 w-5 text-blue-400" />
|
||||
</div>
|
||||
<div class="ml-3 flex-1">
|
||||
<h3 class="text-sm font-medium text-blue-800 dark:text-blue-200">
|
||||
Firmware Update Available
|
||||
</h3>
|
||||
<div class="mt-2 text-sm text-blue-700 dark:text-blue-300">
|
||||
<p>
|
||||
Current version:
|
||||
<span class="font-mono font-semibold">{@snmp_device.firmware_version}</span>
|
||||
<br /> Latest version:
|
||||
<span class="font-mono font-semibold">{@available_firmware.version}</span>
|
||||
<%= if @available_firmware.release_date do %>
|
||||
<span class="text-xs">
|
||||
(released {format_date(@available_firmware.release_date)})
|
||||
</span>
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<a
|
||||
href={@available_firmware.download_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-flex items-center rounded-md bg-blue-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"
|
||||
>
|
||||
Download Firmware
|
||||
<.icon name="hero-arrow-top-right-on-square" class="ml-1.5 h-4 w-4" />
|
||||
</a>
|
||||
<%= if @available_firmware.changelog_url do %>
|
||||
<a
|
||||
href={@available_firmware.changelog_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="ml-3 inline-flex items-center text-sm font-medium text-blue-600 dark:text-blue-400 hover:text-blue-500"
|
||||
>
|
||||
View Release Notes
|
||||
<.icon name="hero-arrow-top-right-on-square" class="ml-1 h-4 w-4" />
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 items-start">
|
||||
<!-- Left Column: Device Information & Traffic -->
|
||||
<div class="space-y-6">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue