Skip to content

Services: Kea: DHCPv4/6: Add delete lease command, use socket for up to date lease collection#10019

Open
Monviech wants to merge 12 commits intomasterfrom
kea-lease-del-hook
Open

Services: Kea: DHCPv4/6: Add delete lease command, use socket for up to date lease collection#10019
Monviech wants to merge 12 commits intomasterfrom
kea-lease-del-hook

Conversation

@Monviech
Copy link
Member

Fixes: #9217
Fixes: #9536

This shows the direction such a button could take. It works in my production KEA setup.

The idea is that leases you can see in the views now reflect the correct in-memory representation of KEA. Any command you do that mutates these leases through the available command sockets mutates the in-memory state.

This means, the csv lease files do not always represent the correct state at any given time during runtime, only the state collected by the socket is true.

When deleting a lease, it disappears from the in-memory database instantly and will not show up in the lease view. Though in the csv file it will be marked with a lifetime of 0, or be represented in .1 and .2 multiple times.

In essence this means we can only trust the control socket here, and never the files.

Docs:
https://kea.readthedocs.io/en/latest/api.html#lease4-del
https://kea.readthedocs.io/en/latest/api.html#lease6-del
https://kea.readthedocs.io/en/latest/api.html#config-get
https://kea.readthedocs.io/en/latest/api.html#lease4-get-all
https://kea.readthedocs.io/en/latest/api.html#lease6-get-all

@Monviech Monviech self-assigned this Mar 23, 2026
@Monviech Monviech added the feature Adding new functionality label Mar 23, 2026
@Monviech Monviech requested a review from swhite2 March 23, 2026 15:32
Comment on lines +124 to +148
const deleteBtn = $(`
<button type="button" class="btn btn-xs" data-toggle="tooltip"
title="{{ lang._('Delete Lease') }}">
<i class="fa fa-fw fa-trash"></i>
</button>
`).on('click', function () {
BootstrapDialog.confirm(
"{{ lang._('Are you sure you want to delete this lease?') }}",
function(ok) {
if (!ok) return;
ajaxCall(
"/api/kea/leases4/delete_lease/" + encodeURIComponent(row.address),
{},
function(data, status) {
if (status === "success" && data.status === "ok") {
$('#grid-leases').bootgrid('reload');
}
},
"POST"
);
}
);
});

return $('<span>').append(reservationBtn).append(deleteBtn)[0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can tie this whole block to the default delete command by setting datakey: 'address' and del: '/api/kea/leases4/delete_lease/'.

If you want batched deletes (delete-selected), you can set selection: true, multiSelect: true, and adjust the controller and backend calls to account for an array (https://github.com/opnsense/core/blob/master/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableModelControllerBase.php#L517).

Comment on lines +124 to +148
const deleteBtn = $(`
<button type="button" class="btn btn-xs" data-toggle="tooltip"
title="{{ lang._('Delete Lease') }}">
<i class="fa fa-fw fa-trash"></i>
</button>
`).on('click', function () {
BootstrapDialog.confirm(
"{{ lang._('Are you sure you want to delete this lease?') }}",
function(ok) {
if (!ok) return;
ajaxCall(
"/api/kea/leases6/delete_lease/" + encodeURIComponent(row.address),
{},
function(data, status) {
if (status === "success" && data.status === "ok") {
$('#grid-leases').bootgrid('reload');
}
},
"POST"
);
}
);
});

return $('<span>').append(reservationBtn).append(deleteBtn)[0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect(path)
sock.sendall(ujson.dumps({"command": cmd, "arguments": {"ip-address": ip}}).encode() + b"\n")
print(sock.recv(4096).decode())
Copy link
Member

@swhite2 swhite2 Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to me the send_command from get_kea_leases.py can be reused in a lib file. Now I know this is a simple delete command and the 4096 buffer is more than plenty, but I'd expect a terminating symbol instead of having to guess (which is what get_kea_leases checks for). Is there also no notion of "success" or "failure" here?

Edit: seems the latter is handled in the controller

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Adding new functionality

Development

Successfully merging this pull request may close these issues.

Kea DHCP GUI: add option to flush active DHCP leases (parity with ISC DHCP) Provide GUI option to delete dynamic Kea leases

2 participants