devon-mar / netbox-kea

Manage Kea DHCP leases in NetBox.
Apache License 2.0
68 stars 3 forks source link

stand alone kea-dhcp4 with no control-agent. #1

Closed ThomasADavis closed 1 year ago

ThomasADavis commented 1 year ago

We run kea in a HA setup, with no control-agent, dhcp4 only. Yes, this is a feature of v2.2. No dhcp6.

Looking at the status page gives an error, which when netbox debug is turned on this stack dump:

Internal Server Error: /plugins/kea/servers/1/status/
Traceback (most recent call last):
  File "/opt/netbox/venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 56, in inner
    response = get_response(request)
  File "/opt/netbox/venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/opt/netbox/venv/lib/python3.10/site-packages/django/views/generic/base.py", line 103, in view
    return self.dispatch(request, *args, **kwargs)
  File "/opt/netbox/netbox/netbox/views/generic/base.py", line 26, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/opt/netbox/netbox/utilities/views.py", line 99, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/opt/netbox/venv/lib/python3.10/site-packages/django/views/generic/base.py", line 142, in dispatch
    return handler(request, *args, **kwargs)
  File "/opt/netbox/netbox/netbox/views/generic/object_views.py", line 73, in get
    **self.get_extra_context(request, instance),
  File "/opt/netbox/venv/lib/python3.10/site-packages/netbox_kea/views.py", line 149, in get_extra_context
    return {"statuses": self._get_statuses(instance.get_client())}
  File "/opt/netbox/venv/lib/python3.10/site-packages/netbox_kea/views.py", line 143, in _get_statuses
    **self._get_dhcp_status(client),
  File "/opt/netbox/venv/lib/python3.10/site-packages/netbox_kea/views.py", line 81, in _get_dhcp_status
    assert len(dhcp_status) == len(services)
AssertionError
10.42.1.22 - - [14/May/2023:22:06:04 +0000] "GET /plugins/kea/servers/1/status/ HTTP/1.1" 500 122443 "https://netbox-dev.nersc.gov/plugins/kea/servers/1/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36"

with this from the netbox debug page Screenshot_2023-05-14_15-10-56

The dhcp6 subnet tab also crashes, with this:

Screenshot_2023-05-14_15-38-55

ThomasADavis commented 1 year ago

This is what you get when you use just curl against it.

[tdavis@mouse-r11 omni-netbox]$ curl -s -X POST -H "Content-Type: application/json" http://cobbler.omni:8001 -d '{ "command": "config-get" }' | jq
[
  {
    "arguments": {
      "Dhcp4": {
        "authoritative": false,
        "boot-file-name": "",
        "calculate-tee-times": false,
        "client-classes": [
          {
            "boot-file-name": "pxelinux.0",
            "name": "Legacy_Intel_x86PC",
            "next-server": "0.0.0.0",
            "option-data": [],
            "option-def": [],
            "server-hostname": "",
            "test": "option[93].hex == 0x0000"
          },
          {
            "boot-file-name": "ipx-snponly.efi",
            "name": "EFI_x86-64",
            "next-server": "0.0.0.0",
            "option-data": [],
            "option-def": [],
            "server-hostname": "",
            "test": "option[93].hex == 0x0009"
          },
          {
            "boot-file-name": "http://192.168.97.6/ipxe-x86_64.efi",
            "name": "HTTPClient",
            "next-server": "0.0.0.0",
            "option-data": [
              {
                "always-send": false,
                "code": 60,
                "csv-format": true,
                "data": "HTTPClient",
                "name": "vendor-class-identifier",
                "space": "dhcp4"
              }
            ],
            "option-def": [],
            "server-hostname": "",
            "test": "option[93].hex == 0x0010"
          },
          {
            "boot-file-name": "http://192.168.97.6/ipxe/boot.ipxe",
            "name": "boot_iPXE",
            "next-server": "0.0.0.0",
            "option-data": [],
            "option-def": [],
            "server-hostname": "",
            "test": "(substring(option[77].hex,0,4) == 'iPXE') and (pkt.iface == 'boot')"
          },
          {
            "boot-file-name": "http://192.168.84.6/ipxe/ovirtmgmt.ipxe",
            "name": "ovirtmgmt_iPXE",
            "next-server": "0.0.0.0",
            "option-data": [],
            "option-def": [],
            "server-hostname": "",
            "test": "(substring(option[77].hex,0,4) == 'iPXE') and (pkt.iface == 'ovirtmgmt')"
          }
        ],
        "control-socket": {
          "socket-name": "/run/kea/kea-dhcp4-ctrl.sock",
          "socket-type": "unix"
        },
        "ddns-generated-prefix": "myhost",
        "ddns-override-client-update": false,
        "ddns-override-no-update": false,
        "ddns-qualifying-suffix": "",
        "ddns-replace-client-name": "never",
        "ddns-send-updates": true,
        "ddns-update-on-renew": false,
        "ddns-use-conflict-resolution": true,
        "decline-probation-period": 86400,
        "dhcp-ddns": {
          "enable-updates": false,
          "max-queue-size": 1024,
          "ncr-format": "JSON",
          "ncr-protocol": "UDP",
          "sender-ip": "0.0.0.0",
          "sender-port": 0,
          "server-ip": "127.0.0.1",
          "server-port": 53001
        },
        "dhcp-queue-control": {
          "capacity": 64,
          "enable-queue": false,
          "queue-type": "kea-ring4"
        },
        "dhcp4o6-port": 0,
        "early-global-reservations-lookup": false,
        "echo-client-id": true,
        "expired-leases-processing": {
          "flush-reclaimed-timer-wait-time": 25,
          "hold-reclaimed-time": 3600,
          "max-reclaim-leases": 100,
          "max-reclaim-time": 250,
          "reclaim-timer-wait-time": 10,
          "unwarned-reclaim-cycles": 5
        },
        "hooks-libraries": [
          {
            "library": "/usr/lib/kea/hooks/libdhcp_bootp.so",
            "parameters": {}
          },
          {
            "library": "/usr/lib/kea/hooks/libdhcp_lease_cmds.so",
            "parameters": {}
          },
          {
            "library": "/usr/lib/kea/hooks/libdhcp_ha.so",
            "parameters": {
              "high-availability": [
                {
                  "delayed-updates-limit": 0,
                  "heartbeat-delay": 10000,
                  "max-ack-delay": 5000,
                  "max-response-delay": 10000,
                  "max-unacked-clients": 3,
                  "mode": "hot-standby",
                  "multi-threading": {
                    "enable-multi-threading": true,
                    "http-client-threads": 4,
                    "http-dedicated-listener": true,
                    "http-listener-threads": 4
                  },
                  "peers": [
                    {
                      "auto-failover": true,
                      "name": "cobbler",
                      "role": "primary",
                      "url": "http://192.168.84.6:8001/"
                    },
                    {
                      "auto-failover": true,
                      "name": "mouse-r11",
                      "role": "standby",
                      "url": "http://192.168.84.2:8001/"
                    },
                    {
                      "auto-failover": true,
                      "name": "mouse-r12",
                      "role": "backup",
                      "url": "http://192.168.84.3:8001/"
                    },
                    {
                      "auto-failover": true,
                      "name": "mouse-r13",
                      "role": "backup",
                      "url": "http://192.168.84.4:8001/"
                    }
                  ],
                  "require-client-certs": true,
                  "restrict-commands": false,
                  "send-lease-updates": true,
                  "sync-leases": true,
                  "sync-page-limit": 10000,
                  "sync-timeout": 60000,
                  "this-server-name": "cobbler",
                  "wait-backup-ack": false
                }
              ]
            }
          }
        ],
        "host-reservation-identifiers": [
          "hw-address",
          "duid",
          "circuit-id",
          "client-id"
        ],
        "hostname-char-replacement": "",
        "hostname-char-set": "[^A-Za-z0-9.-]",
        "hosts-databases": [
          {
            "host": "mariadb.kea-cobbler.svc.cluster.local.",
            "name": "kea",
            "password": "PASSWORDWASHERE",
            "type": "mysql",
            "user": "kea"
          }
        ],
        "interfaces-config": {
          "interfaces": [
            "boot",
            "ipmi",
            "modbus",
            "onewire",
            "ovirtmgmt",
            "pdunet",
            "switch",
            "trendpoint"
          ],
          "re-detect": true
        },
        "ip-reservations-unique": true,
        "lease-database": {
          "host": "mariadb.kea-cobbler.svc.cluster.local.",
          "name": "kea",
          "password": "PASSWORDWASHERE",
          "type": "mysql",
          "user": "kea"
        },
        "loggers": [
          {
            "debuglevel": 0,
            "name": "kea-dhcp4",
            "output_options": [
              {
                "flush": true,
                "output": "stdout",
                "pattern": "%-5p %m\n"
              }
            ],
            "severity": "INFO"
          }
        ],
        "match-client-id": true,
        "multi-threading": {
          "enable-multi-threading": true,
          "packet-queue-size": 64,
          "thread-pool-size": 16
        },
        "next-server": "0.0.0.0",
        "option-data": [
          {
            "always-send": false,
            "code": 15,
            "csv-format": true,
            "data": "omni",
            "name": "domain-name",
            "space": "dhcp4"
          },
          {
            "always-send": false,
            "code": 119,
            "csv-format": true,
            "data": "omni, crt.nersc.gov, nersc.gov",
            "name": "domain-search",
            "space": "dhcp4"
          }
        ],
        "option-def": [],
        "parked-packet-limit": 256,
        "rebind-timer": 1800,
        "renew-timer": 900,
        "reservations-global": false,
        "reservations-in-subnet": true,
        "reservations-lookup-first": false,
        "reservations-out-of-pool": false,
        "sanity-checks": {
          "lease-checks": "warn"
        },
        "server-hostname": "",
        "server-tag": "",
        "shared-networks": [],
        "statistic-default-sample-age": 0,
        "statistic-default-sample-count": 20,
        "store-extended-info": false,
        "subnet4": [
          {
            "4o6-interface": "",
            "4o6-interface-id": "",
            "4o6-subnet": "",
            "calculate-tee-times": false,
            "id": 10,
            "interface": "pdunet",
            "max-valid-lifetime": 3600,
            "min-valid-lifetime": 3600,
            "option-data": [
              {
                "always-send": false,
                "code": 4,
                "csv-format": true,
                "data": "192.168.88.2,192.168.88.3,192.168.88.4",
                "name": "time-servers",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 6,
                "csv-format": true,
                "data": "192.168.88.2,192.168.88.3,192.168.88.4",
                "name": "domain-name-servers",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 3,
                "csv-format": true,
                "data": "192.168.88.1",
                "name": "routers",
                "space": "dhcp4"
              }
            ],
            "pools": [
              {
                "option-data": [],
                "pool": "192.168.91.33-192.168.91.192"
              }
            ],
            "rebind-timer": 1800,
            "relay": {
              "ip-addresses": []
            },
            "renew-timer": 900,
            "reservations": [],
            "reservations-global": false,
            "reservations-in-subnet": true,
            "reservations-out-of-pool": true,
            "store-extended-info": false,
            "subnet": "192.168.88.0/22",
            "t1-percent": 0.5,
            "t2-percent": 0.875,
            "valid-lifetime": 3600
          },
          {
            "4o6-interface": "",
            "4o6-interface-id": "",
            "4o6-subnet": "",
            "calculate-tee-times": false,
            "id": 20,
            "interface": "ipmi",
            "max-valid-lifetime": 3600,
            "min-valid-lifetime": 3600,
            "option-data": [
              {
                "always-send": false,
                "code": 4,
                "csv-format": true,
                "data": "192.168.79.2,192.168.79.3,192.168.79.4",
                "name": "time-servers",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 6,
                "csv-format": true,
                "data": "192.168.79.2,192.168.79.3,192.168.79.4",
                "name": "domain-name-servers",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 3,
                "csv-format": true,
                "data": "192.168.79.1",
                "name": "routers",
                "space": "dhcp4"
              }
            ],
            "pools": [
              {
                "option-data": [],
                "pool": "192.168.79.0/25"
              }
            ],
            "rebind-timer": 1800,
            "relay": {
              "ip-addresses": []
            },
            "renew-timer": 900,
            "reservations": [],
            "reservations-global": false,
            "reservations-in-subnet": true,
            "reservations-out-of-pool": true,
            "store-extended-info": false,
            "subnet": "192.168.76.0/22",
            "t1-percent": 0.5,
            "t2-percent": 0.875,
            "valid-lifetime": 3600
          },
          {
            "4o6-interface": "",
            "4o6-interface-id": "",
            "4o6-subnet": "",
            "calculate-tee-times": false,
            "id": 30,
            "interface": "modbus",
            "max-valid-lifetime": 3600,
            "min-valid-lifetime": 3600,
            "option-data": [
              {
                "always-send": false,
                "code": 4,
                "csv-format": true,
                "data": "192.168.94.2,192.168.94.3,192.168.94.4",
                "name": "time-servers",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 6,
                "csv-format": true,
                "data": "192.168.94.2,192.168.94.3,192.168.94.4",
                "name": "domain-name-servers",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 3,
                "csv-format": true,
                "data": "192.168.94.1",
                "name": "routers",
                "space": "dhcp4"
              }
            ],
            "pools": [
              {
                "option-data": [],
                "pool": "192.168.94.70-192.168.94.92"
              }
            ],
            "rebind-timer": 1800,
            "relay": {
              "ip-addresses": []
            },
            "renew-timer": 900,
            "reservations": [],
            "reservations-global": false,
            "reservations-in-subnet": true,
            "reservations-out-of-pool": true,
            "store-extended-info": false,
            "subnet": "192.168.94.0/24",
            "t1-percent": 0.5,
            "t2-percent": 0.875,
            "valid-lifetime": 3600
          },
          {
            "4o6-interface": "",
            "4o6-interface-id": "",
            "4o6-subnet": "",
            "calculate-tee-times": false,
            "id": 40,
            "interface": "onewire",
            "max-valid-lifetime": 3600,
            "min-valid-lifetime": 3600,
            "option-data": [
              {
                "always-send": false,
                "code": 4,
                "csv-format": true,
                "data": "192.168.93.2,192.168.93.3,192.168.93.4",
                "name": "time-servers",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 6,
                "csv-format": true,
                "data": "192.168.93.2,192.168.93.3,192.168.93.4",
                "name": "domain-name-servers",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 3,
                "csv-format": true,
                "data": "192.168.93.2",
                "name": "routers",
                "space": "dhcp4"
              }
            ],
            "pools": [
              {
                "option-data": [],
                "pool": "192.168.93.224-192.168.93.254"
              }
            ],
            "rebind-timer": 1800,
            "relay": {
              "ip-addresses": []
            },
            "renew-timer": 900,
            "reservations": [],
            "store-extended-info": false,
            "subnet": "192.168.93.0/24",
            "t1-percent": 0.5,
            "t2-percent": 0.875,
            "valid-lifetime": 3600
          },
          {
            "4o6-interface": "",
            "4o6-interface-id": "",
            "4o6-subnet": "",
            "boot-file-name": "ipxe-x86_64.efi",
            "calculate-tee-times": false,
            "id": 50,
            "interface": "ovirtmgmt",
            "max-valid-lifetime": 3600,
            "min-valid-lifetime": 3600,
            "next-server": "192.168.84.6",
            "option-data": [
              {
                "always-send": false,
                "code": 42,
                "csv-format": true,
                "data": "192.168.84.2,192.168.84.3,192.168.84.4",
                "name": "ntp-servers",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 6,
                "csv-format": true,
                "data": "192.168.84.2,192.168.84.3",
                "name": "domain-name-servers",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 3,
                "csv-format": true,
                "data": "192.168.84.1",
                "name": "routers",
                "space": "dhcp4"
              }
            ],
            "pools": [
              {
                "client-class": "ovirtmgmt_iPXE",
                "option-data": [],
                "pool": "192.168.87.16/28"
              },
              {
                "option-data": [],
                "pool": "192.168.87.32-192.168.87.192"
              }
            ],
            "rebind-timer": 1800,
            "relay": {
              "ip-addresses": []
            },
            "renew-timer": 900,
            "reservations": [],
            "reservations-global": false,
            "reservations-in-subnet": true,
            "reservations-out-of-pool": true,
            "store-extended-info": false,
            "subnet": "192.168.84.0/22",
            "t1-percent": 0.5,
            "t2-percent": 0.875,
            "valid-lifetime": 3600
          },
          {
            "4o6-interface": "",
            "4o6-interface-id": "",
            "4o6-subnet": "",
            "boot-file-name": "ipxe-x86_64.efi",
            "calculate-tee-times": false,
            "id": 60,
            "interface": "boot",
            "max-valid-lifetime": 3600,
            "min-valid-lifetime": 3600,
            "next-server": "192.168.97.6",
            "option-data": [
              {
                "always-send": false,
                "code": 6,
                "csv-format": true,
                "data": "192.168.97.2",
                "name": "domain-name-servers",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 3,
                "csv-format": true,
                "data": "192.168.97.1",
                "name": "routers",
                "space": "dhcp4"
              }
            ],
            "pools": [
              {
                "client-class": "boot_iPXE",
                "option-data": [],
                "pool": "192.168.97.64/26"
              },
              {
                "option-data": [],
                "pool": "192.168.97.128-192.168.97.192"
              }
            ],
            "rebind-timer": 1800,
            "relay": {
              "ip-addresses": []
            },
            "renew-timer": 900,
            "reservations": [],
            "reservations-global": false,
            "reservations-in-subnet": true,
            "reservations-out-of-pool": true,
            "store-extended-info": false,
            "subnet": "192.168.97.0/24",
            "t1-percent": 0.5,
            "t2-percent": 0.875,
            "valid-lifetime": 3600
          },
          {
            "4o6-interface": "",
            "4o6-interface-id": "",
            "4o6-subnet": "",
            "calculate-tee-times": false,
            "id": 70,
            "interface": "switch",
            "max-valid-lifetime": 3600,
            "min-valid-lifetime": 3600,
            "option-data": [
              {
                "always-send": false,
                "code": 6,
                "csv-format": true,
                "data": "192.168.96.1",
                "name": "domain-name-servers",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 67,
                "csv-format": true,
                "data": "http://192.168.96.6/sonic/ztp.json",
                "name": "boot-file-name",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 3,
                "csv-format": true,
                "data": "192.168.96.2",
                "name": "routers",
                "space": "dhcp4"
              }
            ],
            "pools": [
              {
                "option-data": [],
                "pool": "192.168.96.192-192.168.96.253"
              }
            ],
            "rebind-timer": 1800,
            "relay": {
              "ip-addresses": []
            },
            "renew-timer": 900,
            "reservations": [],
            "reservations-global": false,
            "reservations-in-subnet": true,
            "reservations-out-of-pool": true,
            "store-extended-info": false,
            "subnet": "192.168.96.0/24",
            "t1-percent": 0.5,
            "t2-percent": 0.875,
            "valid-lifetime": 3600
          },
          {
            "4o6-interface": "",
            "4o6-interface-id": "",
            "4o6-subnet": "",
            "calculate-tee-times": false,
            "id": 75,
            "interface": "trendpoint",
            "max-valid-lifetime": 3600,
            "min-valid-lifetime": 3600,
            "option-data": [
              {
                "always-send": false,
                "code": 6,
                "csv-format": true,
                "data": "192.168.98.2, 192.168.98.3, 192.168.98.4",
                "name": "domain-name-servers",
                "space": "dhcp4"
              },
              {
                "always-send": false,
                "code": 3,
                "csv-format": true,
                "data": "192.168.98.1",
                "name": "routers",
                "space": "dhcp4"
              }
            ],
            "pools": [
              {
                "option-data": [],
                "pool": "192.168.98.221-192.168.98.253"
              }
            ],
            "rebind-timer": 1800,
            "relay": {
              "ip-addresses": []
            },
            "renew-timer": 900,
            "reservations": [],
            "reservations-global": false,
            "reservations-in-subnet": true,
            "reservations-out-of-pool": true,
            "store-extended-info": false,
            "subnet": "192.168.98.0/24",
            "t1-percent": 0.5,
            "t2-percent": 0.875,
            "valid-lifetime": 3600
          }
        ],
        "t1-percent": 0.5,
        "t2-percent": 0.875,
        "valid-lifetime": 3600
      }
    },
    "result": 0
  }
]
devon-mar commented 1 year ago

Wow I can't believe someone is using this already!

Does the DHCPv4 leases view work?

What's the output when you do

curl -H 'Content-Type: application/json' --data  '{"command":"status-get","service":["dhcp4","dhcp6"]}' <YOUR SERVER>

I get the following when DHCPv6 is not configured:

[
  {
    "arguments": {
      "multi-threading-enabled": false,
      "pid": 1,
      "reload": 34933,
      "sockets": {
        "status": "ready"
      },
      "uptime": 34933
    },
    "result": 0
  },
  {
    "result": 1,
    "text": "forwarding socket is not configured for the server type dhcp6"
  }
]

I think I'll add a toggle for DHCPv4/v6 to hide/disable the features.

ThomasADavis commented 1 year ago

Found this when I was looking for kea/netbox integrations.. There are several others, but they failed to work with the HA setup we have - you can't rewrite the config when HA is running.

The Dhcp4 subnets/reservations tabs work great, other than we use FQDN's which don't match up with the netbox device names.

well, when you do the config-get, if you don't see the 'Dhcp4' or 'Dhcp6' array item, you then know what the server supports. You can then also not show the tabs for that supported service; ie, if it's Dhcp4 only, then no Dhcp6 tabs, and vice-a-versa.

[tdavis@mouse-r11 ~]$ curl -s -H 'Content-Type: application/json' --data  '{"command":"status-get","service":["dhcp4","dhcp6"]}' mouse-r11:8001 | jq
[
  {
    "arguments": {
      "high-availability": [
        {
          "ha-mode": "hot-standby",
          "ha-servers": {
            "local": {
              "role": "standby",
              "scopes": [],
              "state": "hot-standby"
            },
            "remote": {
              "age": 9,
              "analyzed-packets": 0,
              "communication-interrupted": false,
              "connecting-clients": 0,
              "in-touch": true,
              "last-scopes": [
                "cobbler"
              ],
              "last-state": "hot-standby",
              "role": "primary",
              "unacked-clients": 0,
              "unacked-clients-left": 0
            }
          }
        }
      ],
      "multi-threading-enabled": true,
      "packet-queue-size": 64,
      "packet-queue-statistics": [
        1.00001,
        1.00819,
        1.01175
      ],
      "pid": 110,
      "reload": 1642757,
      "sockets": {
        "status": "ready"
      },
      "thread-pool-size": 16,
      "uptime": 1642758
    },
    "result": 0
  }
]

It doesn't matter what you ask for it's the same output everytime.

ThomasADavis commented 1 year ago

Dang it, wrong server above.. this is the primary results, above is a hot-standby server.

[tdavis@mouse-r11 ~]$ curl -s -H 'Content-Type: application/json' --data  '{"command":"status-get","service":["dhcp4","dhcp6"]}' cobbler:8001 | jq
[
  {
    "arguments": {
      "high-availability": [
        {
          "ha-mode": "hot-standby",
          "ha-servers": {
            "local": {
              "role": "primary",
              "scopes": [
                "cobbler"
              ],
              "state": "hot-standby"
            },
            "remote": {
              "age": 4,
              "analyzed-packets": 0,
              "communication-interrupted": false,
              "connecting-clients": 0,
              "in-touch": true,
              "last-scopes": [],
              "last-state": "hot-standby",
              "role": "standby",
              "unacked-clients": 0,
              "unacked-clients-left": 0
            }
          }
        }
      ],
      "multi-threading-enabled": true,
      "packet-queue-size": 64,
      "packet-queue-statistics": [
        1.0,
        1.00011,
        1.00261
      ],
      "pid": 55,
      "reload": 529164,
      "sockets": {
        "status": "ready"
      },
      "thread-pool-size": 16,
      "uptime": 529165
    },
    "result": 0
  }
]

and a 3rd server type we run, which is a backup server aka, we are running a primary-secondary-backup setup here.

[tdavis@mouse-r11 ~]$ curl -s -H 'Content-Type: application/json' --data  '{"command":"status-get","service":["dhcp4","dhcp6"]}' mouse-r12:8001 | jq
[
  {
    "arguments": {
      "high-availability": [
        {
          "ha-mode": "hot-standby",
          "ha-servers": {
            "local": {
              "role": "backup",
              "scopes": [],
              "state": "backup"
            }
          }
        }
      ],
      "multi-threading-enabled": true,
      "packet-queue-size": 64,
      "packet-queue-statistics": [
        0.0,
        0.0,
        0.0
      ],
      "pid": 20,
      "reload": 1814925,
      "thread-pool-size": 16,
      "uptime": 1814925
    },
    "result": 0
  }
]
devon-mar commented 1 year ago

We run kea in a HA setup, with no control-agent, dhcp4 only.

I wasn't aware that you can do that. I assume that you're using the setup described here with http-dedicated-listener?

I don't think that sending non-HA commands on a dedicated listener is a supported config: https://gitlab.isc.org/isc-projects/kea/-/issues/2062 and "Note the commands should still be sent via CA. The dedicated listener is specifically for HA updates only." from https://kea.readthedocs.io/en/latest/arm/config-templates.html?highlight=dedicated-listener#id2

you can't rewrite the config when HA is running.

Hmmm I have a script that pushes a config to a hot-standby pair and it seems to work fine.

devon-mar commented 1 year ago

@ThomasADavis could you try the latest master and run ./manage.py migrate it'll add a DHCPv4/6 field to the server which you can toggle. Let me know if this works for you.

ThomasADavis commented 1 year ago

it works.

btw, we run kea-dhcp4 only, in a pod with host network/privileged execution, read-only fs with the leases/reservations in a mysql db; the configurations are supplied by configmap, so no changing it via API.. This plugin at least lets us see the leases and status of the server, except I haven't tried it to see what happens if the daemon is down.

devon-mar commented 1 year ago

Thanks! I published this project on PyPi so you can install it from there now if you'd like.