459 lines
13 KiB
Elixir
459 lines
13 KiB
Elixir
defmodule Towerops.Snmp.BatchInsertTest do
|
|
use Towerops.DataCase, async: false
|
|
|
|
import Towerops.AccountsFixtures
|
|
|
|
alias Towerops.Repo
|
|
alias Towerops.Snmp
|
|
alias Towerops.Snmp.Device
|
|
alias Towerops.Snmp.Interface
|
|
alias Towerops.Snmp.InterfaceStat
|
|
alias Towerops.Snmp.Processor
|
|
alias Towerops.Snmp.ProcessorReading
|
|
alias Towerops.Snmp.Sensor
|
|
alias Towerops.Snmp.SensorReading
|
|
alias Towerops.Snmp.Storage
|
|
alias Towerops.Snmp.StorageReading
|
|
|
|
setup do
|
|
user = user_fixture()
|
|
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)
|
|
|
|
{:ok, site} =
|
|
Towerops.Sites.create_site(%{
|
|
name: "Test Site",
|
|
organization_id: organization.id
|
|
})
|
|
|
|
{:ok, device} =
|
|
Towerops.Devices.create_device(%{
|
|
name: "Test Router",
|
|
ip_address: "192.168.1.1",
|
|
snmp_enabled: true,
|
|
snmp_version: "2c",
|
|
snmp_community: "public",
|
|
snmp_port: 161,
|
|
site_id: site.id,
|
|
organization_id: organization.id
|
|
})
|
|
|
|
snmp_device =
|
|
%Device{}
|
|
|> Device.changeset(%{
|
|
device_id: device.id,
|
|
sys_name: "test-router",
|
|
sys_descr: "Test Device"
|
|
})
|
|
|> Repo.insert!()
|
|
|
|
sensor =
|
|
%Sensor{}
|
|
|> Sensor.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
sensor_type: "temperature",
|
|
sensor_index: "temp_1",
|
|
sensor_oid: "1.3.6.1.4.1.9.9.91.1.1.1.1.4.1"
|
|
})
|
|
|> Repo.insert!()
|
|
|
|
sensor2 =
|
|
%Sensor{}
|
|
|> Sensor.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
sensor_type: "voltage",
|
|
sensor_index: "volt_1",
|
|
sensor_oid: "1.3.6.1.4.1.9.9.91.1.1.1.1.4.2"
|
|
})
|
|
|> Repo.insert!()
|
|
|
|
interface =
|
|
%Interface{}
|
|
|> Interface.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
if_index: 1,
|
|
if_name: "eth0"
|
|
})
|
|
|> Repo.insert!()
|
|
|
|
interface2 =
|
|
%Interface{}
|
|
|> Interface.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
if_index: 2,
|
|
if_name: "eth1"
|
|
})
|
|
|> Repo.insert!()
|
|
|
|
processor =
|
|
%Processor{}
|
|
|> Processor.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
processor_index: "1",
|
|
processor_type: "hr_processor",
|
|
description: "CPU 1"
|
|
})
|
|
|> Repo.insert!()
|
|
|
|
processor2 =
|
|
%Processor{}
|
|
|> Processor.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
processor_index: "2",
|
|
processor_type: "hr_processor",
|
|
description: "CPU 2"
|
|
})
|
|
|> Repo.insert!()
|
|
|
|
storage =
|
|
%Storage{}
|
|
|> Storage.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
storage_index: 1,
|
|
storage_type: "fixed_disk",
|
|
description: "/dev/sda1"
|
|
})
|
|
|> Repo.insert!()
|
|
|
|
storage2 =
|
|
%Storage{}
|
|
|> Storage.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
storage_index: 2,
|
|
storage_type: "ram",
|
|
description: "Physical Memory"
|
|
})
|
|
|> Repo.insert!()
|
|
|
|
%{
|
|
snmp_device: snmp_device,
|
|
sensor: sensor,
|
|
sensor2: sensor2,
|
|
interface: interface,
|
|
interface2: interface2,
|
|
processor: processor,
|
|
processor2: processor2,
|
|
storage: storage,
|
|
storage2: storage2
|
|
}
|
|
end
|
|
|
|
describe "create_sensor_readings_batch/1" do
|
|
test "inserts multiple sensor readings", %{sensor: sensor, sensor2: sensor2} do
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
entries = [
|
|
%{sensor_id: sensor.id, value: 25.5, status: "ok", checked_at: now},
|
|
%{sensor_id: sensor2.id, value: 3.3, status: "warning", checked_at: now}
|
|
]
|
|
|
|
assert {2, nil} = Snmp.create_sensor_readings_batch(entries)
|
|
|
|
readings = Repo.all(SensorReading)
|
|
assert length(readings) == 2
|
|
|
|
reading1 = Enum.find(readings, &(&1.sensor_id == sensor.id))
|
|
assert reading1.value == 25.5
|
|
assert reading1.status == "ok"
|
|
assert reading1.checked_at == now
|
|
assert reading1.id
|
|
assert reading1.inserted_at
|
|
|
|
reading2 = Enum.find(readings, &(&1.sensor_id == sensor2.id))
|
|
assert reading2.value == 3.3
|
|
assert reading2.status == "warning"
|
|
end
|
|
|
|
test "returns {0, nil} for empty list" do
|
|
assert {0, nil} = Snmp.create_sensor_readings_batch([])
|
|
assert Repo.all(SensorReading) == []
|
|
end
|
|
|
|
test "generates unique UUIDs for each entry", %{sensor: sensor} do
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
entries = [
|
|
%{sensor_id: sensor.id, value: 10.0, status: "ok", checked_at: now},
|
|
%{sensor_id: sensor.id, value: 11.0, status: "ok", checked_at: now}
|
|
]
|
|
|
|
{2, nil} = Snmp.create_sensor_readings_batch(entries)
|
|
|
|
readings = Repo.all(SensorReading)
|
|
ids = Enum.map(readings, & &1.id)
|
|
assert length(Enum.uniq(ids)) == 2
|
|
end
|
|
|
|
test "handles optional state_descr field", %{sensor: sensor} do
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
entries = [
|
|
%{
|
|
sensor_id: sensor.id,
|
|
value: 25.5,
|
|
status: "ok",
|
|
state_descr: "Normal operating temperature",
|
|
checked_at: now
|
|
}
|
|
]
|
|
|
|
assert {1, nil} = Snmp.create_sensor_readings_batch(entries)
|
|
|
|
[reading] = Repo.all(SensorReading)
|
|
assert reading.state_descr == "Normal operating temperature"
|
|
end
|
|
|
|
test "handles entries with nil value", %{sensor: sensor} do
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
entries = [
|
|
%{sensor_id: sensor.id, value: nil, status: "error", checked_at: now}
|
|
]
|
|
|
|
assert {1, nil} = Snmp.create_sensor_readings_batch(entries)
|
|
|
|
[reading] = Repo.all(SensorReading)
|
|
assert reading.value == nil
|
|
assert reading.status == "error"
|
|
end
|
|
end
|
|
|
|
describe "create_interface_stats_batch/1" do
|
|
test "inserts multiple interface stats", %{interface: interface, interface2: interface2} do
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
entries = [
|
|
%{
|
|
interface_id: interface.id,
|
|
if_in_octets: 1000,
|
|
if_out_octets: 2000,
|
|
if_in_errors: 0,
|
|
if_out_errors: 0,
|
|
if_in_discards: 0,
|
|
if_out_discards: 0,
|
|
checked_at: now
|
|
},
|
|
%{
|
|
interface_id: interface2.id,
|
|
if_in_octets: 5000,
|
|
if_out_octets: 6000,
|
|
if_in_errors: 1,
|
|
if_out_errors: 2,
|
|
if_in_discards: 3,
|
|
if_out_discards: 4,
|
|
checked_at: now
|
|
}
|
|
]
|
|
|
|
assert {2, nil} = Snmp.create_interface_stats_batch(entries)
|
|
|
|
stats = Repo.all(InterfaceStat)
|
|
assert length(stats) == 2
|
|
|
|
stat1 = Enum.find(stats, &(&1.interface_id == interface.id))
|
|
assert stat1.if_in_octets == 1000
|
|
assert stat1.if_out_octets == 2000
|
|
assert stat1.if_in_errors == 0
|
|
assert stat1.if_out_errors == 0
|
|
assert stat1.if_in_discards == 0
|
|
assert stat1.if_out_discards == 0
|
|
assert stat1.checked_at == now
|
|
assert stat1.id
|
|
assert stat1.inserted_at
|
|
|
|
stat2 = Enum.find(stats, &(&1.interface_id == interface2.id))
|
|
assert stat2.if_in_octets == 5000
|
|
assert stat2.if_out_octets == 6000
|
|
assert stat2.if_in_errors == 1
|
|
assert stat2.if_out_errors == 2
|
|
end
|
|
|
|
test "returns {0, nil} for empty list" do
|
|
assert {0, nil} = Snmp.create_interface_stats_batch([])
|
|
assert Repo.all(InterfaceStat) == []
|
|
end
|
|
|
|
test "generates unique UUIDs for each entry", %{interface: interface} do
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
entries = [
|
|
%{interface_id: interface.id, if_in_octets: 100, if_out_octets: 200, checked_at: now},
|
|
%{interface_id: interface.id, if_in_octets: 300, if_out_octets: 400, checked_at: now}
|
|
]
|
|
|
|
{2, nil} = Snmp.create_interface_stats_batch(entries)
|
|
|
|
stats = Repo.all(InterfaceStat)
|
|
ids = Enum.map(stats, & &1.id)
|
|
assert length(Enum.uniq(ids)) == 2
|
|
end
|
|
|
|
test "handles entries with nil counter values", %{interface: interface} do
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
entries = [
|
|
%{interface_id: interface.id, if_in_octets: nil, if_out_octets: nil, checked_at: now}
|
|
]
|
|
|
|
assert {1, nil} = Snmp.create_interface_stats_batch(entries)
|
|
|
|
[stat] = Repo.all(InterfaceStat)
|
|
assert stat.if_in_octets == nil
|
|
assert stat.if_out_octets == nil
|
|
end
|
|
end
|
|
|
|
describe "create_processor_readings_batch/1" do
|
|
test "inserts multiple processor readings", %{processor: processor, processor2: processor2} do
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
entries = [
|
|
%{processor_id: processor.id, load_percent: 45.0, status: "ok", checked_at: now},
|
|
%{processor_id: processor2.id, load_percent: 92.0, status: "critical", checked_at: now}
|
|
]
|
|
|
|
assert {2, nil} = Snmp.create_processor_readings_batch(entries)
|
|
|
|
readings = Repo.all(ProcessorReading)
|
|
assert length(readings) == 2
|
|
|
|
reading1 = Enum.find(readings, &(&1.processor_id == processor.id))
|
|
assert reading1.load_percent == 45.0
|
|
assert reading1.status == "ok"
|
|
assert reading1.checked_at == now
|
|
assert reading1.id
|
|
assert reading1.inserted_at
|
|
|
|
reading2 = Enum.find(readings, &(&1.processor_id == processor2.id))
|
|
assert reading2.load_percent == 92.0
|
|
assert reading2.status == "critical"
|
|
end
|
|
|
|
test "returns {0, nil} for empty list" do
|
|
assert {0, nil} = Snmp.create_processor_readings_batch([])
|
|
assert Repo.all(ProcessorReading) == []
|
|
end
|
|
|
|
test "generates unique UUIDs for each entry", %{processor: processor} do
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
entries = [
|
|
%{processor_id: processor.id, load_percent: 10.0, status: "ok", checked_at: now},
|
|
%{processor_id: processor.id, load_percent: 20.0, status: "ok", checked_at: now}
|
|
]
|
|
|
|
{2, nil} = Snmp.create_processor_readings_batch(entries)
|
|
|
|
readings = Repo.all(ProcessorReading)
|
|
ids = Enum.map(readings, & &1.id)
|
|
assert length(Enum.uniq(ids)) == 2
|
|
end
|
|
|
|
test "handles entries with nil load_percent", %{processor: processor} do
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
entries = [
|
|
%{processor_id: processor.id, load_percent: nil, status: "error", checked_at: now}
|
|
]
|
|
|
|
assert {1, nil} = Snmp.create_processor_readings_batch(entries)
|
|
|
|
[reading] = Repo.all(ProcessorReading)
|
|
assert reading.load_percent == nil
|
|
assert reading.status == "error"
|
|
end
|
|
end
|
|
|
|
describe "create_storage_readings_batch/1" do
|
|
test "inserts multiple storage readings", %{storage: storage, storage2: storage2} do
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
entries = [
|
|
%{
|
|
storage_id: storage.id,
|
|
used_bytes: 5_000_000,
|
|
total_bytes: 10_000_000,
|
|
usage_percent: 50.0,
|
|
checked_at: now
|
|
},
|
|
%{
|
|
storage_id: storage2.id,
|
|
used_bytes: 2_000_000,
|
|
total_bytes: 8_000_000,
|
|
usage_percent: 25.0,
|
|
checked_at: now
|
|
}
|
|
]
|
|
|
|
assert {2, nil} = Snmp.create_storage_readings_batch(entries)
|
|
|
|
readings = Repo.all(StorageReading)
|
|
assert length(readings) == 2
|
|
|
|
reading1 = Enum.find(readings, &(&1.storage_id == storage.id))
|
|
assert reading1.used_bytes == 5_000_000
|
|
assert reading1.total_bytes == 10_000_000
|
|
assert reading1.usage_percent == 50.0
|
|
assert reading1.checked_at == now
|
|
assert reading1.id
|
|
assert reading1.inserted_at
|
|
|
|
reading2 = Enum.find(readings, &(&1.storage_id == storage2.id))
|
|
assert reading2.used_bytes == 2_000_000
|
|
assert reading2.total_bytes == 8_000_000
|
|
assert reading2.usage_percent == 25.0
|
|
end
|
|
|
|
test "returns {0, nil} for empty list" do
|
|
assert {0, nil} = Snmp.create_storage_readings_batch([])
|
|
assert Repo.all(StorageReading) == []
|
|
end
|
|
|
|
test "generates unique UUIDs for each entry", %{storage: storage} do
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
entries = [
|
|
%{
|
|
storage_id: storage.id,
|
|
used_bytes: 1000,
|
|
total_bytes: 2000,
|
|
usage_percent: 50.0,
|
|
checked_at: now
|
|
},
|
|
%{
|
|
storage_id: storage.id,
|
|
used_bytes: 1500,
|
|
total_bytes: 2000,
|
|
usage_percent: 75.0,
|
|
checked_at: now
|
|
}
|
|
]
|
|
|
|
{2, nil} = Snmp.create_storage_readings_batch(entries)
|
|
|
|
readings = Repo.all(StorageReading)
|
|
ids = Enum.map(readings, & &1.id)
|
|
assert length(Enum.uniq(ids)) == 2
|
|
end
|
|
|
|
test "handles entries with nil optional fields", %{storage: storage} do
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
entries = [
|
|
%{
|
|
storage_id: storage.id,
|
|
used_bytes: nil,
|
|
total_bytes: nil,
|
|
usage_percent: nil,
|
|
checked_at: now
|
|
}
|
|
]
|
|
|
|
assert {1, nil} = Snmp.create_storage_readings_batch(entries)
|
|
|
|
[reading] = Repo.all(StorageReading)
|
|
assert reading.used_bytes == nil
|
|
assert reading.total_bytes == nil
|
|
assert reading.usage_percent == nil
|
|
end
|
|
end
|
|
end
|