confd: Add support for timezone-utc-offset

Some deviations has been done the yang model to comply with tzdata
on linux.

This fixes #106
This commit is contained in:
Mattias Walström
2023-10-20 12:55:02 +02:00
committed by Joachim Wiberg
parent 0db65846c3
commit d66740250c
7 changed files with 113 additions and 22 deletions
+1 -1
View File
@@ -160,7 +160,7 @@ sysrepoctl -s $SEARCH \
-i infix-lldp@2023-08-23.yang -g wheel -p 0660 \
-i infix-dhcp-client@2023-05-22.yang -g wheel -p 0660 \
-i infix-shell-type@2023-08-21.yang -g wheel -p 0660 \
-i infix-system@2023-08-15.yang -g wheel -p 0660 \
-i infix-system@2023-10-19.yang -g wheel -p 0660 \
-i infix-services@2023-10-16.yang -g wheel -p 0660 \
-i ieee802-ethernet-interface@2019-06-21.yang -g wheel -p 0660 \
-I "${INIT_DATA}"
+14 -5
View File
@@ -301,6 +301,8 @@ static int change_clock(sr_session_ctx_t *session, uint32_t sub_id, const char *
const char *xpath, sr_event_t event, unsigned request_id, void *priv)
{
char *timezone;
char *tz_utc_offset;
char tz_name[14];
switch (event) {
case SR_EV_ENABLED: /* first time, on register. */
@@ -329,13 +331,20 @@ static int change_clock(sr_session_ctx_t *session, uint32_t sub_id, const char *
default:
return SR_ERR_OK;
}
tz_utc_offset = srx_get_str(session, XPATH_BASE_"/clock/timezone-utc-offset");
timezone = srx_get_str(session, XPATH_BASE_"/clock/timezone-name");
if (!timezone && !tz_utc_offset) {
snprintf(tz_name,sizeof(tz_name),"Etc/UTC");
timezone = tz_name;
}
/* XXX: add support also for /ietf-system:system/clock/timezone-utc-offset (deviation) */
timezone = srx_get_str(session, XPATH_BASE_"/clock/timezone-name");
if (!timezone) {
ERROR("Failed reading timezone-name");
return SR_ERR_VALIDATION_FAILED;
if (tz_utc_offset) {
int8_t offset = atol(tz_utc_offset);
/* When using Etc/GMT offsets, the +/- is inverted in tzdata. */
snprintf(tz_name,sizeof(tz_name), "Etc/GMT%s%.2d", offset>-1?"":"+", -offset);
timezone = tz_name;
}
remove("/etc/localtime+");
@@ -19,6 +19,13 @@ module infix-system {
contact "kernelkit@googlegroups.com";
description "Infix augments and deviations to ietf-system.";
revision 2023-10-19 {
description "Change deviation for timezone-utc-offset from unsupported to Etc+/-HOUR
- Unit is set to hours (tzdata compatibility)
- Range is -12 .. 14";
reference "internal";
}
revision 2023-08-15 {
description "Add support for user login shell.
@@ -76,8 +83,14 @@ module infix-system {
}
}
deviation "/sys:system/sys:clock/sys:timezone/sys:timezone-utc-offset" {
deviate not-supported;
deviation "/sys:system/sys:clock/sys:timezone/sys:timezone-utc-offset/sys:timezone-utc-offset" {
description "Timezone UTC offset should be set in hours, not minutes";
deviate replace {
type int16 {
range "-12 .. 14";
}
units "hours";
}
}
deviation "/sys:system/sys:radius" {
+2
View File
@@ -1,3 +1,5 @@
---
- case: hostname.py
- case: add_delete_user.py
- case: timezone.py
- case: timezone_utc_offset.py
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env python3
import random, string
import time
import infamy
import lxml
with infamy.Test() as test:
with test.step("Initialize"):
env = infamy.Env(infamy.std_topology("1x1"))
target = env.attach("target", "mgmt")
with test.step("Set timezone"):
target.put_config_dict("ietf-system", {
"system": {
"clock": {
"timezone-name": "Australia/Perth" # always +8:00, no DTS
}
}
})
with test.step("Verify current time."):
root = target.get_dict("/ietf-system:system-state/clock",as_xml=True)
current_datetime = root.find('.//{urn:ietf:params:xml:ns:yang:ietf-system}current-datetime').text
offset=current_datetime[-6:]
assert(offset == "+08:00")
test.succeed()
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env python3
import infamy
import lxml
with infamy.Test() as test:
with test.step("Initialize"):
env = infamy.Env(infamy.std_topology("1x1"))
target = env.attach("target", "mgmt")
with test.step("Set timezone UTC offset"):
target.put_config_dict("ietf-system", {
"system": {
"clock": {
"timezone-utc-offset": "12"
}
}
})
with test.step("Verify current time."):
root = target.get_dict("/ietf-system:system-state/clock",as_xml=True)
current_datetime = root.find('.//{urn:ietf:params:xml:ns:yang:ietf-system}current-datetime').text
offset=current_datetime[-6:]
assert(offset == "+12:00")
test.succeed()
+26 -14
View File
@@ -147,7 +147,7 @@ class Device(object):
pieces.append("</get-data>")
return self._ncc_make_rpc("".join(pieces), msg_id=msg_id)
def _get(self, xpath, getter):
def _get(self, xpath, getter, as_xml=False):
# Figure out which modules we are referencing
mods = self._modules_in_xpath(xpath)
@@ -155,30 +155,42 @@ class Device(object):
xmlns = " ".join([f"xmlns:{m['name']}=\"{m['namespace']}\"" for m in mods])
filt = f"<filter type=\"xpath\" select=\"{xpath}\" {xmlns} />"
# pylint: disable=c-extension-no-member
cfg = lxml.etree.tostring(getter(filter=filt).data_ele[0])
data=getter(filter=filt).data_ele[0]
if as_xml:
return data
else:
cfg = lxml.etree.tostring(data)
return self.ly.parse_data_mem(cfg, "xml", parse_only=True)
return self.ly.parse_data_mem(cfg, "xml", parse_only=True)
def _get_data(self, xpath):
def _get_data(self, xpath,as_xml=False):
"""Local member wrapper for netconf-client <get-data> RPC"""
# pylint: disable=protected-access
(raw, ele) = self.ncc._send_rpc(self._ncc_get_data_rpc(filter=xpath))
data = NccGetDataReply(raw, ele)
# pylint: disable=c-extension-no-member
cfg = lxml.etree.tostring(data.data_ele[0])
return self.ly.parse_data_mem(cfg, "xml", parse_only=True)
if(as_xml):
return data
else:
# pylint: disable=c-extension-no-member
cfg = lxml.etree.tostring(data.data_ele[0])
return self.ly.parse_data_mem(cfg, "xml", parse_only=True)
def get(self, xpath):
def get(self, xpath, as_xml=False):
"""RPC <get> (legacy NETCONF) fetches config:false data"""
return self._get(xpath, self.ncc.get)
return self._get(xpath, self.ncc.get, as_xml)
def get_dict(self, xpath):
def get_dict(self, xpath,as_xml=False):
"""Return Python dictionary of <get> RPC data"""
return self.get(xpath).print_dict()
if(as_xml):
return self.get(xpath, as_xml=True)
else:
return self.get(xpath).print_dict()
def get_data(self, xpath):
def get_data(self, xpath, as_xml=False):
"""RPC <get-data> to fetch operational data"""
return self._get_data(xpath).print_dict()
if(as_xml):
return self._get_data(xpath,as_xml)
else:
return self._get_data(xpath).print_dict()
def get_config(self, xpath):
return self._get(xpath, self.ncc.get_config)