towerops/lib/mix/tasks/copy_mibs.ex

128 lines
3.6 KiB
Elixir

defmodule Mix.Tasks.CopyMibs do
@shortdoc "Copies MIB files from source directory to app MIB directory"
@moduledoc """
Copies MIB files from a source directory to the application's MIB directory.
## Usage
# Copy all MIB files
mix copy_mibs --source-path ~/mibs
# Copy specific vendor MIB directories
mix copy_mibs --source-path ~/mibs --vendors mikrotik,cisco,ubiquiti
"""
use Mix.Task
require Logger
def run(args) do
{opts, _} =
OptionParser.parse!(args,
strict: [
source_path: :string,
vendors: :string,
target_dir: :string
]
)
source_path = opts[:source_path] || raise "Missing --source-path argument"
target_dir = opts[:target_dir] || get_default_target_dir()
vendors = parse_vendors(opts[:vendors])
source_mibs = source_path
if !File.exists?(source_mibs) do
raise "LibreNMS MIB directory not found: #{source_mibs}"
end
# Ensure target directory exists
File.mkdir_p!(target_dir)
case vendors do
:all ->
copy_all_mibs(source_mibs, target_dir)
vendor_list ->
copy_vendor_mibs(source_mibs, target_dir, vendor_list)
end
end
defp get_default_target_dir do
# In development, use priv/mibs; in production use /app/mibs
if Application.get_env(:towerops, :env) == :dev do
Path.join([File.cwd!(), "priv", "mibs"])
else
Application.get_env(:towerops, :mib_dir, "/app/mibs")
end
end
defp parse_vendors(nil), do: :all
defp parse_vendors(""), do: :all
defp parse_vendors(vendors_string) do
vendors_string
|> String.split(",")
|> Enum.map(&String.trim/1)
|> Enum.reject(&(&1 == ""))
end
defp copy_all_mibs(source_dir, target_dir) do
Logger.info("Copying all MIB files from #{source_dir} to #{target_dir}...")
# Use rsync for efficient copying
case System.cmd("rsync", ["-av", "--exclude=.git", "#{source_dir}/", target_dir]) do
{output, 0} ->
Logger.info("Successfully copied MIB files")
Logger.debug(output)
:ok
{error, exit_code} ->
Logger.error("Failed to copy MIB files (exit code #{exit_code}): #{error}")
{:error, :copy_failed}
end
rescue
_e in ErlangError ->
# rsync not found, fall back to File.cp_r
Logger.warning("rsync not found, using File.cp_r (slower)")
copy_mibs_recursive(source_dir, target_dir)
end
defp copy_vendor_mibs(source_dir, target_dir, vendors) do
Logger.info("Copying MIB files for vendors: #{Enum.join(vendors, ", ")}")
results =
Enum.map(vendors, fn vendor ->
source_path = Path.join(source_dir, vendor)
target_path = Path.join(target_dir, vendor)
if File.exists?(source_path) do
Logger.info("Copying #{vendor} MIBs...")
File.mkdir_p!(target_path)
_ = File.cp_r!(source_path, target_path)
{:ok, vendor}
else
Logger.warning("Vendor MIB directory not found: #{vendor}")
{:error, vendor}
end
end)
successes = Enum.count(results, &match?({:ok, _}, &1))
failures = Enum.count(results, &match?({:error, _}, &1))
Logger.info("Copied #{successes} vendor MIB directories (#{failures} not found)")
end
defp copy_mibs_recursive(source_dir, target_dir) do
case File.cp_r(source_dir, target_dir) do
{:ok, _files} ->
Logger.info("Successfully copied MIB files")
:ok
{:error, reason, file} ->
Logger.error("Failed to copy #{file}: #{inspect(reason)}")
{:error, :copy_failed}
end
end
end