librenms

package
v1.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 5, 2026 License: AGPL-3.0 Imports: 27 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FetchRemoteConfig

func FetchRemoteConfig(factumConfig *util.ConfigFactum) (*util.ConfigLibrenms, error)

FetchRemoteConfig pulls the full LibreNMS config - default domain, REST API connection settings, and the Sync regex-filter lists - from the primary, authenticated with factumConfig.Token (checked against the primary's Settings.FactumApiToken - see web.Controller.checkServiceToken).

Types

type FactumLibrenmsClient

type FactumLibrenmsClient struct {
	Config            *util.ConfigFactum
	DB                *util.ConfigDB
	Factum            *factum.FactumClient
	Librenms          *LibrenmsClient
	Netbox            *netboxtool.NetboxClient
	FactumDevices     []*models.Device
	LibrenmsDevices   []*LibrenmsDevice   // cache of devices
	LibrenmsPorts     []*LibrenmsPort     // cache of ports
	LibrenmsLocations []*LibrenmsLocation // cache of locations
	// Places are NetBox sites with coordinates, used to shorten a
	// generated location code. Empty when sites could not be loaded.
	Places                     []locationPlace
	RolesEnabledCompiled       []*regexp.Regexp
	InterfacesDisabledCompiled []*regexp.Regexp
}

func NewFactumLibrenmsClient

func NewFactumLibrenmsClient(config *util.ConfigFactum) (*FactumLibrenmsClient, error)

NewFactumLibrenmsClient fetches the LibreNMS config (REST API URL/key and the Sync regex-filter maps) from the primary over REST - config.Librenms is never used, since factum2-librenms-cli typically runs on a different host than the primary and has no local librenms config of its own (see util.ConfigLibrenms's doc comment).

func (*FactumLibrenmsClient) RefreshFactumDevices

func (fl *FactumLibrenmsClient) RefreshFactumDevices() error

func (*FactumLibrenmsClient) RefreshLibrenmsDevices

func (fl *FactumLibrenmsClient) RefreshLibrenmsDevices() error

func (*FactumLibrenmsClient) Sync

func (fl *FactumLibrenmsClient) Sync(reporter jobevent.Reporter) error

type Float32String

type Float32String float32

Float32String unmarshals a JSON number or a JSON string holding a number into a float32 - librenms's API is inconsistent about which one it sends for lat/lng (its own docs show lat/lng posted as strings), so a plain float32 field fails to unmarshal whenever a device/location happens to come back with a quoted value.

func (*Float32String) UnmarshalJSON

func (f *Float32String) UnmarshalJSON(data []byte) error

type IntString

type IntString int

IntString unmarshals a JSON number, a JSON bool, or a JSON string holding a number into an int - librenms's API sends the same field (e.g. ignore/disabled) as a number on the device-list endpoint but as a real JSON boolean on the single-device endpoint, on top of the number-as- string inconsistency Float32String works around.

func (*IntString) UnmarshalJSON

func (i *IntString) UnmarshalJSON(data []byte) error

type LibrenmsClient

type LibrenmsClient struct {
	P *util.ConfigLibrenms
	// DBConfig holds LibreNMS's own MySQL credentials, read directly from
	// LibreNMS's .env file on disk (see NewFactumLibrenmsClient) - unlike P,
	// which is fetched over REST from the primary. Left nil for callers that
	// never touch the port-level methods (PortsGet/PortsUpdateIgnore).
	DBConfig *util.ConfigDB
	DB       *sql.DB
}

func NewLibrenmsClient

func NewLibrenmsClient(param *util.ConfigLibrenms) *LibrenmsClient

Create a librenmsClient

func RemoteClient

func RemoteClient(factumConfig *util.ConfigFactum) (*LibrenmsClient, error)

RemoteClient is the FetchRemoteConfig + NewLibrenmsClient convenience most callers want.

func (*LibrenmsClient) DeviceAssignLocation added in v1.6.0

func (librenms *LibrenmsClient) DeviceAssignLocation(deviceID int, locationName string) error

DeviceAssignLocation points a device at a location that already exists and keeps polling from replacing it with sysLocation. The coordinate location is created directly in the database, so the device is linked the same way instead of relying on the location field of the device API.

func (*LibrenmsClient) DeviceCreate

func (librenms *LibrenmsClient) DeviceCreate(name string, display string, force_add bool, version string, community string) (int, error)

Create device, returns the librenms device_id of the created device. https://docs.librenms.org/API/Devices/#add_device display is the rendered name. add_device stores it as display_template and LibreNMS fills the display column from that on insert. The field named "display" is ignored.

func (*LibrenmsClient) DeviceDelete

func (librenms *LibrenmsClient) DeviceDelete(deviceID int) (*string, error)

Delete device https://docs.librenms.org/API/Devices/#del_device

func (*LibrenmsClient) DeviceGet

func (librenms *LibrenmsClient) DeviceGet(deviceID int) (*LibrenmsDevice, error)

Get one device, key is ID

func (*LibrenmsClient) DeviceGetByName

func (librenms *LibrenmsClient) DeviceGetByName(name string) (*LibrenmsDevice, error)

Get one device, name can be hostname or device_id https://docs.librenms.org/API/Devices/#get_device curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://foo.example/api/v0/devices/localhost

func (*LibrenmsClient) DeviceHelper

func (librenms *LibrenmsClient) DeviceHelper(name string) ([]*LibrenmsDevice, error)

Get all devices https://docs.librenms.org/API/Devices/#list_devices

func (*LibrenmsClient) DeviceParentCreate

func (librenms *LibrenmsClient) DeviceParentCreate(deviceID int, parent string) error

Add a parent to a device https://docs.librenms.org/API/Devices/#add_parents_to_host curl -X POST -d '{"parent_ids":"15,16,17"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://foo.example/api/v0/devices/1/parents

func (*LibrenmsClient) DeviceParentDelete

func (librenms *LibrenmsClient) DeviceParentDelete(deviceID int, parent string) (*string, error)

Delete a parent from a device, parent is device_id or hostname https://docs.librenms.org/API/Devices/#delete_parents_from_host curl -X DELETE -d '{"parent_ids":"15,16,17"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://foo.example/api/v0/devices/1/parents

func (*LibrenmsClient) DeviceParentList

func (librenms *LibrenmsClient) DeviceParentList(deviceID int) ([]*string, error)

Get all parents for a device https://docs.librenms.org/API/Devices/#list_parents_of_host curl -H 'X-Auth-Token: YOURAPITOKENHERE' 'http://foo.example/api/v0/devices?type=device_id&query=34'

func (*LibrenmsClient) DeviceRename

func (librenms *LibrenmsClient) DeviceRename(deviceID int, newName string) (*string, error)

Rename device. https://docs.librenms.org/API/Devices/#rename_device PATCH /api/v0/devices/:hostname/rename/:new_hostname (hostname may be the device id). The documented body is [{"status":"ok","message":"Device has been renamed"}]; current api_success returns that object without the array wrapper. LibreNMS 26.8.2's rename_device saves the hostname and then falls off the end of the function, so a successful rename is HTTP 200 with an empty body. That is not a failure: re-read the device and accept the rename when the hostname matches.

func (*LibrenmsClient) DeviceSetLocation

func (librenms *LibrenmsClient) DeviceSetLocation(deviceID int, locationName string, lat *float64, lng *float64) error

Set location on a device If location does not exist, it is created

func (*LibrenmsClient) DeviceUpdate

func (librenms *LibrenmsClient) DeviceUpdate(deviceID int, updates map[string]string) (*string, error)

Update device fields https://docs.librenms.org/API/Devices/#update_device_field

func (*LibrenmsClient) DevicesGet

func (librenms *LibrenmsClient) DevicesGet() ([]*LibrenmsDevice, error)

func (*LibrenmsClient) LocationCreate

func (librenms *LibrenmsClient) LocationCreate(locationName string, lat *float64, lng *float64) (*string, error)

Create new location https://docs.librenms.org/API/Locations/#add_location curl -X POST -d '{"location":"Google", "lat":"37.4220041","lng":"-122.0862462"}' -H 'X-Auth-Token:YOUR-API-TOKEN' https://foo.example/api/v0/locations

func (*LibrenmsClient) LocationGet

func (librenms *LibrenmsClient) LocationGet(name string) (*LibrenmsLocation, error)

Get one location, using the name or id https://docs.librenms.org/API/Locations/#get_location

func (*LibrenmsClient) LocationInsertCoordinates added in v1.6.0

func (librenms *LibrenmsClient) LocationInsertCoordinates(locationName string, lat, lng float64) (bool, error)

LocationInsertCoordinates creates a LibreNMS location that already has its pin, with fixed_coordinates set. Sync uses it for a coordinate location that does not exist yet. A duplicate name falls through to LocationSetCoordinates.

func (*LibrenmsClient) LocationSetCoordinates added in v1.5.0

func (librenms *LibrenmsClient) LocationSetCoordinates(locationName string, lat, lng float64) (bool, error)

LocationSetCoordinates writes lat/lng onto a LibreNMS location and pins them. Coordinates live on the location row, which every device at that location shares. The edit-location API can set lat/lng, but fixed_coordinates is not fillable there, so the next poll geocodes over the values. The web UI sets the flag itself; this update does the same in the database. A matching row that is already at these coordinates and already fixed is left alone. changed is false in that case.

func (*LibrenmsClient) LocationUpdate

func (librenms *LibrenmsClient) LocationUpdate(locationID int, lat *float64, lng *float64) (*string, error)

Update location, location: name or id of the location to edit https://docs.librenms.org/API/Locations/#edit_location curl -X PATCH -d '{"lng":"100.0862462"}' -H 'X-Auth-Token:YOUR-API-TOKEN' https://foo.example/api/v0/locations/Google

func (*LibrenmsClient) LocationsGet

func (librenms *LibrenmsClient) LocationsGet() ([]*LibrenmsLocation, error)

Get all locations https://docs.librenms.org/API/Locations/ curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://foo.example/api/v0/resources/locations

func (*LibrenmsClient) NormalizeHostnames

func (librenms *LibrenmsClient) NormalizeHostnames(reporter jobevent.Reporter) (int, error)

NormalizeHostnames finds every device whose hostname is not an IP address (e.g. a legacy/manually-added device keyed on a name), preserves that name as the device's display name, then renames the device's hostname to its last-known IP address (LibrenmsDevice.IP) via the rename_device API. https://docs.librenms.org/API/Devices/#rename_device A device with no known IP yet is skipped rather than failed, since there is nothing to rename it to. Per-device errors are logged and skipped so one bad device doesn't block the rest of the run.

func (*LibrenmsClient) PortsGet

func (librenms *LibrenmsClient) PortsGet(deviceID int) ([]*LibrenmsPort, error)

Get all ports for a device. https://docs.librenms.org/API/Devices/#get_device_ports Uses direct database access, API is SLOW!

func (*LibrenmsClient) PortsUpdateIgnore

func (librenms *LibrenmsClient) PortsUpdateIgnore(portID int, ignore int) error

Update a port details There is no API, database is updated directly

func (*LibrenmsClient) SetDeviceParent

func (librenms *LibrenmsClient) SetDeviceParent(deviceID int, new_parents []*string) error

Set parent on a device This is not an Librenms API call. Fetch all parents and adjust accordingly

type LibrenmsDevice

type LibrenmsDevice struct {
	DeviceID                 int            `json:"device_id"`
	Hostname                 string         `json:"hostname"`
	Location                 string         `json:"location"`
	Display                  string         `json:"display"`
	IP                       string         `json:"ip"`
	Community                string         `json:"community"`
	SNMPver                  string         `json:"snmpver"`
	LocationID               int            `json:"location_id"`
	OS                       string         `json:"hpe-ilo"`
	Ignore                   int            `json:"ignore"`
	Disabled                 int            `json:"disabled"`
	DependencyParentID       int            `json:"dependency_parent_id"`
	DependencyParentHostname string         `json:"dependency_parent_hostname"`
	Lat                      *Float32String `json:"lat"`
	Lng                      *Float32String `json:"lng"`
}

We follow librenms names on variables

func (*LibrenmsDevice) UnmarshalJSON

func (d *LibrenmsDevice) UnmarshalJSON(data []byte) error

librenms's API is inconsistent about whether device_id/location_id/ignore/ disabled/dependency_parent_id come back as JSON numbers or JSON strings (same issue as lat/lng) - unmarshal through IntString-typed fields and copy the results into the plain ints the rest of the codebase expects.

type LibrenmsLocation

type LibrenmsLocation struct {
	ID               int            `json:"id"`
	Location         string         `json:"location"`
	Lat              *Float32String `json:"lat"`
	Lng              *Float32String `json:"lng"`
	FixedCoordinates int            `json:"fixed_coordinates"`
}

func (*LibrenmsLocation) UnmarshalJSON

func (l *LibrenmsLocation) UnmarshalJSON(data []byte) error

See LibrenmsDevice.UnmarshalJSON - fixed_coordinates has been observed as a JSON bool (in the nested location object embedded by the single-device endpoint), so route it through IntString like the device's bool-ish fields.

type LibrenmsLocationResponse

type LibrenmsLocationResponse struct {
	StatusJSON
	Locations []*LibrenmsLocation `json:"get_location"`
}

API JSON response

type LibrenmsLocationsResponse

type LibrenmsLocationsResponse struct {
	StatusJSON
	Locations []*LibrenmsLocation `json:"locations"`
}

API JSON response

type LibrenmsPort

type LibrenmsPort struct {
	PortID   int    `json:"port_id"`
	DeviceID int    `json:"device_id"`
	Name     string `json:"Name"`
	IfName   string `json:"ifName"`
	IfDescr  string `json:"ifDescr"`
	IfAlias  string `json:"ifAlias"`
	Ignore   int    `json:"ignore"`
}

type LibrenmsPorts

type LibrenmsPorts struct {
	Status string          `json:"status"`
	Ports  []*LibrenmsPort `json:"ports"`
}

API JSON response

type StatusJSON

type StatusJSON struct {
	Status  string      `json:"status"`
	Count   StringOrNum `json:"count"`
	Message string      `json:"message"`
}

type StringOrNum

type StringOrNum string

StringOrNum unmarshals a JSON number or a JSON string into a string - librenms's delete_device endpoint sends "count" as a number while other endpoints (e.g. add_device) send it as a string, the same status-JSON inconsistency pattern Float32String/IntString work around elsewhere in this file.

func (*StringOrNum) UnmarshalJSON

func (s *StringOrNum) UnmarshalJSON(data []byte) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL