Commit 55bfebe9 authored by Filip Siroky's avatar Filip Siroky Committed by Filip Široký

zone-status: add filtering + event timing

parent 245ae377
......@@ -89,9 +89,6 @@ in the configuration. (*)
\fBzone\-memstats\fP [\fIzone\fP\&...]
Estimate memory use for the zone. (*)
.TP
\fBzone\-status\fP [\fIzone\fP\&...]
Show the zone status. (*)
.TP
\fBzone\-reload\fP [\fIzone\fP\&...]
Trigger a zone reload from a disk without checking its modification time. For
slave zone, the refresh from a master server is scheduled; for master zone,
......@@ -145,6 +142,10 @@ Purge zone data, file, journal, and timers.
Show zone statistics counter(s). To print also counters with value 0, use
force option.
.TP
\fBzone\-status\fP \fIzone\fP [\fIfilter\fP]
Show the zone status. (*)
Filters are type, serial, next\-event, auto\-dnssec, transaction, event\-timers.
.TP
\fBzone\-freeze\fP [\fIzone\fP\&...]
Temporarily postpone zone\-changing events (load, refresh, update, flush, and
DNSSEC signing).
......
......@@ -66,9 +66,6 @@ Actions
**zone-memstats** [*zone*...]
Estimate memory use for the zone. (*)
**zone-status** [*zone*...]
Show the zone status. (*)
**zone-reload** [*zone*...]
Trigger a zone reload from a disk without checking its modification time. For
slave zone, the refresh from a master server is scheduled; for master zone,
......@@ -122,6 +119,10 @@ Actions
Show zone statistics counter(s). To print also counters with value 0, use
force option.
**zone-status** *zone* [*filter*]
Show the zone status. (*)
Filters are type, serial, next-event, auto-dnssec, transaction, event-timers.
**zone-freeze** [*zone*...]
Temporarily postpone zone-changing events (load, refresh, update, flush, and
DNSSEC signing).
......
......@@ -16,6 +16,7 @@
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include "knot/common/log.h"
#include "knot/common/stats.h"
......@@ -137,6 +138,43 @@ static int zones_apply(ctl_args_t *args, int (*fcn)(zone_t *, ctl_args_t *))
return ret;
}
typedef enum {
ZONE_STATUS_INVALID = -1,
ZONE_STATUS_NONE = 0,
ZONE_STATUS_TYPE = 1,
ZONE_STATUS_SERIAL,
ZONE_STATUS_NEXT_EVENT,
ZONE_STATUS_AUTO_DNSSEC,
ZONE_STATUS_TRANSACTION,
ZONE_STATUS_EVENT_TIMERS,
} zone_status_param ;
static zone_status_param zone_status_param_check(const char *param)
{
if (param == NULL) {
return ZONE_STATUS_NONE;
}
if (strcmp(param, "type") == 0) {
return ZONE_STATUS_TYPE;
}
if (strcmp(param, "serial") == 0) {
return ZONE_STATUS_SERIAL;
}
if (strcmp(param, "next-event") == 0) {
return ZONE_STATUS_NEXT_EVENT;
}
if (strcmp(param, "auto-dnssec") == 0) {
return ZONE_STATUS_AUTO_DNSSEC;
}
if (strcmp(param, "transaction") == 0) {
return ZONE_STATUS_TRANSACTION;
}
if (strcmp(param, "event-timers") == 0) {
return ZONE_STATUS_EVENT_TIMERS;
}
return ZONE_STATUS_INVALID;
}
static int zone_status(zone_t *zone, ctl_args_t *args)
{
// Zone name.
......@@ -146,108 +184,166 @@ static int zone_status(zone_t *zone, ctl_args_t *args)
}
knot_ctl_data_t data = {
[KNOT_CTL_IDX_ZONE] = name
[KNOT_CTL_IDX_ZONE] = name
};
// Zone type.
data[KNOT_CTL_IDX_TYPE] = "type";
if (zone_is_slave(conf(), zone)) {
data[KNOT_CTL_IDX_DATA] = "slave";
} else {
data[KNOT_CTL_IDX_DATA] = "master";
}
int ret = knot_ctl_send(args->ctl, KNOT_CTL_TYPE_DATA, &data);
if (ret != KNOT_EOK) {
return ret;
zone_status_param param = zone_status_param_check(args->data[KNOT_CTL_IDX_OWNER]);
if (param == ZONE_STATUS_INVALID) {
data[KNOT_CTL_IDX_ERROR] = "Invalid parameters.";
int ret = knot_ctl_send(args->ctl, KNOT_CTL_TYPE_DATA, &data);
if (ret != KNOT_EOK) {
return ret;
}
return KNOT_EINVAL;
}
// Zone serial.
data[KNOT_CTL_IDX_TYPE] = "serial";
int ret;
char buff[128];
if (zone->contents != NULL) {
knot_rdataset_t *soa = node_rdataset(zone->contents->apex,
KNOT_RRTYPE_SOA);
ret = snprintf(buff, sizeof(buff), "%u", knot_soa_serial(soa));
} else {
ret = snprintf(buff, sizeof(buff), "none");
}
if (ret < 0 || ret >= sizeof(buff)) {
return KNOT_ESPACE;
}
knot_ctl_type_t type = KNOT_CTL_TYPE_DATA;
// Zone type.
if (param == ZONE_STATUS_TYPE || param == ZONE_STATUS_NONE) {
data[KNOT_CTL_IDX_TYPE] = "type";
data[KNOT_CTL_IDX_DATA] = buff;
if (zone_is_slave(conf(), zone)) {
data[KNOT_CTL_IDX_DATA] = "slave";
} else {
data[KNOT_CTL_IDX_DATA] = "master";
}
ret = knot_ctl_send(args->ctl, KNOT_CTL_TYPE_EXTRA, &data);
if (ret != KNOT_EOK) {
return ret;
ret = knot_ctl_send(args->ctl, type, &data);
if (ret != KNOT_EOK) {
return ret;
} else {
type = KNOT_CTL_TYPE_EXTRA;
}
}
// Zone serial.
if (param == ZONE_STATUS_SERIAL || param == ZONE_STATUS_NONE) {
data[KNOT_CTL_IDX_TYPE] = "serial";
// Next event.
data[KNOT_CTL_IDX_TYPE] = "next-event";
zone_event_type_t next_type = ZONE_EVENT_INVALID;
time_t next_time = zone_events_get_next(zone, &next_type);
if (next_type != ZONE_EVENT_INVALID) {
const char *next_name = zone_events_get_name(next_type);
next_time = next_time - time(NULL);
if (next_time < 0) {
ret = snprintf(buff, sizeof(buff), "%s pending",
next_name);
if (zone->contents != NULL) {
knot_rdataset_t *soa = node_rdataset(zone->contents->apex,
KNOT_RRTYPE_SOA);
ret = snprintf(buff, sizeof(buff), "%u", knot_soa_serial(soa));
} else {
ret = snprintf(buff, sizeof(buff), "%s in %lldh%lldm%llds",
next_name,
(long long)(next_time / 3600),
(long long)(next_time % 3600) / 60,
(long long)(next_time % 60));
ret = snprintf(buff, sizeof(buff), "none");
}
if (ret < 0 || ret >= sizeof(buff)) {
return KNOT_ESPACE;
}
data[KNOT_CTL_IDX_DATA] = buff;
} else {
data[KNOT_CTL_IDX_DATA] = "idle";
}
ret = knot_ctl_send(args->ctl, KNOT_CTL_TYPE_EXTRA, &data);
if (ret != KNOT_EOK) {
return ret;
ret = knot_ctl_send(args->ctl, type, &data);
if (ret != KNOT_EOK) {
return ret;
} else {
type = KNOT_CTL_TYPE_EXTRA;
}
}
// Next event.
if (param == ZONE_STATUS_NEXT_EVENT || param == ZONE_STATUS_NONE) {
data[KNOT_CTL_IDX_TYPE] = "next-event";
zone_event_type_t next_type = ZONE_EVENT_INVALID;
time_t next_time = zone_events_get_next(zone, &next_type);
if (next_type != ZONE_EVENT_INVALID) {
const char *next_name = zone_events_get_name(next_type);
next_time = next_time - time(NULL);
if (next_time < 0) {
ret = snprintf(buff, sizeof(buff), "%s pending",
next_name);
} else {
ret = snprintf(buff, sizeof(buff), "%s in %lldh%lldm%llds",
next_name,
(long long)(next_time / 3600),
(long long)(next_time % 3600) / 60,
(long long)(next_time % 60));
}
if (ret < 0 || ret >= sizeof(buff)) {
return KNOT_ESPACE;
}
data[KNOT_CTL_IDX_DATA] = buff;
} else {
data[KNOT_CTL_IDX_DATA] = "idle";
}
ret = knot_ctl_send(args->ctl, type, &data);
if (ret != KNOT_EOK) {
return ret;
} else {
type = KNOT_CTL_TYPE_EXTRA;
}
}
// DNSSEC re-signing time.
data[KNOT_CTL_IDX_TYPE] = "auto-dnssec";
if (param == ZONE_STATUS_AUTO_DNSSEC || param == ZONE_STATUS_NONE) {
data[KNOT_CTL_IDX_TYPE] = "auto-dnssec";
conf_val_t val = conf_zone_get(conf(), C_DNSSEC_SIGNING, zone->name);
if (conf_bool(&val)) {
struct tm time_gm = { 0 };
time_t refresh_at = zone_events_get_time(zone, ZONE_EVENT_DNSSEC);
gmtime_r(&refresh_at, &time_gm);
size_t written = strftime(buff, sizeof(buff), KNOT_LOG_TIME_FORMAT,
&time_gm);
if (written == 0) {
return KNOT_ESPACE;
}
conf_val_t val = conf_zone_get(conf(), C_DNSSEC_SIGNING, zone->name);
if (conf_bool(&val)) {
struct tm time_gm = { 0 };
time_t refresh_at = zone_events_get_time(zone, ZONE_EVENT_DNSSEC);
gmtime_r(&refresh_at, &time_gm);
size_t written = strftime(buff, sizeof(buff), KNOT_LOG_TIME_FORMAT,
&time_gm);
if (written == 0) {
return KNOT_ESPACE;
data[KNOT_CTL_IDX_DATA] = buff;
} else {
data[KNOT_CTL_IDX_DATA] = "disabled";
}
data[KNOT_CTL_IDX_DATA] = buff;
} else {
data[KNOT_CTL_IDX_DATA] = "disabled";
ret = knot_ctl_send(args->ctl, type, &data);
if (ret != KNOT_EOK) {
return ret;
} else {
type = KNOT_CTL_TYPE_EXTRA;
}
}
ret = knot_ctl_send(args->ctl, KNOT_CTL_TYPE_EXTRA, &data);
if (ret != KNOT_EOK) {
return ret;
// Zone transaction.
if (param == ZONE_STATUS_TRANSACTION || param == ZONE_STATUS_NONE) {
data[KNOT_CTL_IDX_TYPE] = "transaction";
data[KNOT_CTL_IDX_DATA] = (zone->control_update != NULL) ? "open" : "none";
ret = knot_ctl_send(args->ctl, type, &data);
if (ret != KNOT_EOK) {
return ret;
}
}
// list modules
if (param == ZONE_STATUS_EVENT_TIMERS || param == ZONE_STATUS_NONE) {
time_t ev_time;
for (zone_event_type_t i = 0; i < ZONE_EVENT_COUNT; i++) {
data[KNOT_CTL_IDX_TYPE] = zone_events_get_name(i);
// Zone transaction.
data[KNOT_CTL_IDX_TYPE] = "transaction";
data[KNOT_CTL_IDX_DATA] = (zone->control_update != NULL) ? "open" : "none";
ev_time = zone_events_get_time(zone, i);
ev_time = ev_time - time(NULL);
if (ev_time < 0) {
ret = snprintf(buff, sizeof(buff), "pending");
} else {
ret = snprintf(buff, sizeof(buff), "in %lldh%lldm%llds",
(long long)(ev_time / 3600),
(long long)(ev_time % 3600) / 60,
(long long)(ev_time % 60));
}
if (ret < 0 || ret >= sizeof(buff)) {
return KNOT_ESPACE;
}
data[KNOT_CTL_IDX_DATA] = buff;
return knot_ctl_send(args->ctl, KNOT_CTL_TYPE_EXTRA, &data);
ret = knot_ctl_send(args->ctl, !i? KNOT_CTL_TYPE_DATA : KNOT_CTL_TYPE_EXTRA, &data);
if (ret != KNOT_EOK) {
return ret;
}
type = KNOT_CTL_TYPE_EXTRA;
}
}
return KNOT_EOK;
}
static int zone_reload(zone_t *zone, ctl_args_t *args)
......
......@@ -712,6 +712,7 @@ static int set_node_items(cmd_args_t *args, knot_ctl_data_t *data, char *rdata,
switch (args->desc->cmd) {
case CTL_ZONE_READ:
case CTL_ZONE_GET: min_args = 1; max_args = 3; break;
case CTL_ZONE_STATUS: min_args = 1; max_args = 2; break;
case CTL_ZONE_DIFF: min_args = 1; max_args = 1; break;
case CTL_ZONE_SET: min_args = 3; max_args = -1; break;
case CTL_ZONE_UNSET: min_args = 2; max_args = -1; break;
......@@ -968,7 +969,6 @@ const cmd_desc_t cmd_table[] = {
{ CMD_ZONE_CHECK, cmd_zone_check, CTL_NONE, CMD_FOPT_ZONE | CMD_FREAD },
{ CMD_ZONE_MEMSTATS, cmd_zone_memstats, CTL_NONE, CMD_FOPT_ZONE | CMD_FREAD },
{ CMD_ZONE_STATUS, cmd_zone_ctl, CTL_ZONE_STATUS, CMD_FOPT_ZONE },
{ CMD_ZONE_RELOAD, cmd_zone_ctl, CTL_ZONE_RELOAD, CMD_FOPT_ZONE },
{ CMD_ZONE_REFRESH, cmd_zone_ctl, CTL_ZONE_REFRESH, CMD_FOPT_ZONE },
{ CMD_ZONE_RETRANSFER, cmd_zone_ctl, CTL_ZONE_RETRANSFER, CMD_FOPT_ZONE },
......@@ -987,6 +987,7 @@ const cmd_desc_t cmd_table[] = {
{ CMD_ZONE_UNSET, cmd_zone_node_ctl, CTL_ZONE_UNSET, CMD_FREQ_ZONE },
{ CMD_ZONE_PURGE, cmd_zone_ctl, CTL_ZONE_PURGE, CMD_FREQ_ZONE },
{ CMD_ZONE_STATS, cmd_stats_ctl, CTL_ZONE_STATS, CMD_FREQ_ZONE },
{ CMD_ZONE_STATUS, cmd_zone_node_ctl, CTL_ZONE_STATUS, CMD_FREQ_ZONE },
{ CMD_CONF_INIT, cmd_conf_init, CTL_NONE, CMD_FWRITE },
{ CMD_CONF_CHECK, cmd_conf_check, CTL_NONE, CMD_FREAD },
......@@ -1014,7 +1015,6 @@ static const cmd_help_t cmd_help_table[] = {
{ "", "", "" },
{ CMD_ZONE_CHECK, "[<zone>...]", "Check if the zone can be loaded. (*)" },
{ CMD_ZONE_MEMSTATS, "[<zone>...]", "Estimate memory use for the zone. (*)" },
{ CMD_ZONE_STATUS, "[<zone>...]", "Show the zone status." },
{ CMD_ZONE_RELOAD, "[<zone>...]", "Reload a zone from a disk." },
{ CMD_ZONE_REFRESH, "[<zone>...]", "Force slave zone refresh." },
{ CMD_ZONE_RETRANSFER, "[<zone>...]", "Force slave zone retransfer (no serial check)." },
......@@ -1033,6 +1033,7 @@ static const cmd_help_t cmd_help_table[] = {
{ CMD_ZONE_UNSET, "<zone> <owner> [<type> [<rdata>]]", "Remove zone data within the transaction." },
{ CMD_ZONE_PURGE, "<zone>...", "Purge zone data, file, journal, and timers." },
{ CMD_ZONE_STATS, "<zone> [<module>[.<counter>]]", "Show zone statistics counter(s)."},
{ CMD_ZONE_STATUS, "<zone> [filter]", "Show the zone status." },
{ "", "", "" },
{ CMD_CONF_INIT, "", "Initialize the confdb. (*)" },
{ CMD_CONF_CHECK, "", "Check the server configuration. (*)" },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment