187 lines
4.6 KiB
Elixir
187 lines
4.6 KiB
Elixir
defmodule Towerops.Sites do
|
|
@moduledoc """
|
|
The Sites context.
|
|
"""
|
|
|
|
import Ecto.Query
|
|
|
|
alias Towerops.Agents.AgentAssignment
|
|
alias Towerops.Devices.Device
|
|
alias Towerops.Repo
|
|
alias Towerops.Sites.Site
|
|
|
|
@doc """
|
|
Returns the list of sites for an organization.
|
|
"""
|
|
def list_organization_sites(organization_id) do
|
|
Repo.all(
|
|
from(s in Site, where: s.organization_id == ^organization_id, order_by: [asc: s.name], preload: [:parent_site])
|
|
)
|
|
end
|
|
|
|
@doc """
|
|
Returns the count of sites for an organization.
|
|
"""
|
|
def count_organization_sites(organization_id) do
|
|
Repo.aggregate(
|
|
from(s in Site, where: s.organization_id == ^organization_id),
|
|
:count
|
|
)
|
|
end
|
|
|
|
@doc """
|
|
Returns the list of root sites (sites without a parent) for an organization.
|
|
"""
|
|
def list_root_sites(organization_id) do
|
|
Repo.all(
|
|
from(s in Site,
|
|
where: s.organization_id == ^organization_id,
|
|
where: is_nil(s.parent_site_id),
|
|
order_by: [asc: s.name]
|
|
)
|
|
)
|
|
end
|
|
|
|
@doc """
|
|
Returns the list of child sites for a parent site.
|
|
"""
|
|
def list_child_sites(parent_site_id) do
|
|
Repo.all(from(s in Site, where: s.parent_site_id == ^parent_site_id, order_by: [asc: s.name]))
|
|
end
|
|
|
|
@doc """
|
|
Gets a single site.
|
|
"""
|
|
def get_site!(id) do
|
|
Site
|
|
|> Repo.get!(id)
|
|
|> Repo.preload([:parent_site, :child_sites, :device])
|
|
end
|
|
|
|
@doc """
|
|
Gets a single site belonging to an organization.
|
|
"""
|
|
def get_organization_site!(organization_id, site_id) do
|
|
Repo.one!(
|
|
from(s in Site,
|
|
where: s.id == ^site_id,
|
|
where: s.organization_id == ^organization_id,
|
|
preload: [:parent_site, :child_sites, :device]
|
|
)
|
|
)
|
|
end
|
|
|
|
@doc """
|
|
Creates a site.
|
|
"""
|
|
def create_site(attrs) do
|
|
%Site{}
|
|
|> Site.changeset(attrs)
|
|
|> Repo.insert()
|
|
end
|
|
|
|
@doc """
|
|
Updates a site.
|
|
"""
|
|
def update_site(%Site{} = site, attrs) do
|
|
site
|
|
|> Site.changeset(attrs)
|
|
|> Repo.update()
|
|
end
|
|
|
|
@doc """
|
|
Deletes a site.
|
|
"""
|
|
def delete_site(%Site{} = site) do
|
|
Repo.delete(site)
|
|
end
|
|
|
|
@doc """
|
|
Returns an `%Ecto.Changeset{}` for tracking site changes.
|
|
"""
|
|
def change_site(%Site{} = site, attrs \\ %{}) do
|
|
Site.changeset(site, attrs)
|
|
end
|
|
|
|
@doc """
|
|
Builds a hierarchical tree structure of sites.
|
|
"""
|
|
def build_site_tree(organization_id) do
|
|
sites = list_organization_sites(organization_id)
|
|
root_sites = Enum.filter(sites, &is_nil(&1.parent_site_id))
|
|
|
|
Enum.map(root_sites, fn root ->
|
|
build_tree_node(root, sites)
|
|
end)
|
|
end
|
|
|
|
defp build_tree_node(site, all_sites) do
|
|
children =
|
|
all_sites
|
|
|> Enum.filter(&(&1.parent_site_id == site.id))
|
|
|> Enum.map(&build_tree_node(&1, all_sites))
|
|
|
|
%{site: site, children: children}
|
|
end
|
|
|
|
## Bulk Configuration Updates
|
|
|
|
@doc """
|
|
Applies site's SNMP configuration to all devices at the site.
|
|
|
|
This updates all devices records to use the site's SNMP version and community string,
|
|
overwriting any existing device-level configurations.
|
|
|
|
Returns the number of device records updated.
|
|
"""
|
|
def apply_snmp_config_to_all_equipment(site_id) do
|
|
site = get_site!(site_id)
|
|
|
|
Repo.update_all(from(e in Device, where: e.site_id == ^site_id),
|
|
set: [
|
|
snmp_version: site.snmp_version,
|
|
snmp_community: site.snmp_community,
|
|
updated_at: DateTime.truncate(DateTime.utc_now(), :second)
|
|
]
|
|
)
|
|
end
|
|
|
|
@doc """
|
|
Applies site's agent to all devices at the site.
|
|
|
|
This creates/updates agent assignments for all devices at the site to use the site's
|
|
agent, overwriting any existing device-level assignments.
|
|
|
|
Returns the number of device records assigned.
|
|
"""
|
|
def apply_agent_to_all_equipment(site_id) do
|
|
site = Repo.get!(Site, site_id)
|
|
|
|
# device IDs for this site
|
|
device_ids = Repo.all(from(e in Device, where: e.site_id == ^site_id, select: e.id))
|
|
|
|
if site.agent_token_id do
|
|
# Delete existing assignments
|
|
Repo.delete_all(from(a in AgentAssignment, where: a.device_id in ^device_ids))
|
|
|
|
# Create new assignments
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
|
|
assignments =
|
|
Enum.map(device_ids, fn device_id ->
|
|
%{
|
|
device_id: device_id,
|
|
agent_token_id: site.agent_token_id,
|
|
inserted_at: now,
|
|
updated_at: now
|
|
}
|
|
end)
|
|
|
|
{count, _} = Repo.insert_all(AgentAssignment, assignments)
|
|
{count, nil}
|
|
else
|
|
# No agent set, delete all assignments (they will inherit from org or use cloud)
|
|
Repo.delete_all(from(a in AgentAssignment, where: a.device_id in ^device_ids))
|
|
end
|
|
end
|
|
end
|