0

List devices

by
Published today

List monitored devices with their IP addresses and SNMP system info, optionally filtered by name/regex or device group.

Script akips Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 6 hours ago
1
//native
2

3
async function adb(auth: RT.Akips, cmd: string) {
4
  // A line break starts a second api-db command (§4.5.2 data), so inputs must stay on one line.
5
  if (/[\r\n]/.test(cmd)) throw new Error("api-db command must be a single line")
6

7
  // Documented form (API guide §4.5.2): password in the URL, commands in the POST body.
8
  const url = new URL(`${auth.base_url}/api-db`)
9
  url.searchParams.append("username", auth.username)
10
  url.searchParams.append("password", auth.password)
11
  const response = await fetch(url, {
12
    method: "POST",
13
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
14
    body: new URLSearchParams({ cmds: cmd }),
15
  }).catch((e) => {
16
    // Network errors quote the full URL: drop the query string, which holds the password.
17
    throw new Error(String(e).replaceAll(url.search, ""))
18
  })
19
  const text = await response.text()
20
  if (!response.ok || text.startsWith("ERROR:")) {
21
    throw new Error(`${response.status} ${text}`)
22
  }
23
  return text.split("\n").filter((line) => line.trim() !== "")
24
}
25

26
/**
27
 * List devices
28
 * List monitored devices with their IP addresses and SNMP system info (sysName, sysDescr, sysLocation, sysContact). Filter by device name/regex or device group. AKIPS returns all matches at once; limit/offset page through them.
29
 */
30
export async function main(
31
  auth: RT.Akips,
32
  device: string | undefined,
33
  group: string | undefined,
34
  limit: number | undefined,
35
  offset: number | undefined
36
) {
37
  const selector = device || "*"
38
  const groupFilter = group ? ` any group ${group}` : ""
39

40
  // Every device, including those without SNMP or IP text attributes ("Retrieve a list of
41
  // devices", API guide §4.5.1). The device name is the first token of each line.
42
  const names = [
43
    ...new Set(
44
      (await adb(auth, `mget device ${selector}${groupFilter}`)).map(
45
        (line) => line.trim().split(/\s+/)[0]
46
      )
47
    ),
48
  ].sort()
49

50
  const start = offset || 0
51
  const size = limit || 500
52
  const page = names.slice(start, start + size)
53

54
  // Each line: "{device} sys {attribute} = {value}"
55
  const attributes = new Map<string, { [key: string]: string }>()
56
  if (page.length > 0) {
57
    const lines = await adb(
58
      auth,
59
      `mget text ${selector} sys /^(ip4addr|ip6addr|SNMPv2-MIB\\.sysName|SNMPv2-MIB\\.sysDescr|SNMPv2-MIB\\.sysLocation|SNMPv2-MIB\\.sysContact)$/${groupFilter}`
60
    )
61
    for (const line of lines) {
62
      const match = line.match(/^(\S+)\s+\S+\s+(\S+)\s+=\s?(.*)$/)
63
      if (!match) continue
64
      const [, name, attribute, value] = match
65
      if (!attributes.has(name)) attributes.set(name, {})
66
      attributes.get(name)![attribute] = value
67
    }
68
  }
69

70
  const devices = page.map((name) => {
71
    const a = attributes.get(name) ?? {}
72
    return {
73
      name,
74
      ip4addr: a["ip4addr"],
75
      ip6addr: a["ip6addr"],
76
      sys_name: a["SNMPv2-MIB.sysName"],
77
      sys_descr: a["SNMPv2-MIB.sysDescr"],
78
      sys_location: a["SNMPv2-MIB.sysLocation"],
79
      sys_contact: a["SNMPv2-MIB.sysContact"],
80
    }
81
  })
82

83
  return {
84
    total: names.length,
85
    offset: start,
86
    limit: size,
87
    next_offset: start + size < names.length ? start + size : null,
88
    devices,
89
  }
90
}
91