Skip to content

Commit

Permalink
Add support for timezone-utc-offset
Browse files Browse the repository at this point in the history
Some deviations has been done the yang model to comply with tzdata
on linux.
  • Loading branch information
mattiaswal committed Oct 19, 2023
1 parent f383c12 commit 0bb2af7
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/confd/bin/bootstrap
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ sysrepoctl -s $SEARCH \
-i [email protected] -g wheel -p 0660 \
-i [email protected] -g wheel -p 0660 \
-i [email protected] -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 [email protected] -g wheel -p 0660 \
-i [email protected] -g wheel -p 0660 \
-I "${INIT_DATA}"
Expand Down
21 changes: 16 additions & 5 deletions src/confd/src/ietf-system.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -329,13 +331,22 @@ static int change_clock(sr_session_ctx_t *session, uint32_t sub_id, const char *

default:
return SR_ERR_OK;
}

/* XXX: add support also for /ietf-system:system/clock/timezone-utc-offset (deviation) */
}
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) {
ERROR("Failed reading timezone-name");
return SR_ERR_VALIDATION_FAILED;
if (!timezone && !tz_utc_offset) {
snprintf(tz_name,sizeof(tz_name),"Etc/UTC");
timezone = tz_name;
}

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+");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ module infix-system {
contact "[email protected]";
description "Infix augments and deviations to ietf-system.";

revision 2023-10-19 {
description "Add support for timezone-utc-offset
Add deviations for timezone-utc-offset:
- Metric is set to hours (tzdata compatibility)
- Range is -12 .. 14";

reference "internal";
}
revision 2023-08-15 {
description "Add support for user login shell.
Expand Down Expand Up @@ -76,8 +84,13 @@ 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" {
deviate replace {
type int16 {
range "-12 .. 14";
}
units "hours";
}
}

deviation "/sys:system/sys:radius" {
Expand Down
2 changes: 2 additions & 0 deletions test/case/ietf_system/all.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
---
- case: hostname.py
- case: add_delete_user.py
- case: timezone.py
- case: timezone_utc_offset.py
28 changes: 28 additions & 0 deletions test/case/ietf_system/timezone.py
Original file line number Diff line number Diff line change
@@ -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 changes: 27 additions & 0 deletions test/case/ietf_system/timezone_utc_offset.py
Original file line number Diff line number Diff line change
@@ -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()
22 changes: 14 additions & 8 deletions test/infamy/netconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,20 @@ def _ncc_get_data_rpc(self, datastore="operational", filter=None, msg_id=None):
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)

# Fetch the data
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])

return self.ly.parse_data_mem(cfg, "xml", parse_only=True)
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)

def _get_data(self, xpath):
"""Local member wrapper for netconf-client <get-data> RPC"""
Expand All @@ -168,13 +171,16 @@ def _get_data(self, xpath):
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):
"""RPC <get-data> to fetch operational data"""
Expand Down

0 comments on commit 0bb2af7

Please sign in to comment.