From d24ffc5bcea4af195b2b43425777024ff3a57f3c Mon Sep 17 00:00:00 2001 From: Jimmy Jin Date: Fri, 12 Dec 2025 12:47:21 -0800 Subject: [PATCH 1/9] Add following openconfig optical yang models with annotation yang, sonic yang and transformer functions: - openconfig-optical-attenuator.yang, openconfig-opticalamplifier.yang and openconfig-channel-monitor.yang --- .../openconfig-channel-monitor-annot.yang | 122 ++++ .../openconfig-optical-amplifier-annot.yang | 401 +++++++++++++ .../openconfig-optical-attenuator-annot.yang | 154 +++++ .../openconfig-transport-line-common.yang | 314 ++++++++++ models/yang/openconfig-channel-monitor.yang | 354 ++++++++++++ models/yang/openconfig-optical-amplifier.yang | 544 ++++++++++++++++++ .../yang/openconfig-optical-attenuator.yang | 233 ++++++++ models/yang/sonic/sonic-channel-monitor.yang | 44 ++ .../yang/sonic/sonic-optical-amplifier.yang | 129 +++++ .../yang/sonic/sonic-optical-attenuator.yang | 70 +++ translib/transformer/xfmr_otn_openconfig.go | 216 +++++++ 11 files changed, 2581 insertions(+) create mode 100644 models/yang/annotations/openconfig-channel-monitor-annot.yang create mode 100644 models/yang/annotations/openconfig-optical-amplifier-annot.yang create mode 100644 models/yang/annotations/openconfig-optical-attenuator-annot.yang create mode 100644 models/yang/common/openconfig-transport-line-common.yang create mode 100644 models/yang/openconfig-channel-monitor.yang create mode 100644 models/yang/openconfig-optical-amplifier.yang create mode 100644 models/yang/openconfig-optical-attenuator.yang create mode 100644 models/yang/sonic/sonic-channel-monitor.yang create mode 100644 models/yang/sonic/sonic-optical-amplifier.yang create mode 100644 models/yang/sonic/sonic-optical-attenuator.yang create mode 100644 translib/transformer/xfmr_otn_openconfig.go diff --git a/models/yang/annotations/openconfig-channel-monitor-annot.yang b/models/yang/annotations/openconfig-channel-monitor-annot.yang new file mode 100644 index 000000000..9448af936 --- /dev/null +++ b/models/yang/annotations/openconfig-channel-monitor-annot.yang @@ -0,0 +1,122 @@ +module openconfig-channel-monitor-annot { + + yang-version "1"; + + namespace "http://openconfig.net/yang/annotation/oc-chan-monitor-annot"; + prefix "oc-chan-monitor-annot"; + + import openconfig-extensions { prefix oc-ext; } + import openconfig-transport-types { prefix oc-opt-types; } + import openconfig-channel-monitor { prefix oc-chan-monitor; } + + deviation /oc-chan-monitor:channel-monitors { + deviate add { + sonic-ext:table-name "OTN_OCM"; + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor { + deviate add { + sonic-ext:key-transformer "oc_name_key_xfmr"; + sonic-ext:table-transformer "otn_table_xfmr"; + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:config { + deviate add { + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:config/oc-chan-monitor:monitor-port { + deviate add { + sonic-ext:field-name "monitor-port"; + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:config/oc-chan-monitor:name { + deviate add { + sonic-ext:field-transformer "oc_name_field_xfmr"; + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OTN_OCM_TABLE"; + sonic-ext:key-transformer "oc_name_key_xfmr"; + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:state/oc-chan-monitor:monitor-port { + deviate add { + sonic-ext:field-name "monitor-port"; + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:state/oc-chan-monitor:name { + deviate add { + sonic-ext:field-transformer "oc_name_field_xfmr"; + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels { + deviate add { + sonic-ext:table-transformer "otn_table_xfmr"; + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OTN_OCM_CHANNEL_TABLE"; + sonic-ext:table-transformer "otn_table_xfmr"; + sonic-ext:key-transformer "ocm_channel_key_xfmr"; + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:lower-frequency { + deviate add { + sonic-ext:field-name "lower-frequency"; + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:upper-frequency { + deviate add { + sonic-ext:field-name "upper-frequency"; + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state { + deviate add { + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state/oc-chan-monitor:upper-frequency { + deviate add { + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state/oc-chan-monitor:power { + deviate add { + sonic-ext:field-name "power"; + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state/oc-chan-monitor:target-power { + deviate add { + sonic-ext:field-name "target-power"; + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state/oc-chan-monitor:lower-frequency { + deviate add { + } + } + + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:name { + deviate add { + } + } + +} + diff --git a/models/yang/annotations/openconfig-optical-amplifier-annot.yang b/models/yang/annotations/openconfig-optical-amplifier-annot.yang new file mode 100644 index 000000000..0061ef5aa --- /dev/null +++ b/models/yang/annotations/openconfig-optical-amplifier-annot.yang @@ -0,0 +1,401 @@ +module openconfig-optical-amplifier-annot { + + yang-version "1"; + + namespace "http://openconfig.net/yang/annotation/oc-opt-amp-annot"; + prefix "oc-opt-amp-annot"; + + import sonic-extensions { prefix sonic-ext; } + import openconfig-optical-amplifier { prefix oc-opt-amp; } + + deviation /oc-opt-amp:optical-amplifier { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers { + deviate add { + sonic-ext:table-name "OTN_OA"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier { + deviate add { + sonic-ext:key-transformer "oc_name_key_xfmr"; + sonic-ext:table-transformer "otn_table_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:name { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:name { + deviate add { + sonic-ext:field-transformer "oc_name_field_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:type { + deviate add { + sonic-ext:field-name "type"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:target-gain { + deviate add { + sonic-ext:field-name "target-gain"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:min-gain { + deviate add { + sonic-ext:field-name "min-gain"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:max-gain { + deviate add { + sonic-ext:field-name "max-gain"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:target-gain-tilt { + deviate add { + sonic-ext:field-name "target-gain-tilt"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:gain-range { + deviate add { + sonic-ext:field-name "gain-range"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:amp-mode { + deviate add { + sonic-ext:field-name "amp-mode"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:target-output-power { + deviate add { + sonic-ext:field-name "target-output-power"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:max-output-power { + deviate add { + sonic-ext:field-name "max-output-power"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:enabled { + deviate add { + sonic-ext:field-name "enabled"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:fiber-type-profile { + deviate add { + sonic-ext:field-name "fiber-type-profile"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OTN_OA_TABLE"; + sonic-ext:key-transformer "oc_name_key_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:name { + deviate add { + sonic-ext:field-transformer "oc_name_field_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:type { + deviate add { + sonic-ext:field-name "type"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:target-gain { + deviate add { + sonic-ext:field-name "target-gain"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:min-gain { + deviate add { + sonic-ext:field-name "min-gain"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:max-gain { + deviate add { + sonic-ext:field-name "max-gain"; + } + } + + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:target-gain-tilt { + deviate add { + sonic-ext:field-name "target-gain-tilt"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:gain-range { + deviate add { + sonic-ext:field-name "gain-range"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:amp-mode { + deviate add { + sonic-ext:field-name "amp-mode"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:target-output-power { + deviate add { + sonic-ext:field-name "target-output-power"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:max-output-power { + deviate add { + sonic-ext:field-name "max-output-power"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:enabled { + deviate add { + sonic-ext:field-name "enabled"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:fiber-type-profile { + deviate add { + sonic-ext:field-name "fiber-type-profile"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:component { + deviate add { + sonic-ext:field-name "component"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:ingress-port { + deviate add { + sonic-ext:field-name "ingress-port"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:egress-port { + deviate add { + sonic-ext:field-name "egress-port"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "actual-gain"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain-tilt { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain-tilt/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "actual-gain-tilt"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-total { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-total/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "input-power-total"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-c-band { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-c-band/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "input-power-c-band"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-l-band { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-l-band/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "input-power-l-band"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-total { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-total/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "output-power-total"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-c-band { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-c-band/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "output-power-c-band"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-l-band { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-l-band/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "output-power-l-band"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:laser-bias-current { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "laser-bias-current"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:optical-return-loss { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:optical-return-loss/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "optical-return-loss"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels { + deviate add { + sonic-ext:table-name "OTN_OSC"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel { + deviate add { + sonic-ext:key-transformer "osc_key_xfmr"; + sonic-ext:table-transformer "otn_table_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:interface { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:config { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:config/oc-opt-amp:interface { + deviate add { + sonic-ext:field-transformer "osc_interface_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OTN_OSC_TABLE"; + sonic-ext:key-transformer "osc_key_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:interface { + deviate add { + sonic-ext:field-transformer "osc_interface_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:input-power { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:input-power/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "input-power"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-power { + deviate add { + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-power/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "output-power"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:laser-bias-current { + deviate add { + } + } + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "laser-bias-current"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-frequency { + deviate add { + sonic-ext:field-name "output-frequency"; + } + } + +} diff --git a/models/yang/annotations/openconfig-optical-attenuator-annot.yang b/models/yang/annotations/openconfig-optical-attenuator-annot.yang new file mode 100644 index 000000000..c7d0bbd06 --- /dev/null +++ b/models/yang/annotations/openconfig-optical-attenuator-annot.yang @@ -0,0 +1,154 @@ +module openconfig-optical-attenuator-annot { + + yang-version "1"; + + namespace "http://openconfig.net/yang/annotation/oc-opt-att-annot"; + prefix "oc-opt-att-annot"; + + import sonic-extensions { prefix sonic-ext; } + import openconfig-optical-attenuator { prefix oc-opt-att; } + + deviation /oc-opt-att:optical-attenuator { + deviate add { + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators { + deviate add { + sonic-ext:table-name "OTN_ATTENUATOR"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator { + deviate add { + sonic-ext:key-transformer "oc_name_key_xfmr"; + sonic-ext:table-transformer "otn_table_xfmr"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config { + deviate add { + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:name { + deviate add { + sonic-ext:field-transformer "oc_name_field_xfmr"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:attenuation-mode { + deviate add { + sonic-ext:field-name "attenuation-mode"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:target-output-power { + deviate add { + sonic-ext:field-name "target-output-power"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:attenuation { + deviate add { + sonic-ext:field-name "attenuation"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:enabled { + deviate add { + sonic-ext:field-name "enabled"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OTN_ATTENUATOR_TABLE"; + sonic-ext:key-transformer "oc_name_key_xfmr"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:name { + deviate add { + sonic-ext:field-transformer "oc_name_field_xfmr"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:attenuation-mode { + deviate add { + sonic-ext:field-name "attenuation-mode"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:target-output-power { + deviate add { + sonic-ext:field-name "target-output-power"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:attenuation { + deviate add { + sonic-ext:field-name "attenuation"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:enabled { + deviate add { + sonic-ext:field-name "enabled"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:component { + deviate add { + sonic-ext:field-name "component"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:ingress-port { + deviate add { + sonic-ext:field-name "ingress-port"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:egress-port { + deviate add { + sonic-ext:field-name "egress-port"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:actual-attenuation { + deviate add { + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:actual-attenuation/oc-opt-att:instant { + deviate add { + sonic-ext:field-name "actual-attenuation"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:output-power-total { + deviate add { + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:output-power-total/oc-opt-att:instant { + deviate add { + sonic-ext:field-name "output-power-total"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:optical-return-loss { + deviate add { + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:optical-return-loss/oc-opt-att:instant { + deviate add { + sonic-ext:field-name "optical-return-loss"; + } + } + +} + diff --git a/models/yang/common/openconfig-transport-line-common.yang b/models/yang/common/openconfig-transport-line-common.yang new file mode 100644 index 000000000..09c9c3855 --- /dev/null +++ b/models/yang/common/openconfig-transport-line-common.yang @@ -0,0 +1,314 @@ +module openconfig-transport-line-common { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/transport-line-common"; + + prefix "oc-line-com"; + + // import some basic types +//import iana-if-type { prefix ianaift; } + import openconfig-extensions { prefix oc-ext; } +//import openconfig-interfaces { prefix oc-if; } + import openconfig-platform { prefix oc-platform; } + import openconfig-types { prefix oc-types; } + import openconfig-transport-types { prefix oc-opt-types; } +//import openconfig-platform-transceiver { prefix oc-transceiver; } + + + // meta + organization "OpenConfig working group"; + + contact + "OpenConfig working group + www.openconfig.net"; + + description + "This module defines common data elements for OpenConfig data + models for optical transport line system elements, such as + amplifiers and ROADMs (wavelength routers)."; + + oc-ext:openconfig-version "0.6.0"; + + revision "2019-06-03" { + description + "Add state leaf 'tilt' to optical-port"; + reference "0.6.0"; + } + + revision "2019-04-16" { + description + "Update import prefix for iana-if-type module"; + reference "0.5.2"; + } + + revision "2018-11-21" { + description + "Add OpenConfig module metadata extensions."; + reference "0.4.2"; + } + + revision "2018-07-17" { + description + "Remove leaf 'enabled' from osc-config"; + reference "0.4.1"; + } + + revision "2018-05-08" { + description + "Added leaf 'enabled' to osc-config and + leaf 'output-frequency' to osc-state"; + reference "0.4.0"; + } + + revision "2017-09-08" { + description + "Correct bug with OSC interfaces"; + reference "0.3.1"; + } + + revision "2017-07-08" { + description + "Add monitor port type and refs to hw ports, "; + reference "0.3.0"; + } + + revision "2017-03-28" { + description + "Added min/max/avg stats, status for media channels, OCM, APS"; + reference "0.2.0"; + } + + revision "2016-03-31" { + description + "Initial public release"; + reference "0.1.0"; + } + + // OpenConfig specific extensions for module metadata. + oc-ext:regexp-posix; + oc-ext:catalog-organization "openconfig"; + oc-ext:origin "openconfig"; + + // extension statements + + // feature statements + + // identity statements + + // typedef statements + + // grouping statements + + grouping optical-osc-config { + description + "Configuration data for OSC interfaces"; + + leaf interface { + type string; + //type oc-if:base-interface-ref; + description + "Reference to an OSC interface"; + } + } + + grouping optical-osc-state { + description + "Operational state data for OSC interfaces"; + + container input-power { + description + "The input optical power of this port in units + of 0.01dBm. If avg/min/max statistics are not supported, + the target is expected to just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container output-power { + description + "The output optical power of this port in units + of 0.01dBm. If avg/min/max statistics are not supported, + the target is expected to just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container laser-bias-current { + description + "The current applied by the system to the transmit laser to + achieve the output power. The current is expressed in mA + with up to one decimal precision. If avg/min/max statistics + are not supported, the target is expected to just supply + the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-mA; + } + + //OPLINK: use output-frequncy directly. avoid another level of import. + // uses oc-transceiver:output-optical-frequency; + leaf output-frequency { + type oc-opt-types:frequency-type; + description + "The frequency in MHz of the individual physical channel + (e.g. ITU C50 - 195.0THz and would be reported as + 195,000,000 MHz in this model). This attribute is not + configurable on most client ports."; + } + } + + + + grouping optical-osc-top { + description + "Top-level grouping for configuration and operational state + data for optical supervisory channels (OSC) for amplifiers, + WSS/ROADM, nodes, etc."; + + container config { + description + "Configuration data for OSCs"; + + uses optical-osc-config; + } + + container state { + + config false; + + description + "Operational state data for OSCs"; + + uses optical-osc-config; + uses optical-osc-state; + } + } + + + grouping transport-line-common-port-config { + description + "Configuration data for optical line ports"; + + leaf admin-state { + type oc-opt-types:admin-state-type; + description + "Sets the admin state of the optical-port"; + } + } + + grouping transport-line-common-port-state { + description + "Operational state data describing optical line ports"; + + leaf optical-port-type { + type identityref { + base oc-opt-types:OPTICAL_PORT_TYPE; + } + description + "For physical ports belonging to optical transport + devices, this indicates the type of optical port. This is an + informational field that should be made available by the + device."; + } + + leaf tilt { + type decimal64 { + fraction-digits 2; + } + units dB; + description + "The total tilt measured on the port. This is applicable to + ports of type INGRESS and EGRESS."; + } + + container input-power { + description + "For line system device ports, this value indicates + the total input optical power of the port in units + of 0.01dBm. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container output-power { + description + "For line system device ports, this value indicates + the total output optical power of the port in units + of 0.01dBm. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + } + + grouping transport-line-common-port-top { + description + "Top-level grouping for optical port data"; + + container optical-port { + description + "Contains data specific to ports on optical transport + devices."; + + container config { + + description + "Operational config data for optical ports"; + + uses transport-line-common-port-config; + } + + container state { + + config false; + + description + "Operational state data for optical ports"; + + uses transport-line-common-port-config; + uses transport-line-common-port-state; + } + } + } + + + + // data definition statements + + // uses optical-osc-top; + + // augment statements + + augment "/oc-platform:components/oc-platform:component" + + "/oc-platform:port" { + description + "Adding optical port data to platform components model"; + + uses transport-line-common-port-top; + } + +/***** OPLINK - not used for now + //TODO:this is placeholder until SONET model is added + //to interfaces model + augment "/oc-if:interfaces/oc-if:interface" { + when "oc-if:config/oc-if:type = 'ianaift:sonet'" { + description "Additional interface configuration parameters when + the interface type is SONET/SDH"; + } + description "Adds additional SONET/SDH-specific data to + osc model"; + + container sonet { + description + "Data related to SONET/SDH interfaces"; + } + } +*****/ + + // rpc statements + + // notification statements + +} diff --git a/models/yang/openconfig-channel-monitor.yang b/models/yang/openconfig-channel-monitor.yang new file mode 100644 index 000000000..3623681c6 --- /dev/null +++ b/models/yang/openconfig-channel-monitor.yang @@ -0,0 +1,354 @@ +module openconfig-channel-monitor { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/channel-monitor"; + + prefix "oc-chan-monitor"; + + // import some basic types + import openconfig-extensions { prefix oc-ext; } + import openconfig-interfaces { prefix oc-if; } + import openconfig-platform { prefix oc-platform; } + import openconfig-transport-types { prefix oc-opt-types; } + + + // meta + organization "OpenConfig working group"; + + contact + "OpenConfig working group + www.openconfig.net"; + + description + "This model describes operational state data for an optical + channel monitor (OCM) for optical transport line system + elements such as wavelength routers (ROADMs) and amplifiers."; + + oc-ext:openconfig-version "0.5.0"; + + revision "2024-04-04" { + description + "Add new leaf media-channel target-power."; + reference "0.5.0"; + } + + revision "2019-10-24" { + description + "Migrate from using power spectral densisty to using power + target values"; + reference "0.4.0"; + } + + revision "2018-11-21" { + description + "Add OpenConfig module metadata extensions."; + reference "0.3.2"; + } + + revision "2017-09-08" { + description + "Correct bug with OSC interfaces"; + reference "0.3.1"; + } + + revision "2017-07-08" { + description + "Support multiple OCMs, add refs to hw ports, "; + reference "0.3.0"; + } + + revision "2017-03-28" { + description + "Added min/max/avg stats, status for media channels, OCM, APS"; + reference "0.2.0"; + } + + revision "2016-09-14" { + description + "Initial revision"; + reference "0.1.0"; + } + + // OpenConfig specific extensions for module metadata. + oc-ext:regexp-posix; + oc-ext:catalog-organization "openconfig"; + oc-ext:origin "openconfig"; + + // grouping statements + + grouping media-channel-port-config { + description + "Configuration data for a media channel source/dest port"; + + leaf port-name { + type oc-if:base-interface-ref; + description + "Reference to the corresponding node interface"; + } + } + + grouping media-channel-port-state { + description + "Operational state data for a media channel source/dest port"; + } + + grouping media-channel-source-port-top { + description + "Top-level grouping for source of the media channel"; + + container source { + description + "Top-level container for media channel source"; + + container config { + description + "Configuration data for the media channel source"; + + uses media-channel-port-config; + } + + container state { + + config false; + + description + "Operational state data for the media channel source"; + + uses media-channel-port-config; + uses media-channel-port-state; + } + } + } + + grouping media-channel-dest-port-top { + description + "Top-level grouping for destination of the media channel"; + + container dest { + description + "Top-level container for media channel destination"; + + container config { + description + "Configuration data for the media channel destination"; + + uses media-channel-port-config; + } + + container state { + + config false; + + description + "Operational state data for the media channel destination"; + + uses media-channel-port-config; + uses media-channel-port-state; + } + } + } + + grouping media-channel-spectrum-power-state { + description + "Operational state data for the media channel spectrum power"; + + leaf lower-frequency { + type oc-opt-types:frequency-type; + description + "Lower frequency of the specified spectrum power"; + } + + leaf upper-frequency { + type oc-opt-types:frequency-type; + description + "Upper frequency of the specified spectrum power"; + } + + leaf power { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "Average measured optical power over the specified spectrum"; + } + + leaf target-power { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "Target optical power over the specified spectrum"; + } + } + + grouping media-channel-spectrum-power-top { + description + "Top-level grouping "; + + container channels { + description + "Enclosing container for the list of values describing + the spectrum power distribution"; + + list channel { + key "lower-frequency upper-frequency"; + config false; + description + "List of tuples describing the spectrum power distribution"; + + leaf lower-frequency { + type leafref { + path "../state/lower-frequency"; + } + description + "Reference to the list key"; + } + + leaf upper-frequency { + type leafref { + path "../state/upper-frequency"; + } + description + "Reference to the list key"; + } + + + container state { + + config false; + + description + "Operational state data for spectrum power"; + + uses media-channel-spectrum-power-state; + } + } + } + } + + grouping media-channel-config { + description + "Configuration data for media channel definitions"; + + leaf index { + type uint32; + description + "Identifier for the defined media channel"; + } + + leaf lower-frequency { + type oc-opt-types:frequency-type; + description + "The lower frequency for the spectrum defined by this media + channel"; + } + + leaf upper-frequency { + type oc-opt-types:frequency-type; + description + "The upper frequency for the spectrum defined by this media + channel"; + } + + } + + grouping channel-monitor-config { + description + "Configuration data for the optical channel monitor"; + + leaf name { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "Reference to system-supplied name of the port on the + optical channel monitor (OCM). If this port is embedded + in another card (i.e. an amplifier card) the device + should still define a port representing the OCM even if + it is internal and not physically present on the + faceplate of the card"; + } + + leaf monitor-port { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "Reference to system-supplied name of the port that the + channel monitor is physically connected to. This port + will be of type MONITOR. This port is a tap off of the + monitored-port and would be in the same card as the + monitored port. If this port is embedded in another card + (i.e. an amplifier card) the device should still define + a port representing the monitor port if it is internal + and not physically present on the faceplate of the card"; + } + } + + grouping channel-monitor-state { + description + "Operational state data "; + } + + grouping channel-monitor-top { + description + "Top-level grouping "; + + container channel-monitors { + description + "Top-level container for optical channel monitors"; + + list channel-monitor { + key "name"; + description + "List of channel monitors, keyed by channel monitor name."; + + leaf name { + type leafref { + path "../config/name"; + } + description + "References the optical channel monitor name"; + } + + container config { + description + "Configuration data "; + + uses channel-monitor-config; + } + + container state { + + config false; + + description + "Operational state data "; + + uses channel-monitor-config; + uses channel-monitor-state; + } + + uses media-channel-spectrum-power-top; + } + } + } + + // data definition statements + + uses channel-monitor-top; + + + // augment statements + + // rpc statements + + // notification statements + +} diff --git a/models/yang/openconfig-optical-amplifier.yang b/models/yang/openconfig-optical-amplifier.yang new file mode 100644 index 000000000..08e829356 --- /dev/null +++ b/models/yang/openconfig-optical-amplifier.yang @@ -0,0 +1,544 @@ +module openconfig-optical-amplifier { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/optical-amplfier"; + + prefix "oc-opt-amp"; + + import openconfig-platform { prefix oc-platform; } + import openconfig-transport-line-common { prefix oc-line-com; } + import openconfig-types { prefix oc-types; } + import openconfig-extensions { prefix oc-ext; } + + + // meta + organization "OpenConfig working group"; + + contact + "OpenConfig working group + www.openconfig.net"; + + description + "This model describes configuration and operational state data + for optical amplifiers, deployed as part of a transport + line system."; + + oc-ext:openconfig-version "0.5.0"; + + revision "2019-12-06" { + description + "Add DYNAMIC_GAIN mode and related leaves."; + reference "0.5.0"; + } + + revision "2018-11-21" { + description + "Add OpenConfig module metadata extensions."; + reference "0.4.1"; + } + + revision "2017-10-02" { + description + "Add support for fiber type profile and physical component + association for amplifier gain blocks."; + reference "0.4.0"; + } + + revision "2017-09-08" { + description + "Correct bug with OSC interfaces"; + reference "0.3.1"; + } + + revision "2017-07-08" { + description + "Add monitor port type and refs to hw ports, "; + reference "0.3.0"; + } + + revision "2017-03-28" { + description + "Added min/max/avg stats, status for media channels, OCM, APS"; + reference "0.2.0"; + } + + revision "2016-03-31" { + description + "Initial public release"; + reference "0.1.0"; + } + + // OpenConfig specific extensions for module metadata. + oc-ext:regexp-posix; + oc-ext:catalog-organization "openconfig"; + oc-ext:origin "openconfig"; + + + // extension statements + + // feature statements + + // identity statements + + identity OPTICAL_AMPLIFIER_TYPE { + description + "Type definition for different types of optical amplifiers"; + } + + identity EDFA { + base OPTICAL_AMPLIFIER_TYPE; + description + "Erbium doped fiber amplifer (EDFA)"; + } + + identity FORWARD_RAMAN { + base OPTICAL_AMPLIFIER_TYPE; + description + "Forward pumping Raman amplifier"; + } + + identity BACKWARD_RAMAN { + base OPTICAL_AMPLIFIER_TYPE; + description + "Backward pumping Raman amplifier"; + } + + identity HYBRID { + base OPTICAL_AMPLIFIER_TYPE; + description + "Hybrid backward pumping Raman + EDFA amplifier"; + } + + identity GAIN_RANGE { + description + "Base type for expressing the gain range for a switched gain + amplifier. The gain range is expressed as a generic setting, + e.g., LOW/MID/HIGH. The actual db range will be determined + by the implementation."; + } + + identity LOW_GAIN_RANGE { + base GAIN_RANGE; + description + "LOW gain range setting"; + } + + identity MID_GAIN_RANGE { + base GAIN_RANGE; + description + "MID gain range setting"; + } + + identity HIGH_GAIN_RANGE { + base GAIN_RANGE; + description + "HIGH gain range setting"; + } + + identity FIXED_GAIN_RANGE { + base GAIN_RANGE; + description + "Fixed or non-switched gain amplfier"; + } + + identity OPTICAL_AMPLIFIER_MODE { + description + "Type definition for different types of optical amplifier + operating modes"; + } + + identity CONSTANT_POWER { + base OPTICAL_AMPLIFIER_MODE; + description + "Constant power mode. In constant power mode, the amplifier + will maintain a constant output power by adjusting the + amplifier gain and/or related variable optical attenuators"; + } + + identity CONSTANT_GAIN { + base OPTICAL_AMPLIFIER_MODE; + description + "Constant gain mode. In constant gain mode, the amplifier + will maintain a constant amplifier gain"; + } + + identity DYNAMIC_GAIN { + base OPTICAL_AMPLIFIER_MODE; + description + "Dynamic gain mode. In dynamic gain mode, the amplifier will + automatically adjust gain to stay within parameters defined + by: + - target-gain + - min-gain + - max-gain"; + } + + identity FIBER_TYPE_PROFILE { + description + "Type definition for different profiles of fiber types"; + } + + identity DSF { + base FIBER_TYPE_PROFILE; + description + "Dispersion shifted fiber"; + } + + identity LEAF { + base FIBER_TYPE_PROFILE; + description + "Large effective area fiber"; + } + + identity SSMF { + base FIBER_TYPE_PROFILE; + description + "Standard single mode fiber"; + } + + identity TWC { + base FIBER_TYPE_PROFILE; + description + "True wave classic"; + } + + identity TWRS { + base FIBER_TYPE_PROFILE; + description + "True wave reduced slope"; + } + + // grouping statements + + grouping optical-amplifier-config { + description + "Configuration data for optical amplifiers"; + + leaf name { + type string; + description + "User-defined name assigned to identify a specific amplifier + in the device"; + } + + leaf type { + type identityref { + base OPTICAL_AMPLIFIER_TYPE; + } + description + "Type of the amplifier"; + } + + leaf target-gain { + type decimal64 { + fraction-digits 2; + range 0..max; + } + units dB; + description + "Positive gain applied by the amplifier. This is used + when the amp-mode is in CONSTANT_GAIN or DYNAMIC_GAIN + mode to set the target gain that the amplifier should + achieve."; + } + + leaf min-gain { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "The minimum allowed gain of the amplifier. This is used + when the amp-mode is in CONSTANT_POWER or DYNAMIC_GAIN mode + to prevent the gain from dropping below a desired threshold. + If left empty, the platform will apply a minimum gain based + on hardware specifications."; + } + + leaf max-gain { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "The maximum allowed gain of the amplifier. This is used + when the amp-mode is in CONSTANT_POWER or DYNAMIC_GAIN mode + to prevent the gain from exceeding a desired threshold. If + left empty, the platform will apply a maximum gain based on + hardware specifications."; + } + + leaf target-gain-tilt { + type decimal64 { + fraction-digits 2; + } + units dB; + description + "Gain tilt control"; + } + + leaf gain-range { + type identityref { + base GAIN_RANGE; + } + description + "Selected gain range. The gain range is a platform-defined + value indicating the switched gain amplifier setting"; + } + + leaf amp-mode { + type identityref { + base OPTICAL_AMPLIFIER_MODE; + } + description + "The operating mode of the amplifier"; + } + + leaf target-output-power { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "Output optical power of the amplifier."; + } + + leaf max-output-power { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "The maximum optical output power of the amplifier. This + may be used to prevent the output power from exceeding a + desired threshold."; + } + + leaf enabled { + type boolean; + description + "Turns power on / off to the amplifiers gain module."; + } + + leaf fiber-type-profile { + type identityref { + base FIBER_TYPE_PROFILE; + } + description + "The fiber type profile specifies details about the + fiber type which are needed to accurately determine + the gain and perform efficient amplification. This is + only needed for Raman type amplifiers."; + } + + } + + grouping optical-amplifier-state { + description + "Operational state data for optical amplifiers"; + + leaf component { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "Reference to the system-supplied physical component that + the amplifier gain block is contained within. Multiple + amplifier gain blocks may be contained within the same + physical component."; + } + + leaf ingress-port { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "Reference to system-supplied name of the amplifier ingress + port. This leaf is only valid for ports of type INGRESS."; + } + + leaf egress-port { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "Reference to system-supplied name of the amplifier egress + port. This leaf is only valid for ports of type EGRESS."; + } + + container actual-gain { + description + "The actual gain applied by the amplifier in units of + 0.01dB. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dB; + } + + container actual-gain-tilt { + description + "The actual tilt applied by the amplifier in units of + 0.01dB. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dB; + } + + container input-power-total { + description + "The total input optical power of this port in units + of 0.01dBm. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container input-power-c-band { + description + "The C band (consisting of approximately 191 to 195 THz or + 1530nm to 1565 nm) input optical power of this port in units + of 0.01dBm. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container input-power-l-band { + description + "The L band (consisting of approximately 184 to 191 THz or + 1565 to 1625 nm) input optical power of this port in units + of 0.01dBm. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container output-power-total { + description + "The total output optical power of this port in units + of 0.01dBm. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container output-power-c-band { + description + "The C band (consisting of approximately 191 to 195 THz or + 1530nm to 1565 nm)output optical power of this port in units + of 0.01dBm. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container output-power-l-band { + description + "The L band (consisting of approximately 184 to 191 THz or + 1565 to 1625 nm)output optical power of this port in units + of 0.01dBm. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container laser-bias-current { + description + "The current applied by the system to the transmit laser to + achieve the output power. The current is expressed in mA + with up to two decimal precision. If avg/min/max statistics + are not supported, just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-mA; + } + + container optical-return-loss { + description + "The optical return loss (ORL) is the ratio of the light + reflected back into the port to the light launched out of + the port. ORL is in units of 0.01dBm. If avg/min/max + statistics are not supported, just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + } + + grouping optical-amplifier-top { + description + "Top-level grouping for optical amplifier data"; + + container optical-amplifier { + description + "Enclosing container for amplifiers and supervisory channels"; + + container amplifiers { + description + "Enclosing container for list of amplifiers"; + + list amplifier { + key "name"; + description + "List of optical amplifiers present in the device"; + + leaf name { + type leafref { + path "../config/name"; + } + description + "Reference to the name of the amplifier"; + } + + container config { + description + "Configuration data for the amplifier"; + + uses optical-amplifier-config; + } + + container state { + + config false; + + description + "Operational state data for the amplifier"; + + uses optical-amplifier-config; + uses optical-amplifier-state; + } + } + } + + container supervisory-channels { + description + "Enclosing container for list of supervisory channels"; + + list supervisory-channel { + key "interface"; + description + "List of supervisory channels"; + + leaf interface { + type leafref { + path "../config/interface"; + } + description + "Reference to the interface of the supervisory channel"; + } + + uses oc-line-com:optical-osc-top; + } + } + } + } + + // data definition statements + + uses optical-amplifier-top; + + +} diff --git a/models/yang/openconfig-optical-attenuator.yang b/models/yang/openconfig-optical-attenuator.yang new file mode 100644 index 000000000..94b3d71bf --- /dev/null +++ b/models/yang/openconfig-optical-attenuator.yang @@ -0,0 +1,233 @@ +module openconfig-optical-attenuator { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/optical-attenuator"; + + prefix "oc-opt-att"; + + import openconfig-platform { prefix oc-platform; } + import openconfig-types { prefix oc-types; } + import openconfig-extensions { prefix oc-ext; } + + + // meta + organization "OpenConfig working group"; + + contact + "OpenConfig working group + www.openconfig.net"; + + description + "This model describes configuration and operational state data + for variable optical attenuators, deployed as part of a transport + line system."; + + oc-ext:openconfig-version "0.1.0"; + + revision "2019-07-19" { + description + "Initial release"; + reference "0.1.0"; + } + + // OpenConfig specific extensions for module metadata. + oc-ext:regexp-posix; + oc-ext:catalog-organization "openconfig"; + oc-ext:origin "openconfig"; + + + // extension statements + + // feature statements + + // identity statements + + identity OPTICAL_ATTENUATOR_MODE { + description + "Type definition for different types of optical attenuator + operating modes"; + } + + identity CONSTANT_POWER { + base OPTICAL_ATTENUATOR_MODE; + description + "Constant power mode"; + } + + identity CONSTANT_ATTENUATION { + base OPTICAL_ATTENUATOR_MODE; + description + "Constant attenuation mode"; + } + + + // grouping statements + + grouping optical-attenuator-config { + description + "Configuration data for optical attenuators"; + + leaf name { + type string; + description + "User-defined name assigned to identify a specific attenuator + in the device"; + } + + leaf attenuation-mode { + type identityref { + base OPTICAL_ATTENUATOR_MODE; + } + description + "The operating mode of the attenuator"; + } + + leaf target-output-power { + type decimal64 { + fraction-digits 2; + } + units dB; + description + "Power level set on the output of attenuator. This leaf is + only relevant when in CONSTANT_POWER mode."; + } + + leaf attenuation { + type decimal64 { + fraction-digits 2; + range 0..max; + } + units dB; + description + "Attenuation applied by the attenuator. This leaf is only + relevant when in CONSTANT_ATTENUATION mode."; + } + + leaf enabled { + type boolean; + description + "When true, attenuator is set to specified attenuation or varies to + maintain constant output power. When false, the attenuator is set + max attenuation or blocked."; + } + } + + grouping optical-attenuator-state { + description + "Operational state data for optical attenuators"; + + leaf component { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "Reference to the system-supplied physical component that + the attenuator block is contained within. Multiple + attenuator blocks may be contained within the same + physical component."; + } + + leaf ingress-port { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "Reference to system-supplied name of the attenuator ingress + port. This leaf is only valid for ports of type INGRESS."; + } + + leaf egress-port { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "Reference to system-supplied name of the attenuator egress + port. This leaf is only valid for ports of type EGRESS."; + } + + + container actual-attenuation { + description + "The actual attenuation applied by the attenuator in units of + 0.01dB. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dB; + } + + container output-power-total { + description + "The total output optical power of this port in units + of 0.01dBm. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container optical-return-loss { + description + "The optical return loss (ORL) is the ratio of the light + reflected back into the port to the light launched out of + the port. ORL is in units of 0.01dBm. If avg/min/max + statistics are not supported, just supply the instant value."; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + } + + grouping optical-attenuator-top { + description + "Top-level grouping for optical attenuator data"; + + container optical-attenuator { + description + "Enclosing container for attenuators"; + + container attenuators { + description + "Enclosing container for list of attenuators"; + + list attenuator { + key "name"; + description + "List of variable optical attenuators present in the device"; + + leaf name { + type leafref { + path "../config/name"; + } + description + "Reference to the name of the attenuator"; + } + + container config { + description + "Configuration data for the attenuator"; + + uses optical-attenuator-config; + } + + container state { + + config false; + + description + "Operational state data for the attenuator"; + + uses optical-attenuator-config; + uses optical-attenuator-state; + } + } + } + } + } + + // data definition statements + uses optical-attenuator-top; + +} diff --git a/models/yang/sonic/sonic-channel-monitor.yang b/models/yang/sonic/sonic-channel-monitor.yang new file mode 100644 index 000000000..73e9864c7 --- /dev/null +++ b/models/yang/sonic/sonic-channel-monitor.yang @@ -0,0 +1,44 @@ +module sonic-channel-monitor { + namespace "http://github.com/Azure/sonic-channel-monitor"; + prefix "sopt-ocm"; + + organization + "SONiC"; + + contact + "SONiC"; + + description + "SONIC OCM"; + + revision 2023-11-17 { + description + "Initial revision."; + } + + + container sonic-channel-monitor { + + container OTN_OCM { + + list OTN_OCM_LIST { + key "name"; + + leaf name { + type string; + description + "User-defined name assigned to identify a specific amplifier + in the device"; + } + + leaf monitor-port { + type string { + length 0..31; + } + description + "Type of the amplifier"; + } + } + } + } +} diff --git a/models/yang/sonic/sonic-optical-amplifier.yang b/models/yang/sonic/sonic-optical-amplifier.yang new file mode 100644 index 000000000..0ae0082ac --- /dev/null +++ b/models/yang/sonic/sonic-optical-amplifier.yang @@ -0,0 +1,129 @@ +module sonic-optical-amplifier { + namespace "http://github.com/Azure/sonic-optical-amplifier"; + prefix "sopt-amp"; + + import sonic-extension { + prefix sonic-ext; + } + + organization + "SONiC"; + + contact + "SONiC"; + + description + "SONIC OPTICAL AMPLIFIER"; + + revision 2022-06-13 { + description + "Initial revision."; + } + + + container sonic-optical-amplifier { + + container OTN_OA { + + list OTN_OA_LIST { + key "name"; + + leaf name { + type string; + description + "User-defined name assigned to identify a specific amplifier + in the device"; + } + + leaf type { + type string; + description + "Type of the amplifier"; + } + + leaf target-gain { + type decimal64 { + fraction-digits 2; + } + description + "Positive gain applied by the amplifier."; + } + + leaf target-gain-tilt { + type decimal64 { + fraction-digits 2; + } + description + "Gain tilt control"; + } + + leaf gain-range { + type string; + description + "Selected gain range. The gain range is a platform-defined + value indicating the switched gain amplifier setting"; + } + + leaf amp-mode { + type string; + description + "The operating mode of the amplifier"; + } + + leaf target-output-power { + type decimal64 { + fraction-digits 2; + } + description + "Output optical power of the amplifier."; + } + + leaf enabled { + type boolean; + description + "Turns power on / off to the amplifiers gain module."; + } + + leaf fiber-type-profile { + type string; + description + "The fiber type profile specifies details about the + fiber type which are needed to accurately determine + the gain and perform efficient amplification. This is + only needed for Raman type amplifiers."; + } + + leaf autolos { + type boolean; + description + "Determines the behavior of the amplifier on input LOS."; + } + + leaf apr-enabled { + type boolean; + description + "Turns apr on / off to the amplifiers."; + } + } + } + + container OTN_OSC { + + list OTN_OSC_LIST { + key "interface"; + + leaf interface { + type string; + description + "Reference to an OSC interface"; + } + + leaf enabled { + type boolean; + description + "turn on/off sfp"; + } + } + } + } +} diff --git a/models/yang/sonic/sonic-optical-attenuator.yang b/models/yang/sonic/sonic-optical-attenuator.yang new file mode 100644 index 000000000..f1728a94d --- /dev/null +++ b/models/yang/sonic/sonic-optical-attenuator.yang @@ -0,0 +1,70 @@ +module sonic-optical-attenuator { + namespace "http://github.com/Azure/sonic-optical-attenuator"; + prefix "sonic-opt-att"; + + import sonic-extension { prefix sonic-ext; } + + organization + "SONiC"; + + contact + "SONiC"; + + description + "SONIC OPTICAL ATTENUATOR"; + + revision 2022-06-13 { + description + "Initial revision."; + } + + + container sonic-optical-attenuator { + + container OTN_ATTENUATOR { + + list OTN_ATTENUATOR_LIST { + key "name"; + + leaf name { + type string; + description + "User-defined name assigned to identify a specific attenuator + in the device"; + } + + leaf attenuation-mode { + type string; + description + "The operating mode of the attenuator"; + } + + leaf target-output-power { + type decimal64 { + fraction-digits 2; + } + description + "Power level set on the output of attenuator. This leaf is + only relevant when in CONSTANT_POWER mode."; + } + + leaf attenuation { + type decimal64 { + fraction-digits 2; + } + description + "Attenuation applied by the attenuator. This leaf is only + relevant when in CONSTANT_ATTENUATION mode."; + } + + leaf enabled { + type boolean; + description + "When true, attenuator is set to specified attenuation or varies to + maintain constant output power. When false, the attenuator is set + max attenuation or blocked."; + } + } + } + } +} diff --git a/translib/transformer/xfmr_otn_openconfig.go b/translib/transformer/xfmr_otn_openconfig.go new file mode 100644 index 000000000..fbe4a99b9 --- /dev/null +++ b/translib/transformer/xfmr_otn_openconfig.go @@ -0,0 +1,216 @@ +package transformer + +import ( + "errors" + "github.com/Azure/sonic-mgmt-common/translib/db" + log "github.com/golang/glog" + "strings" +) + +func init() { + XlateFuncBind("YangToDb_oc_name_key_xfmr", YangToDb_oc_name_key_xfmr) + XlateFuncBind("DbToYang_oc_name_key_xfmr", DbToYang_oc_name_key_xfmr) + XlateFuncBind("YangToDb_oc_name_field_xfmr", YangToDb_oc_name_field_xfmr) + XlateFuncBind("DbToYang_oc_name_field_xfmr", DbToYang_oc_name_field_xfmr) + XlateFuncBind("YangToDb_ocm_channel_key_xfmr", YangToDb_ocm_channel_key_xfmr) + XlateFuncBind("DbToYang_ocm_channel_key_xfmr", DbToYang_ocm_channel_key_xfmr) + XlateFuncBind("YangToDb_ocm_lower_frequency_xfmr", YangToDb_ocm_lower_frequency_xfmr) + XlateFuncBind("YangToDb_osc_key_xfmr", YangToDb_osc_key_xfmr) + XlateFuncBind("DbToYang_osc_key_xfmr", DbToYang_osc_key_xfmr) + XlateFuncBind("YangToDb_osc_interface_xfmr", YangToDb_osc_interface_xfmr) + XlateFuncBind("DbToYang_osc_interface_xfmr", DbToYang_osc_interface_xfmr) + XlateFuncBind("otn_table_xfmr", otn_table_xfmr) +} + +// Generic KeyXfmr for openconfig "name" +var YangToDb_oc_name_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + if log.V(3) { + log.Info("YangToDb_oc_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + } + pathInfo := NewPathInfo(inParams.uri) + ockey := pathInfo.Var("name") + + return ockey, nil +} + +var DbToYang_oc_name_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + res_map := make(map[string]interface{}, 1) + var err error + + if log.V(3) { + log.Info("DbToYang_oc_key_xfmr: ", inParams.key) + } + + res_map["name"] = inParams.key + + return res_map, err +} + +var YangToDb_oc_name_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + res_map := make(map[string]string) + var err error + res_map["NULL"] = "NULL" + return res_map, err +} + +var DbToYang_oc_name_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + var err error + rmap := make(map[string]interface{}) + rmap["name"] = inParams.key + + return rmap, err +} + +// OCM Channel KeyXfmrs +var YangToDb_ocm_channel_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + if log.V(3) { + log.Info("YangToDb_ocm_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + } + pathInfo := NewPathInfo(inParams.uri) + name := pathInfo.Var("name") + lower := pathInfo.Var("lower-frequency") + key := name + "|" + lower + + return key, nil +} + +var DbToYang_ocm_channel_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + rmap := make(map[string]interface{}) + tableKeys := strings.Split(inParams.key, "|") + + if len(tableKeys) >= 2 { + rmap["lower-frequency"] = tableKeys[1] + } + + tableName := "" + if strings.Contains(inParams.uri, "channels/channel") { + tableName = "OTN_OCM_CHANNEL_TABLE" + } + + upperFreq := "" + + // 1. Try Cache + if inParams.dbDataMap != nil && tableName != "" { + if tblData, ok := (*inParams.dbDataMap)[inParams.curDb][tableName]; ok { + if row, ok2 := tblData[inParams.key]; ok2 { + upperFreq = row.Field["upper-frequency"] + } + } + } + + // 2. Direct Redis Fetch (fixes the undefined: db error and the type mismatch) + if upperFreq == "" && tableName != "" { + ts := &db.TableSpec{Name: tableName} + // Using Comp for composite keys allows the driver to handle the '|' separator correctly + rowKey := db.Key{Comp: strings.Split(inParams.key, "|")} + + entry, err := inParams.dbs[inParams.curDb].GetEntry(ts, rowKey) + if err == nil { + upperFreq = entry.Field["upper-frequency"] + } + } + + if upperFreq != "" { + rmap["upper-frequency"] = upperFreq + } else { + log.Warningf("DbToYang_ocm_channel_key_xfmr: Could not resolve upper-frequency for %s", inParams.key) + } + + return rmap, nil +} + +var YangToDb_ocm_lower_frequency_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + var err error + rmap := make(map[string]string) + + rmap["NULL"] = "NULL" + + return rmap, err +} + +// OSC Interface KeyXfmrs +var YangToDb_osc_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + if log.V(3) { + log.Info("YangToDb_osc_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + } + pathInfo := NewPathInfo(inParams.uri) + osckey := pathInfo.Var("interface") + + return osckey, nil +} + +var DbToYang_osc_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + res_map := make(map[string]interface{}, 1) + var err error + + if log.V(3) { + log.Info("DbToYang_osc_key_xfmr: ", inParams.key) + } + + res_map["interface"] = inParams.key + + return res_map, err +} + +var YangToDb_osc_interface_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + res_map := make(map[string]string) + var err error + return res_map, err +} + +var DbToYang_osc_interface_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + var err error + rmap := make(map[string]interface{}) + rmap["interface"] = inParams.key + + return rmap, err +} + +var otn_table_xfmr TableXfmrFunc = func(inParams XfmrParams) ([]string, error) { + + // Check for nil + if inParams.uri == "" { + log.Error("otn_table_xfmr: uri is empty!") + return nil, errors.New("otn_table_xfmr: uri is empty") + } + + pathInfo := NewPathInfo(inParams.uri) + targetUriPath := pathInfo.YangPath + + tblList := []string{} + + switch { + case strings.HasPrefix(targetUriPath, "/openconfig-optical-attenuator:optical-attenuator/attenuators/attenuator"): + tblList = append(tblList, "OTN_ATTENUATOR") + + // 1. Check the specific LIST first (Longer path) + case strings.HasPrefix(targetUriPath, "/openconfig-channel-monitor:channel-monitors/channel-monitor/channels/channel"): + tblList = append(tblList, "OTN_OCM_CHANNEL_TABLE") + + // 2. Check the CONTAINER next (Shorter path) + case strings.HasPrefix(targetUriPath, "/openconfig-channel-monitor:channel-monitors/channel-monitor/channels"): + // Returning empty here forces the framework to recurse + // down to the 'channel' list where it will find the table above. + return tblList, nil + + // 3. Check the PARENT MONITOR + case strings.HasPrefix(targetUriPath, "/openconfig-channel-monitor:channel-monitors/channel-monitor"): + tblList = append(tblList, "OTN_OCM") + + case strings.HasPrefix(targetUriPath, "/openconfig-optical-amplifier:optical-amplifier/amplifiers/amplifier"): + tblList = append(tblList, "OTN_OA") + + case strings.HasPrefix(targetUriPath, "/openconfig-optical-amplifier:optical-amplifier/supervisory-channels/supervisory-channel"): + tblList = append(tblList, "OTN_OSC") + } + + if len(tblList) == 0 { + log.Errorf("otn_table_xfmr: NO MATCHING TABLE for yangPath=%s", targetUriPath) + return nil, errors.New("otn_table_xfmr: no matching table") + } + + return tblList, nil +} From 1121b4fb6f75df5b1bcef3dd2b45d524d9ee148f Mon Sep 17 00:00:00 2001 From: Jimmy Jin Date: Fri, 9 Jan 2026 19:17:07 -0800 Subject: [PATCH 2/9] Add otdr yang model - Alibara --- ...fig-optical-time-domain-reflectometer.yang | 629 ++++++++++++++++++ 1 file changed, 629 insertions(+) create mode 100644 models/yang/openconfig-optical-time-domain-reflectometer.yang diff --git a/models/yang/openconfig-optical-time-domain-reflectometer.yang b/models/yang/openconfig-optical-time-domain-reflectometer.yang new file mode 100644 index 000000000..308b27b9c --- /dev/null +++ b/models/yang/openconfig-optical-time-domain-reflectometer.yang @@ -0,0 +1,629 @@ +module openconfig-optical-time-domain-reflectometer { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/otdr"; + + prefix "oc-otdr"; + + // import some basic types + import openconfig-platform { prefix oc-platform; } + import openconfig-platform-types { prefix oc-platform-types; } + import openconfig-extensions { prefix oc-ext; } + import openconfig-yang-types { prefix oc-yang; } + import openconfig-transport-types { prefix oc-opt-types; } + + + // meta + organization "OpenConfig working group"; + + contact + "OpenConfig working group + www.openconfig.net"; + + description + "This model describes configuration and operational state data + for an OTDR."; + + oc-ext:openconfig-version 0.1.3; + + revision 2020-04-01 { + description + "add otdr locator when sending rpc, modify ieee float-32 format to decimal64"; + reference "0.6.0"; + } + + revision "2019-04-28" { + description + "Update otdr result categories, e.g. baseline, current and history, add scanning-profile to results"; + reference "0.5.0"; + } + + revision "2019-04-11" { + description + "Add otdr repetition, dynamic-range, dead-zone, etc., + modify rpc response structure"; + reference "0.4.0"; + } + + revision "2019-04-01" { + description + "Revised version from Alibaba"; + reference "0.3.0"; + } + + revision "2019-03-29" { + description + "Initial version from Alibaba"; + reference "0.2.0"; + } + + revision "2018-08-28" { + description + "Initial revision"; + reference "0.1.0"; + } + + // typedef statements + + typedef otdr-event-type { + type enumeration { + enum START { + description + "Start-Event on a OTDR trace is the initial point"; + } + enum END { + description + "End-Event on a OTDR trace is the end point of a fiber"; + } + enum REFLECTION { + description + "The phenonmenon on a trace that some power of an optical + pulse is reflected called a reflection event. It is displayed + as a peak signal on a trace"; + } + enum NON-REFLECTION { + description + "The phenonmenon on a trace that there exists some abnormal + loss in an optical line, but no reflection occurred is called + a Non-Reflection-Event. It is displayed as a drop with no peak"; + } + enum FIBER-SECTION { + description + "A fiber section as an event"; + } + enum UNKOWN { + description + "Unknown otdr event"; + } + } + } + + // grouping statements + grouping otdr-fiber-profile { + description + "Enclosing container for otdr fiber-profile configuration"; + + container fiber-profile { + + leaf refractive-index { + type decimal64 { + fraction-digits 4; + } + + description + "refractive ratio"; + } + + leaf backscatter-index { + type decimal64 { + fraction-digits 2; + } + + description + "backscatter ratio"; + } + + leaf reflection-threshold { + type decimal64 { + fraction-digits 2; + } + description + "reflection threshold"; + } + + leaf splice-loss-threshold { + type decimal64 { + fraction-digits 2; + } + + description + "splice loss threshold"; + } + + leaf end-of-fiber-threshold { + type decimal64 { + fraction-digits 2; + } + description + "fiber end event threshold"; + } + } + } + + grouping otdr-scanning-profile { + description + "Enclosing container for otdr scanning profile configuration"; + + container scanning-profile { + + leaf distance-range { + type uint32; + units km; + description + "distance range in km"; + } + + leaf pulse-width { + type uint32; + units ns; + description + "pulse width in ns"; + } + + leaf average-time { + type uint32; + units s; + description + "Average time of each scanning"; + } + + leaf output-frequency { + type oc-opt-types:frequency-type; + description + "The output frequency in MHz of the OTDR"; + } + } + } + + grouping otdr-repetition { + description + "Enclosing container for otdr repetition configuration"; + + container repetition { + + leaf enable { + type boolean; + description + "Repetition or not. If True, then + periodic scan the fiber with given frequency"; + default false; + } + + leaf start-time { + type oc-yang:date-and-time; + description + "The start date and time of the repetition"; + } + + leaf period { + type uint32; + units s; + description + "The scan period of the repetition, e.g. 60s, 15*60s, 24*60*60s"; + } + } + } + + + grouping otdr-config { + description + "Configuration data for otdr scan definitions"; + + leaf name { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "OTDR name"; + } + + leaf parent-port { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "OTDR scan port"; + } + + uses otdr-fiber-profile; + uses otdr-scanning-profile; + uses otdr-repetition; + } + + grouping otdr-specification { + description + "Enclosing container for otdr repetition configuration"; + + container specification { + + leaf dynamic-range { + type uint32; + units dB; + description + "The dynamic range of the OTDR."; + } + + leaf distance-accuracy { + type decimal64 { + fraction-digits 2; + } + + units m; + description + "The distance accuracy of each event"; + } + + leaf sampling-resolution { + type decimal64 { + fraction-digits 2; + } + units m; + description + "sampling resolution of the otdr, with unit of meters"; + } + + leaf loss-dead-zone { + type decimal64 { + fraction-digits 2; + } + + units m; + description + "The dead zone of loss event"; + } + + leaf reflection-dead-zone { + type decimal64 { + fraction-digits 2; + } + + units m; + description + "The dead zone of reflection event"; + } + } + } + + grouping otdr-state { + description + "Operational state data for media channels "; + + uses otdr-specification; + + leaf scanning-status { + type identityref { + base oc-platform-types:COMPONENT_OPER_STATUS; + } + description + "This reports the current scanning status + of the OTDR."; + } + } + + grouping otdr-events { + description + "Top-level grouping for OTDR results"; + + container events { + description + "Enclosing container for otdr results list"; + + leaf scan-time { + type oc-yang:date-and-time; + description + "Time of each scanning operation, including date and time"; + } + + leaf span-distance { + type decimal64 { + fraction-digits 2; + } + + units km; + description + "Total length of a fiber span"; + } + + leaf span-loss { + type decimal64 { + fraction-digits 2; + } + + units dB; + description + "Total loss of a fiber span"; + } + + list event { + key index; + description + "List of otdr results"; + + leaf index { + type uint16; + description + "Index of event"; + } + + leaf type { + type otdr-event-type; + description + "Event type"; + } + + leaf length { + type decimal64 { + fraction-digits 2; + } + + units km; + description + "Event distance or fiber section length in km"; + } + + leaf loss { + type decimal64 { + fraction-digits 2; + } + + description + "Event loss in dB"; + } + + leaf reflection { + type decimal64 { + fraction-digits 2; + } + + description + "Event reflection in dB"; + } + + leaf accumulate-loss { + type decimal64 { + fraction-digits 2; + } + + description + "Accumulated loss at the event point"; + } + } + } + } + + grouping otdr-result-trace { + description + "Top-level grouping for OTDR result waveform"; + + container trace { + + leaf update-time { + type oc-yang:date-and-time; + description + "Update time of the trace, including date and time"; + } + + leaf data { + type oc-yang:hex-string; + } + + description + "Need to consider if there is a better way to collect the waveform"; + } + } + + grouping otdr-result-top { + description + "Top-level grouping for OTDR result"; + + uses otdr-scanning-profile; + uses otdr-events; + uses otdr-result-trace; + } + + grouping otdr-results-top { + description + "Top-level grouping for OTDR result"; + + list result { + key scan-time; + description + "List of otdr results"; + + leaf scan-time { + type leafref { + path "../events/scan-time"; + } + description + "Time of each scanning operation, including date and time"; + } + + uses otdr-result-top; + } + } + + grouping otdr-top { + description + "Top-level grouping for list of defined OTDR monitors"; + + container otdrs { + description + "Enclosing container for OTDR scan list"; + + list otdr { + key name; + description + "List of OTDRs"; + + leaf name { + type leafref { + path "../config/name"; + } + description + "Reference to name to be monitored"; + } + + container config { + description + "Configuration data"; + + uses otdr-config; + } + + container state { + + config false; + + description + "Operational state data"; + + uses otdr-config; + uses otdr-state; + } + + container baseline-result { + + config false; + + description + "Enclosing container for otdr baseline results"; + + uses otdr-result-top; + } + + container current-result { + + config false; + + + description + "Enclosing container for otdr current results"; + + uses otdr-result-top; + } + + container history-results { + + config false; + + description + "Enclosing container for otdr history results"; + + uses otdr-results-top; + } + } + } + } + + // data definition statements + + uses otdr-top; + + // augment statements + // rpc statements + + + rpc trigger-a-shot { + description + "The RPC instantly trigger the otdr and send back the results, if the + scanning-status of the otdr is active, the result is empty with informative + message"; + + input { + leaf name { + type leafref { + path "/oc-otdr:otdrs/otdr/config/oc-otdr:name"; + } + } + } + output { + leaf message { + type string; + description + "Informational response for the otdr results"; + } + + uses otdr-result-top; + } + } + + rpc load-results { + description + "The RPC select a section of time and ask to send back the all the results + within the time section"; + + input { + leaf name { + type leafref { + path "/oc-otdr:otdrs/otdr/config/oc-otdr:name"; + } + } + + leaf start-time { + type oc-yang:date-and-time; + description + "Start time for a period, including date and time"; + } + + leaf end-time { + type oc-yang:date-and-time; + description + "End time for a period, including date and time"; + } + } + + output { + leaf message { + type string; + description + "Informational response for the otdr results"; + } + + uses otdr-results-top; + } + } + + rpc update-baseline { + description + "The RPC will update the baseline result according to the scan time"; + + input { + leaf name { + type leafref { + path "/oc-otdr:otdrs/otdr/config/oc-otdr:name"; + } + } + + leaf scan-time { + type oc-yang:date-and-time; + description + "Update baseline-result, according to scan time"; + } + } + + output { + leaf message { + type string; + description + "Informational response for the otdr results"; + } + + uses otdr-result-top; + } + } + +} \ No newline at end of file From 34e7fe4d9fb454de16f2ebab76623d398d553a7c Mon Sep 17 00:00:00 2001 From: SONIC-ADMIN Date: Tue, 23 Dec 2025 19:12:35 +0530 Subject: [PATCH 3/9] Enhanced mgmt-common framework to support multi namespace Translib operations for OpenConfig OTN YANG models --- config/transformer/models_list | 28 + cvl/common/db_access.go | 1 + cvl/custom_validation/common.go | 1 + cvl/cvl.go | 3 +- cvl/cvl_api.go | 1 + cvl/cvl_error_test.go | 3 +- cvl/cvl_hint_test.go | 31 +- cvl/cvl_leaflist_test.go | 75 +- cvl/cvl_leafref_test.go | 9 +- cvl/cvl_luascript.go | 4 +- cvl/cvl_must_test.go | 24 +- cvl/cvl_optimisation_test.go | 3 +- cvl/cvl_test.go | 1047 +++++---- cvl/internal/util/util.go | 146 +- .../openconfig-channel-monitor-annot.yang | 72 +- .../openconfig-optical-amplifier-annot.yang | 739 ++++++- .../openconfig-optical-attenuator-annot.yang | 424 ++-- ...tical-time-domain-reflectometer-annot.yang | 664 ++++++ .../openconfig-platform-annot.yang | 1520 +++++++++++++ .../annotations/openconfig-system-annot.yang | 1958 ++++++++++++++++- .../openconfig-telemetry-annot.yang | 257 +++ .../openconfig-terminal-device-annot.yang | 1070 +++++++++ .../openconfig-test-xfmr-annot.yang | 173 ++ ...onfig-transport-line-protection-annot.yang | 638 ++++++ .../openconfig-wavelength-router-annot.yang | 377 ++++ .../annotations/sonic-test-xfmr-annot.yang | 62 + .../openconfig-platform-transceiver.yang | 19 + .../common/openconfig-telemetry-types.yang | 124 ++ .../openconfig-transport-line-common.yang | 12 +- .../openconfig-terminal-device-deviation.yang | 30 + ...penconfig-wavelength-router-deviation.yang | 29 + ...fig-optical-time-domain-reflectometer.yang | 5 +- .../yang/openconfig-platform-transceiver.yang | 778 +++++++ models/yang/openconfig-telemetry.yang | 782 +++++++ models/yang/openconfig-terminal-device.yang | 1702 ++++++++++++++ models/yang/openconfig-test-xfmr.yang | 678 ++++++ .../openconfig-transport-line-common.yang | 302 +++ .../openconfig-transport-line-protection.yang | 623 ++++++ models/yang/openconfig-wavelength-router.yang | 755 +++++++ .../sonic/sonic-channel-monitor-state.yang | 71 + .../yang/sonic/sonic-optical-amplifier.yang | 243 +- .../yang/sonic/sonic-optical-attenuator.yang | 136 +- ...nic-optical-time-domain-reflectometer.yang | 117 + models/yang/sonic/sonic-platform-oc.yang | 102 + .../sonic/sonic-platform-transceiver.yang | 60 + models/yang/sonic/sonic-telemetry-client.yang | 118 + models/yang/sonic/sonic-telemetry-config.yang | 183 ++ models/yang/sonic/sonic-terminal-device.yang | 182 ++ models/yang/sonic/sonic-test-xfmr.yang | 344 +++ .../sonic-transport-line-protection.yang | 44 + .../yang/sonic/sonic-wavelength-router.yang | 162 ++ translib/db/db_config_test.go | 181 ++ translib/db/db_util.go | 132 ++ translib/transformer/xfmr_aps.go | 500 +++++ translib/transformer/xfmr_aps_test.go | 244 ++ translib/transformer/xfmr_atten.go | 303 +++ translib/transformer/xfmr_atten_test.go | 260 +++ translib/transformer/xfmr_channel_monitor.go | 281 +++ .../transformer/xfmr_channel_monitor_test.go | 219 ++ translib/transformer/xfmr_getNamespace.go | 26 + translib/transformer/xfmr_line_common.go | 91 + translib/transformer/xfmr_line_common_test.go | 94 + .../transformer/xfmr_optical_amplifier.go | 647 ++++++ .../xfmr_optical_amplifier_test.go | 349 +++ translib/transformer/xfmr_otdr.go | 515 +++++ translib/transformer/xfmr_otdr_test.go | 420 ++++ translib/transformer/xfmr_pfm.go | 247 +++ translib/transformer/xfmr_pfm_test.go | 412 ++++ translib/transformer/xfmr_system.go | 45 + translib/transformer/xfmr_system_test.go | 45 + translib/transformer/xfmr_terminal_device.go | 1366 ++++++++++++ .../transformer/xfmr_terminal_device_test.go | 376 ++++ translib/transformer/xfmr_tlmt.go | 619 ++++++ .../transformer/xfmr_wavelength_router.go | 412 ++++ .../xfmr_wavelength_router_test.go | 316 +++ 75 files changed, 24035 insertions(+), 996 deletions(-) create mode 100644 models/yang/annotations/openconfig-optical-time-domain-reflectometer-annot.yang create mode 100644 models/yang/annotations/openconfig-platform-annot.yang create mode 100644 models/yang/annotations/openconfig-telemetry-annot.yang create mode 100644 models/yang/annotations/openconfig-terminal-device-annot.yang create mode 100644 models/yang/annotations/openconfig-test-xfmr-annot.yang create mode 100644 models/yang/annotations/openconfig-transport-line-protection-annot.yang create mode 100644 models/yang/annotations/openconfig-wavelength-router-annot.yang create mode 100644 models/yang/annotations/sonic-test-xfmr-annot.yang create mode 100644 models/yang/common/openconfig-telemetry-types.yang create mode 100644 models/yang/extensions/openconfig-terminal-device-deviation.yang create mode 100644 models/yang/extensions/openconfig-wavelength-router-deviation.yang create mode 100644 models/yang/openconfig-platform-transceiver.yang create mode 100644 models/yang/openconfig-telemetry.yang create mode 100644 models/yang/openconfig-terminal-device.yang create mode 100644 models/yang/openconfig-test-xfmr.yang create mode 100644 models/yang/openconfig-transport-line-common.yang create mode 100644 models/yang/openconfig-transport-line-protection.yang create mode 100644 models/yang/openconfig-wavelength-router.yang create mode 100644 models/yang/sonic/sonic-channel-monitor-state.yang create mode 100644 models/yang/sonic/sonic-optical-time-domain-reflectometer.yang create mode 100644 models/yang/sonic/sonic-platform-oc.yang create mode 100644 models/yang/sonic/sonic-platform-transceiver.yang create mode 100644 models/yang/sonic/sonic-telemetry-client.yang create mode 100644 models/yang/sonic/sonic-telemetry-config.yang create mode 100644 models/yang/sonic/sonic-terminal-device.yang create mode 100644 models/yang/sonic/sonic-test-xfmr.yang create mode 100644 models/yang/sonic/sonic-transport-line-protection.yang create mode 100644 models/yang/sonic/sonic-wavelength-router.yang create mode 100644 translib/db/db_config_test.go create mode 100644 translib/db/db_util.go create mode 100644 translib/transformer/xfmr_aps.go create mode 100644 translib/transformer/xfmr_aps_test.go create mode 100644 translib/transformer/xfmr_atten.go create mode 100644 translib/transformer/xfmr_atten_test.go create mode 100644 translib/transformer/xfmr_channel_monitor.go create mode 100644 translib/transformer/xfmr_channel_monitor_test.go create mode 100644 translib/transformer/xfmr_getNamespace.go create mode 100644 translib/transformer/xfmr_line_common.go create mode 100644 translib/transformer/xfmr_line_common_test.go create mode 100644 translib/transformer/xfmr_optical_amplifier.go create mode 100644 translib/transformer/xfmr_optical_amplifier_test.go create mode 100644 translib/transformer/xfmr_otdr.go create mode 100644 translib/transformer/xfmr_otdr_test.go create mode 100644 translib/transformer/xfmr_pfm.go create mode 100644 translib/transformer/xfmr_pfm_test.go create mode 100644 translib/transformer/xfmr_system_test.go create mode 100644 translib/transformer/xfmr_terminal_device.go create mode 100644 translib/transformer/xfmr_terminal_device_test.go create mode 100644 translib/transformer/xfmr_tlmt.go create mode 100644 translib/transformer/xfmr_wavelength_router.go create mode 100644 translib/transformer/xfmr_wavelength_router_test.go diff --git a/config/transformer/models_list b/config/transformer/models_list index 32f43e52e..57163c8cb 100644 --- a/config/transformer/models_list +++ b/config/transformer/models_list @@ -16,3 +16,31 @@ gnsi-authz.yang gnsi-pathz.yang gnsi-certz.yang gnsi-credentialz.yang +openconfig-optical-amplifier.yang +openconfig-optical-amplifier-annot.yang +openconfig-optical-attenuator.yang +openconfig-optical-attenuator-annot.yang +openconfig-channel-monitor.yang +openconfig-channel-monitor-annot.yang +openconfig-system.yang +openconfig-system-annot.yang +openconfig-platform.yang +openconfig-platform-annot.yang +openconfig-terminal-device.yang +openconfig-terminal-device-annot.yang +openconfig-terminal-device-deviation.yang +openconfig-optical-time-domain-reflectometer.yang +openconfig-optical-time-domain-reflectometer-annot.yang +openconfig-telemetry.yang +openconfig-telemetry-annot.yang +openconfig-transport-line-protection.yang +openconfig-transport-line-protection-annot.yang +openconfig-wavelength-router.yang +openconfig-wavelength-router-annot.yang +openconfig-transport-line-common.yang +openconfig-platform-transceiver.yang +openconfig-wavelength-router-deviation.yang +openconfig-test-xfmr.yang +openconfig-test-xfmr-annot.yang +sonic-test-xfmr-annot.yang + diff --git a/cvl/common/db_access.go b/cvl/common/db_access.go index 431ec61f0..8ce91f9a3 100644 --- a/cvl/common/db_access.go +++ b/cvl/common/db_access.go @@ -37,6 +37,7 @@ type DBAccess interface { Lookup(s Search) JsonResult // Count entries using a Search criteria. Returns 0 if there are no matches. Count(s Search) IntResult + GetMDBName() string } type IntResult interface { diff --git a/cvl/custom_validation/common.go b/cvl/custom_validation/common.go index 1883aa226..9dda21f7f 100644 --- a/cvl/custom_validation/common.go +++ b/cvl/custom_validation/common.go @@ -115,6 +115,7 @@ type CustValidationCtxt struct { YCur *xmlquery.Node //YANG data tree SessCache *CustValidationCache //Session cache, can be used for storing data, persistent in session RClient common.DBAccess //Db access interface + NameSpace string // Namespace is required to open NewDbClient to other dependent DBs like STATE_DB,APPL_DB.. } // Search criteria for advanced lookup through DBAccess APIs diff --git a/cvl/cvl.go b/cvl/cvl.go index 2a63b1196..230034d03 100644 --- a/cvl/cvl.go +++ b/cvl/cvl.go @@ -1110,7 +1110,8 @@ func (c *CVL) doCustomValidation(node *xmlquery.Node, YNodeVal: nodeVal, YCur: node, SessCache: &(c.custvCache), - RClient: c.dbAccess} + RClient: c.dbAccess, + NameSpace: c.dbAccess.GetMDBName()} for _, custFunction := range custFuncs { CVL_LOG(INFO_TRACE, "Calling custom validation function %s", custFunction) errObj := custv.InvokeCustomValidation(&custv.CustomValidation{}, custFunction, pCustv) diff --git a/cvl/cvl_api.go b/cvl/cvl_api.go index 18e7632cb..6c9368698 100644 --- a/cvl/cvl_api.go +++ b/cvl/cvl_api.go @@ -300,6 +300,7 @@ func (c *CVL) ValidateEditConfig(cfgData []cmn.CVLEditConfigData) (cvlErr CVLErr panic(c.dbAccess) } + CVL_LOG(INFO_DEBUG, "ValidateEditConfig: Namespace:%s", c.dbAccess.GetMDBName()) ts := time.Now() defer func() { diff --git a/cvl/cvl_error_test.go b/cvl/cvl_error_test.go index 30a433253..078fcebe8 100644 --- a/cvl/cvl_error_test.go +++ b/cvl/cvl_error_test.go @@ -82,7 +82,8 @@ const ( ) func verifyValidateEditConfig(t *testing.T, data []CVLEditConfigData, exp CVLErrorInfo) { - c := NewTestSession(t) + d := getMDBInstance(hostDBName) + c := NewTestSession(t, d) res, _ := c.ValidateEditConfig(data) verifyErr(t, res, exp) } diff --git a/cvl/cvl_hint_test.go b/cvl/cvl_hint_test.go index ec37b5350..256426bbe 100644 --- a/cvl/cvl_hint_test.go +++ b/cvl/cvl_hint_test.go @@ -30,19 +30,22 @@ var hKey = "TESTKEY" var hValue = map[string]string{"a": "1", "b": "2"} func TestSetHint(t *testing.T) { - cvSess, retCode := NewCvlSession() - if retCode != cvl.CVL_SUCCESS { - t.Fatalf("cvl.ValidationSessOpen() fails e: %v", retCode) - } - - t.Cleanup(func() { cvl.ValidationSessClose(cvSess) }) - - if retCode = cvSess.StoreHint(hKey, hValue); retCode != cvl.CVL_SUCCESS { - t.Fatalf("cvSess.StoreHint() fails e: %v", retCode) - } - - value, ok := cvSess.LoadHint(hKey) - if !ok || !reflect.DeepEqual(hValue, value) { - t.Errorf("%v != %v", hValue, value) + for _, dbName := range MdbNames { + d := configDb[dbName] + cvSess, retCode := NewCvlSession(d) + if retCode != cvl.CVL_SUCCESS { + t.Fatalf("cvl.ValidationSessOpen() fails e: %v", retCode) + } + + t.Cleanup(func() { cvl.ValidationSessClose(cvSess) }) + + if retCode = cvSess.StoreHint(hKey, hValue); retCode != cvl.CVL_SUCCESS { + t.Fatalf("cvSess.StoreHint() fails e: %v", retCode) + } + + value, ok := cvSess.LoadHint(hKey) + if !ok || !reflect.DeepEqual(hValue, value) { + t.Errorf("%v != %v", hValue, value) + } } } diff --git a/cvl/cvl_leaflist_test.go b/cvl/cvl_leaflist_test.go index bea38967a..427d74af4 100644 --- a/cvl/cvl_leaflist_test.go +++ b/cvl/cvl_leaflist_test.go @@ -63,7 +63,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { // Create test cases t.Run("create_all", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_CREATE, @@ -78,7 +79,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("create_without_min0", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_CREATE, @@ -91,7 +93,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("create_without_min1", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_CREATE, @@ -103,7 +106,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("create_without_min4", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_CREATE, @@ -115,7 +119,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("create_more_than_max", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_CREATE, @@ -128,7 +133,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("create_less_than_min", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_CREATE, @@ -143,7 +149,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { // update cases t.Run("update_without_minmax", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_UPDATE, @@ -155,7 +162,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("update_min0", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_UPDATE, @@ -168,7 +176,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("update_to_min1", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_UPDATE, @@ -181,7 +190,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("update_to_min4", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_UPDATE, @@ -193,7 +203,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("update_to_max", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_UPDATE, @@ -206,7 +217,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("update_more_than_max", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_UPDATE, @@ -219,7 +231,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("update_less_than_min", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_UPDATE, @@ -232,7 +245,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("update_to_empty1", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_UPDATE, @@ -245,7 +259,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("update_to_empty4", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_UPDATE, @@ -258,7 +273,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { // delete cases t.Run("delete_without_minmax", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_DELETE, @@ -269,7 +285,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("delete_min0", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_DELETE, @@ -280,7 +297,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("delete_min1", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_DELETE, @@ -291,7 +309,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("delete_min4", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_DELETE, @@ -304,7 +323,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { // replace cases t.Run("replace_no_constraints2", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ ReplaceOp: true, VType: VALIDATE_ALL, @@ -322,7 +342,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("replace_remove_min0", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ ReplaceOp: true, VType: VALIDATE_ALL, @@ -340,7 +361,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("replace_remove_min1", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ ReplaceOp: true, VType: VALIDATE_ALL, @@ -358,7 +380,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("replace_remove_min4", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ ReplaceOp: true, VType: VALIDATE_ALL, @@ -376,7 +399,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("replace_set_more_than_max", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ ReplaceOp: true, VType: VALIDATE_ALL, @@ -394,7 +418,8 @@ func TestValidateEditConfig_Leaflist_MinMax(t *testing.T) { }) t.Run("replace_set_less_than_min", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ ReplaceOp: true, VType: VALIDATE_ALL, diff --git a/cvl/cvl_leafref_test.go b/cvl/cvl_leafref_test.go index 6102c54f2..153768942 100644 --- a/cvl/cvl_leafref_test.go +++ b/cvl/cvl_leafref_test.go @@ -57,7 +57,8 @@ func TestValidateEditConfig_Create_Chained_Leafref_DepData_Positive(t *testing.T }, }) - cvSess, _ := NewCvlSession() + d := getMDBInstance(hostDBName) + cvSess, _ := NewCvlSession(d) cfgDataVlan := []cmn.CVLEditConfigData{ cmn.CVLEditConfigData{ @@ -389,7 +390,8 @@ func TestValidateEditConfig_Delete_Leafref(t *testing.T) { func deletePO(poId int, expSuccess bool) func(*testing.T) { return func(t *testing.T) { - session, _ := NewCvlSession() + d := getMDBInstance(hostDBName) + session, _ := NewCvlSession(d) defer cvl.ValidationSessClose(session) validateDeletePO(t, session, nil, poId, expSuccess) } @@ -397,7 +399,8 @@ func deletePO(poId int, expSuccess bool) func(*testing.T) { func deleteACLAndPO(aclName, ports string, poId int, bulk, expSuccess bool) func(*testing.T) { return func(t *testing.T) { - session, _ := NewCvlSession() + d := getMDBInstance(hostDBName) + session, _ := NewCvlSession(d) defer cvl.ValidationSessClose(session) var cfgData []cmn.CVLEditConfigData diff --git a/cvl/cvl_luascript.go b/cvl/cvl_luascript.go index e3aa8503b..fb2f652e6 100644 --- a/cvl/cvl_luascript.go +++ b/cvl/cvl_luascript.go @@ -21,14 +21,14 @@ package cvl import ( "errors" - "github.com/go-redis/redis/v7" + //lint:ignore ST1001 This is safe to dot import for util package ) // RunLua is a temporary API to run a named lua script in ConfigDb. Script name // can be one of "count_entries" or "filter_entries". // TODO move the script definitions to DBAL and remove this API -func RunLua(name string, args ...interface{}) (interface{}, error) { +func RunLua(redisClient *redis.Client, name string, args ...interface{}) (interface{}, error) { script, ok := luaScripts[name] if !ok || script == nil { return nil, errors.New("unknown script: " + name) diff --git a/cvl/cvl_must_test.go b/cvl/cvl_must_test.go index 1f0ade629..b0ec52cef 100644 --- a/cvl/cvl_must_test.go +++ b/cvl/cvl_must_test.go @@ -154,7 +154,8 @@ func TestValidateEditConfig_Not_equal_in_predicate_postive(t *testing.T) { // Create of another entry with unused port t.Run("create_entry_unused_port", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_CREATE, @@ -167,7 +168,8 @@ func TestValidateEditConfig_Not_equal_in_predicate_postive(t *testing.T) { // Update of ifname to an unused port t.Run("update_ifname_unused_port", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_UPDATE, @@ -180,7 +182,8 @@ func TestValidateEditConfig_Not_equal_in_predicate_postive(t *testing.T) { // Update of some other attribute t.Run("update_other_attr", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_UPDATE, @@ -192,7 +195,8 @@ func TestValidateEditConfig_Not_equal_in_predicate_postive(t *testing.T) { }) // Delete of some other attribute t.Run("delete_other_attr", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_DELETE, @@ -218,7 +222,8 @@ func TestValidateEditConfig_Not_equal_in_predicate_negative(t *testing.T) { }}) // Create of entry with already existing ifname t.Run("create_entry_already_existing_port", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_CREATE, @@ -236,7 +241,8 @@ func TestValidateEditConfig_Not_equal_in_predicate_negative(t *testing.T) { // Update of ifname to already used port name t.Run("update_ifname_already_existing_port", func(tt *testing.T) { - c := NewTestSession(tt) + d := getMDBInstance(hostDBName) + c := NewTestSession(tt, d) res, _ := c.ValidateEditConfig([]CVLEditConfigData{{ VType: VALIDATE_ALL, VOp: OP_UPDATE, @@ -325,7 +331,8 @@ func TestValidateEditConfig_MustExp_With_Default_Value_Negative(t *testing.T) { }, } - cvSess, _ := NewCvlSession() + d := getMDBInstance(hostDBName) + cvSess, _ := NewCvlSession(d) //Try to add second element cvlErrInfo, _ := cvSess.ValidateEditConfig(cfgData) @@ -659,7 +666,8 @@ func TestValidateEditConfig_MustExp_Add_NULL(t *testing.T) { func testNullAdd(data ...cmn.CVLEditConfigData) func(*testing.T) { return func(t *testing.T) { - session, _ := NewCvlSession() + d := getMDBInstance(hostDBName) + session, _ := NewCvlSession(d) defer cvl.ValidationSessClose(session) var cfgData []cmn.CVLEditConfigData diff --git a/cvl/cvl_optimisation_test.go b/cvl/cvl_optimisation_test.go index d45968d1d..6103d987e 100644 --- a/cvl/cvl_optimisation_test.go +++ b/cvl/cvl_optimisation_test.go @@ -32,7 +32,8 @@ func extraChecksHelper(t *testing.T, dbData map[string]interface{}, data []CVLEd if dbData != nil { setupTestData(t, dbData) } - c := NewTestSession(t) + d := getMDBInstance(hostDBName) + c := NewTestSession(t, d) c.StoreHint(hintKey, false) res, _ := c.ValidateEditConfig(data) verifyErr(t, res, Success) diff --git a/cvl/cvl_test.go b/cvl/cvl_test.go index 8bbd400c8..4c883132f 100644 --- a/cvl/cvl_test.go +++ b/cvl/cvl_test.go @@ -321,6 +321,11 @@ func clearDb() { /* Setup before starting of test. */ func TestMain(m *testing.M) { + rclient = redis.NewClient(&redis.Options{ + Addr: "localhost:6381", // Change this to your desired port (e.g., "localhost:6380") + Password: "", // No password set + DB: 0, // Default DB + }) redisAlreadyRunning := false pidOfRedis, err := exec.Command("pidof", "redis-server").Output() if err == nil && string(pidOfRedis) != "\n" { @@ -372,19 +377,33 @@ func TestMain(m *testing.M) { } -var configDb *db.DB +var configDb map[string]*db.DB + +const hostDBName string = "host" + +var MdbNames []string = []string{"host"} func init() { var err error - configDb, err = db.NewDB(db.Options{ - DBNo: db.ConfigDB, - TableNameSeparator: "|", - KeySeparator: "|", - IsWriteDisabled: true, - }) - if err != nil { - panic(err) + configDb = make(map[string]*db.DB) + + if IsMultiAsic() { + MdbNames = append(MdbNames, "asic0") } + + for _, dbName := range MdbNames { + configDb[dbName], err = db.NewDB(db.Options{ + DBNo: db.ConfigDB, + MDBName: dbName, + TableNameSeparator: "|", + KeySeparator: "|", + IsWriteDisabled: true, + }) + if err != nil { + panic(err) + } + } + } // Test Initialize() API @@ -413,8 +432,8 @@ func TestFinish(t *testing.T) { cvl.Initialize() } -func NewCvlSession() (cvlSess *cvl.CVL, retCode cvl.CVLRetCode) { - cvlSess, err := configDb.NewValidationSession() +func NewCvlSession(d *db.DB) (cvlSess *cvl.CVL, retCode cvl.CVLRetCode) { + cvlSess, err := d.NewValidationSession() retCode = cvl.CVL_SUCCESS if err != nil { retCode = cvl.CVLRetCode(err.(tlerr.TranslibCVLFailure).Code) @@ -422,8 +441,8 @@ func NewCvlSession() (cvlSess *cvl.CVL, retCode cvl.CVLRetCode) { return } -func NewTestSession(t *testing.T) *cvl.CVL { - c, _ := configDb.NewValidationSession() +func NewTestSession(t *testing.T, d *db.DB) *cvl.CVL { + c, _ := d.NewValidationSession() t.Cleanup(func() { cvl.ValidationSessClose(c) }) return c } @@ -433,6 +452,13 @@ func setupTestData(t *testing.T, dbData map[string]interface{}) { t.Cleanup(func() { unloadConfigDB(rclient, dbData) }) } +func getMDBInstance(dbName string) *db.DB { + d := configDb[dbName] + d.Opts.MDBName = dbName + + return d +} + /* ValidateEditConfig with user input in file . */ func TestValidateEditConfig_CfgFile(t *testing.T) { @@ -444,40 +470,42 @@ func TestValidateEditConfig_CfgFile(t *testing.T) { }{ {filedescription: "ACL_DATA", cfgDataFile: "testdata/aclrule.json", depDataFile: "testdata/acltable.json", retCode: cvl.CVL_SUCCESS}, } + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) - cvSess, _ := NewCvlSession() + for index, tc := range tests { + t.Logf("Running Testcase %d with Description %s", index+1, tc.filedescription) - for index, tc := range tests { - t.Logf("Running Testcase %d with Description %s", index+1, tc.filedescription) + t.Run(tc.filedescription+" "+dbName, func(t *testing.T) { - t.Run(tc.filedescription, func(t *testing.T) { + jsonEditCfg_Create_DependentMap := convertJsonFileToMap(t, tc.depDataFile) + jsonEditCfg_Create_ConfigMap := convertJsonFileToMap(t, tc.cfgDataFile) - jsonEditCfg_Create_DependentMap := convertJsonFileToMap(t, tc.depDataFile) - jsonEditCfg_Create_ConfigMap := convertJsonFileToMap(t, tc.cfgDataFile) + cfgData := []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{cmn.VALIDATE_ALL, cmn.OP_CREATE, "ACL_TABLE|TestACL1", jsonEditCfg_Create_DependentMap, false}, + } - cfgData := []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{cmn.VALIDATE_ALL, cmn.OP_CREATE, "ACL_TABLE|TestACL1", jsonEditCfg_Create_DependentMap, false}, - } + cvlErrObj, err := cvSess.ValidateEditConfig(cfgData) - cvlErrObj, err := cvSess.ValidateEditConfig(cfgData) + if err != tc.retCode { + t.Errorf("Config Validation failed. %v", cvlErrObj) + } - if err != tc.retCode { - t.Errorf("Config Validation failed. %v", cvlErrObj) - } + cfgData = []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{cmn.VALIDATE_ALL, cmn.OP_CREATE, "ACL_RULE|TestACL1|Rule1", jsonEditCfg_Create_ConfigMap, false}, + } - cfgData = []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{cmn.VALIDATE_ALL, cmn.OP_CREATE, "ACL_RULE|TestACL1|Rule1", jsonEditCfg_Create_ConfigMap, false}, - } + cvlErrObj, err = cvSess.ValidateEditConfig(cfgData) - cvlErrObj, err = cvSess.ValidateEditConfig(cfgData) + if err != tc.retCode { + t.Errorf("Config Validation failed. %v", cvlErrObj) + } + }) + } - if err != tc.retCode { - t.Errorf("Config Validation failed. %v", cvlErrObj) - } - }) + cvl.ValidationSessClose(cvSess) } - - cvl.ValidationSessClose(cvSess) } /* ValidateEditConfig with user input inline. */ @@ -490,45 +518,48 @@ func TestValidateEditConfig_CfgStrBuffer(t *testing.T) { retCode cvl.CVLRetCode } - cvSess, _ := NewCvlSession() + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) - tests := []testStruct{} + tests := []testStruct{} - /* Iterate through data present is separate file. */ - for index, _ := range json_edit_config_create_acl_table_dependent_data { - tests = append(tests, testStruct{filedescription: "ACL_DATA", cfgData: json_edit_config_create_acl_rule_config_data[index], - depData: json_edit_config_create_acl_table_dependent_data[index], retCode: cvl.CVL_SUCCESS}) - } + /* Iterate through data present is separate file. */ + for index, _ := range json_edit_config_create_acl_table_dependent_data { + tests = append(tests, testStruct{filedescription: "ACL_DATA", cfgData: json_edit_config_create_acl_rule_config_data[index], + depData: json_edit_config_create_acl_table_dependent_data[index], retCode: cvl.CVL_SUCCESS}) + } - for index, tc := range tests { - t.Logf("Running Testcase %d with Description %s", index+1, tc.filedescription) - t.Run(tc.filedescription, func(t *testing.T) { - jsonEditCfg_Create_DependentMap := convertDataStringToMap(t, tc.depData) - jsonEditCfg_Create_ConfigMap := convertDataStringToMap(t, tc.cfgData) + for index, tc := range tests { + t.Logf("Running Testcase %d with Description %s", index+1, tc.filedescription) + t.Run(tc.filedescription+" "+dbName, func(t *testing.T) { + jsonEditCfg_Create_DependentMap := convertDataStringToMap(t, tc.depData) + jsonEditCfg_Create_ConfigMap := convertDataStringToMap(t, tc.cfgData) - cfgData := []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{cmn.VALIDATE_ALL, cmn.OP_CREATE, "ACL_TABLE|TestACL1", jsonEditCfg_Create_DependentMap, false}, - } + cfgData := []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{cmn.VALIDATE_ALL, cmn.OP_CREATE, "ACL_TABLE|TestACL1", jsonEditCfg_Create_DependentMap, false}, + } - cvlErrObj, err := cvSess.ValidateEditConfig(cfgData) + cvlErrObj, err := cvSess.ValidateEditConfig(cfgData) - if err != tc.retCode { - t.Errorf("Config Validation failed. %v", cvlErrObj) - } + if err != tc.retCode { + t.Errorf("Config Validation failed. %v", cvlErrObj) + } - cfgData = []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{cmn.VALIDATE_ALL, cmn.OP_CREATE, "ACL_RULE|TestACL1|Rule1", jsonEditCfg_Create_ConfigMap, false}, - } + cfgData = []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{cmn.VALIDATE_ALL, cmn.OP_CREATE, "ACL_RULE|TestACL1|Rule1", jsonEditCfg_Create_ConfigMap, false}, + } - cvlErrObj, err = cvSess.ValidateEditConfig(cfgData) + cvlErrObj, err = cvSess.ValidateEditConfig(cfgData) - if err != tc.retCode { - t.Errorf("Config Validation failed. %v", cvlErrObj) - } - }) - } + if err != tc.retCode { + t.Errorf("Config Validation failed. %v", cvlErrObj) + } + }) + } - cvl.ValidationSessClose(cvSess) + cvl.ValidationSessClose(cvSess) + } } /* API when config is given as string buffer. */ @@ -549,7 +580,8 @@ func TestValidateConfig_CfgStrBuffer(t *testing.T) { tests = append(tests, testStruct{filedescription: modelName, jsonString: json_validate_config_data[index], retCode: cvl.CVL_SUCCESS}) } - cvSess, _ := NewCvlSession() + d := getMDBInstance(hostDBName) + cvSess, _ := NewCvlSession(d) for index, tc := range tests { t.Logf("Running Testcase %d with Description %s", index+1, tc.filedescription) @@ -579,47 +611,53 @@ func TestValidateConfig_CfgFile(t *testing.T) { {filedescription: "Config File - VLAN,ACL,PORTCHANNEL", fileName: "testdata/config_db1.json", retCode: cvl.CVL_SUCCESS}, } - cvSess, _ := NewCvlSession() + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) - for index, tc := range tests { + for index, tc := range tests { - t.Logf("Running Testcase %d with Description %s", index+1, tc.filedescription) - t.Run(tc.filedescription, func(t *testing.T) { - jsonString := convertJsonFileToString(t, tc.fileName) - err := cvSess.ValidateConfig(jsonString) + t.Logf("Running Testcase %d with Description %s", index+1, tc.filedescription) + t.Run(tc.filedescription+" "+dbName, func(t *testing.T) { + jsonString := convertJsonFileToString(t, tc.fileName) + err := cvSess.ValidateConfig(jsonString) - if err != tc.retCode { - t.Errorf("Config Validation failed.") - } + if err != tc.retCode { + t.Errorf("Config Validation failed.") + } - }) - } + }) + } - cvl.ValidationSessClose(cvSess) + cvl.ValidationSessClose(cvSess) + } } // Validate invalid json data func TestValidateConfig_Negative(t *testing.T) { - cvSess, _ := NewCvlSession() - jsonData := `{ - "VLANjunk": { - "Vlan100": { - "members": [ - "Ethernet4", - "Ethernet8" - ], - "vlanid": "100" + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) + jsonData := `{ + "VLANjunk": { + "Vlan100": { + "members": [ + "Ethernet4", + "Ethernet8" + ], + "vlanid": "100" + } } - } - }` + }` - err := cvSess.ValidateConfig(jsonData) + err := cvSess.ValidateConfig(jsonData) - if err == cvl.CVL_SUCCESS { //Should return failure - t.Errorf("Config Validation failed.") - } + if err == cvl.CVL_SUCCESS { //Should return failure + t.Errorf("Config Validation failed.") + } - cvl.ValidationSessClose(cvSess) + cvl.ValidationSessClose(cvSess) + } } /* Delete Existing Key.*/ @@ -1969,27 +2007,30 @@ func TestValidateEditConfig_Update_Semantic_Positive(t *testing.T) { /* API to test edit config with valid syntax. */ func TestValidateConfig_Semantic_Vlan_Negative(t *testing.T) { - cvSess, _ := NewCvlSession() + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) + + jsonData := `{ + "VLAN": { + "Vlan100": { + "members": [ + "Ethernet44", + "Ethernet64" + ], + "vlanid": "107" + } + } + }` - jsonData := `{ - "VLAN": { - "Vlan100": { - "members": [ - "Ethernet44", - "Ethernet64" - ], - "vlanid": "107" - } - } - }` + err := cvSess.ValidateConfig(jsonData) - err := cvSess.ValidateConfig(jsonData) + if err == cvl.CVL_SUCCESS { //Expected semantic failure + t.Errorf("Config Validation failed -- error details.") + } - if err == cvl.CVL_SUCCESS { //Expected semantic failure - t.Errorf("Config Validation failed -- error details.") + cvl.ValidationSessClose(cvSess) } - - cvl.ValidationSessClose(cvSess) } func TestValidateEditConfig_Update_Syntax_DependentData_Redis_Positive(t *testing.T) { @@ -2036,7 +2077,8 @@ func TestValidateEditConfig_Update_Syntax_DependentData_Redis_Positive(t *testin }, } - cvSess, _ := NewCvlSession() + d := getMDBInstance(hostDBName) + cvSess, _ := NewCvlSession(d) cvlErrInfo, retCode := cvSess.ValidateEditConfig(cfgData) @@ -2088,67 +2130,74 @@ func TestValidateEditConfig_Update_Syntax_DependentData_Invalid_Op_Seq(t *testin }, } - cvSess, _ := NewCvlSession() + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) - cvlErrInfo, err := cvSess.ValidateEditConfig(cfgData) + cvSess, _ := NewCvlSession(d) - cvl.ValidationSessClose(cvSess) + cvlErrInfo, err := cvSess.ValidateEditConfig(cfgData) - if err == cvl.CVL_SUCCESS { //Validation should fail - t.Errorf("Config Validation failed -- error details %v", cvlErrInfo) - } + cvl.ValidationSessClose(cvSess) + if err == cvl.CVL_SUCCESS { //Validation should fail + t.Errorf("Config Validation failed -- error details %v", cvlErrInfo) + } + } } /* Create with User provided dependent data. */ func TestValidateEditConfig_Create_Syntax_DependentData_Redis_Positive(t *testing.T) { - /* ACL and Rule name pre-created . */ - cfgData := []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{ - cmn.VALIDATE_ALL, - cmn.OP_CREATE, - "ACL_TABLE|TestACL22", - map[string]string{ - "stage": "INGRESS", - "type": "MIRROR", + for _, dbName := range MdbNames { + /* ACL and Rule name pre-created . */ + cfgData := []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{ + cmn.VALIDATE_ALL, + cmn.OP_CREATE, + "ACL_TABLE|TestACL22", + map[string]string{ + "stage": "INGRESS", + "type": "MIRROR", + }, + false, }, - false, - }, - } + } - cvSess, _ := NewCvlSession() + d := getMDBInstance(dbName) - cvlErrInfo, err := cvSess.ValidateEditConfig(cfgData) + cvSess, _ := NewCvlSession(d) - if err != cvl.CVL_SUCCESS { - t.Errorf("Config Validation failed -- error details %v", cvlErrInfo) - } + cvlErrInfo, err := cvSess.ValidateEditConfig(cfgData) - cfgData = []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{ - cmn.VALIDATE_ALL, - cmn.OP_CREATE, - "ACL_RULE|TestACL22|Rule1", - map[string]string{ - "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", - "SRC_IP": "10.1.1.1/32", - "L4_SRC_PORT": "1909", - "IP_PROTOCOL": "103", - "DST_IP": "20.2.2.2/32", - "L4_DST_PORT_RANGE": "9000-12000", + if err != cvl.CVL_SUCCESS { + t.Errorf("Config Validation failed -- error details %v", cvlErrInfo) + } + + cfgData = []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{ + cmn.VALIDATE_ALL, + cmn.OP_CREATE, + "ACL_RULE|TestACL22|Rule1", + map[string]string{ + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPV4", + "SRC_IP": "10.1.1.1/32", + "L4_SRC_PORT": "1909", + "IP_PROTOCOL": "103", + "DST_IP": "20.2.2.2/32", + "L4_DST_PORT_RANGE": "9000-12000", + }, + false, }, - false, - }, - } + } - cvlErrInfo, err = cvSess.ValidateEditConfig(cfgData) + cvlErrInfo, err = cvSess.ValidateEditConfig(cfgData) - cvl.ValidationSessClose(cvSess) + cvl.ValidationSessClose(cvSess) - if err != cvl.CVL_SUCCESS { - t.Errorf("Config Validation failed -- error details %v", cvlErrInfo) + if err != cvl.CVL_SUCCESS { + t.Errorf("Config Validation failed -- error details %v", cvlErrInfo) + } } } @@ -2174,100 +2223,106 @@ func TestValidateEditConfig_Delete_Semantic_ACLTableReference_Negative(t *testin func TestValidateEditConfig_Create_Dependent_CacheData(t *testing.T) { - cvSess, _ := NewCvlSession() - - //Create ACL rule - cfgDataAcl := []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{ - cmn.VALIDATE_ALL, - cmn.OP_CREATE, - "ACL_TABLE|TestACL14", - map[string]string{ - "stage": "INGRESS", - "type": "MIRROR", + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) + + //Create ACL rule + cfgDataAcl := []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{ + cmn.VALIDATE_ALL, + cmn.OP_CREATE, + "ACL_TABLE|TestACL14", + map[string]string{ + "stage": "INGRESS", + "type": "MIRROR", + }, + false, }, - false, - }, - } - - cvlErrInfo, err1 := cvSess.ValidateEditConfig(cfgDataAcl) + } - //Create ACL rule - cfgDataRule := []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{ - cmn.VALIDATE_ALL, - cmn.OP_CREATE, - "ACL_RULE|TestACL14|Rule1", - map[string]string{ - "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", - "SRC_IP": "10.1.1.1/32", - "L4_SRC_PORT": "1909", - "IP_PROTOCOL": "103", - "DST_IP": "20.2.2.2/32", - "L4_DST_PORT_RANGE": "9000-12000", + cvlErrInfo, err1 := cvSess.ValidateEditConfig(cfgDataAcl) + + //Create ACL rule + cfgDataRule := []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{ + cmn.VALIDATE_ALL, + cmn.OP_CREATE, + "ACL_RULE|TestACL14|Rule1", + map[string]string{ + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPV4", + "SRC_IP": "10.1.1.1/32", + "L4_SRC_PORT": "1909", + "IP_PROTOCOL": "103", + "DST_IP": "20.2.2.2/32", + "L4_DST_PORT_RANGE": "9000-12000", + }, + false, }, - false, - }, - } + } - cvlErrInfo, err2 := cvSess.ValidateEditConfig(cfgDataRule) + cvlErrInfo, err2 := cvSess.ValidateEditConfig(cfgDataRule) - if err1 != cvl.CVL_SUCCESS || err2 != cvl.CVL_SUCCESS { - t.Errorf("Config Validation failed -- error details %v", cvlErrInfo) + if err1 != cvl.CVL_SUCCESS || err2 != cvl.CVL_SUCCESS { + t.Errorf("Config Validation failed -- error details %v", cvlErrInfo) + } + cvl.ValidationSessClose(cvSess) } - cvl.ValidationSessClose(cvSess) } func TestValidateEditConfig_Create_DepData_In_MultiSess(t *testing.T) { - //Create ACL rule - Session 1 - cvSess, _ := NewCvlSession() - cfgDataAcl := []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{ - cmn.VALIDATE_ALL, - cmn.OP_CREATE, - "ACL_TABLE|TestACL16", - map[string]string{ - "stage": "INGRESS", - "type": "MIRROR", + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + + //Create ACL rule - Session 1 + cvSess, _ := NewCvlSession(d) + cfgDataAcl := []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{ + cmn.VALIDATE_ALL, + cmn.OP_CREATE, + "ACL_TABLE|TestACL16", + map[string]string{ + "stage": "INGRESS", + "type": "MIRROR", + }, + false, }, - false, - }, - } - - cvlErrInfo, err1 := cvSess.ValidateEditConfig(cfgDataAcl) - - cvl.ValidationSessClose(cvSess) + } - //Create ACL rule - Session 2, validation should fail - cvSess, _ = NewCvlSession() - cfgDataRule := []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{ - cmn.VALIDATE_ALL, - cmn.OP_CREATE, - "ACL_RULE|TestACL16|Rule1", - map[string]string{ - "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", - "SRC_IP": "10.1.1.1/32", - "L4_SRC_PORT": "1909", - "IP_PROTOCOL": "103", - "DST_IP": "20.2.2.2/32", - "L4_DST_PORT_RANGE": "9000-12000", + cvlErrInfo, err1 := cvSess.ValidateEditConfig(cfgDataAcl) + + cvl.ValidationSessClose(cvSess) + + //Create ACL rule - Session 2, validation should fail + cvSess, _ = NewCvlSession(d) + cfgDataRule := []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{ + cmn.VALIDATE_ALL, + cmn.OP_CREATE, + "ACL_RULE|TestACL16|Rule1", + map[string]string{ + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPV4", + "SRC_IP": "10.1.1.1/32", + "L4_SRC_PORT": "1909", + "IP_PROTOCOL": "103", + "DST_IP": "20.2.2.2/32", + "L4_DST_PORT_RANGE": "9000-12000", + }, + false, }, - false, - }, - } + } - _, err2 := cvSess.ValidateEditConfig(cfgDataRule) + _, err2 := cvSess.ValidateEditConfig(cfgDataRule) - cvl.ValidationSessClose(cvSess) + cvl.ValidationSessClose(cvSess) - if err1 != cvl.CVL_SUCCESS || err2 == cvl.CVL_SUCCESS { - t.Errorf("Config Validation failed -- error details %v", cvlErrInfo) + if err1 != cvl.CVL_SUCCESS || err2 == cvl.CVL_SUCCESS { + t.Errorf("Config Validation failed -- error details %v", cvlErrInfo) + } } - } func TestValidateEditConfig_Create_DepData_From_Redis_Negative11(t *testing.T) { @@ -2758,7 +2813,8 @@ func TestValidateConfig_Repeated_Keys_Positive(t *testing.T) { } }` - cvSess, _ := NewCvlSession() + d := getMDBInstance(hostDBName) + cvSess, _ := NewCvlSession(d) err := cvSess.ValidateConfig(jsonData) if err != cvl.CVL_SUCCESS { @@ -2782,7 +2838,8 @@ func TestValidateEditConfig_Delete_Entry_Then_Dep_Leafref_Positive(t *testing.T) }, }) - cvSess, _ := NewCvlSession() + d := getMDBInstance(hostDBName) + cvSess, _ := NewCvlSession(d) cfgDataAcl := []cmn.CVLEditConfigData{ cmn.CVLEditConfigData{ @@ -2931,7 +2988,8 @@ func TestValidateEditConfig_Delete_Create_Same_Entry_Positive(t *testing.T) { }, }) - cvSess, _ := NewCvlSession() + d := getMDBInstance(hostDBName) + cvSess, _ := NewCvlSession(d) cfgDataVlan := []cmn.CVLEditConfigData{ cmn.CVLEditConfigData{ @@ -2977,11 +3035,14 @@ func TestValidateEditConfig_Delete_Create_Same_Entry_Positive(t *testing.T) { } func TestValidateStartupConfig_Positive(t *testing.T) { - cvSess, _ := NewCvlSession() - if cvl.CVL_NOT_IMPLEMENTED != cvSess.ValidateStartupConfig("") { - t.Errorf("Not implemented yet.") + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) + if cvl.CVL_NOT_IMPLEMENTED != cvSess.ValidateStartupConfig("") { + t.Errorf("Not implemented yet.") + } + cvl.ValidationSessClose(cvSess) } - cvl.ValidationSessClose(cvSess) } func TestValidateIncrementalConfig_Positive(t *testing.T) { @@ -3018,7 +3079,8 @@ func TestValidateIncrementalConfig_Positive(t *testing.T) { //Prepare data in Redis setupTestData(t, existingDataMap) - cvSess, _ := NewCvlSession() + d := getMDBInstance(hostDBName) + cvSess, _ := NewCvlSession(d) jsonData := `{ "VLAN": { @@ -3052,29 +3114,38 @@ func TestValidateIncrementalConfig_Positive(t *testing.T) { // Validate key only func TestValidateKeys(t *testing.T) { - cvSess, _ := NewCvlSession() - if cvl.CVL_NOT_IMPLEMENTED != cvSess.ValidateKeys([]string{}) { - t.Errorf("Not implemented yet.") + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) + if cvl.CVL_NOT_IMPLEMENTED != cvSess.ValidateKeys([]string{}) { + t.Errorf("Not implemented yet.") + } + cvl.ValidationSessClose(cvSess) } - cvl.ValidationSessClose(cvSess) } // Validate key and data func TestValidateKeyData(t *testing.T) { - cvSess, _ := NewCvlSession() - if cvl.CVL_NOT_IMPLEMENTED != cvSess.ValidateKeyData("", "") { - t.Errorf("Not implemented yet.") + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) + if cvl.CVL_NOT_IMPLEMENTED != cvSess.ValidateKeyData("", "") { + t.Errorf("Not implemented yet.") + } + cvl.ValidationSessClose(cvSess) } - cvl.ValidationSessClose(cvSess) } // Validate key, field and value func TestValidateFields(t *testing.T) { - cvSess, _ := NewCvlSession() - if cvl.CVL_NOT_IMPLEMENTED != cvSess.ValidateFields("", "", "") { - t.Errorf("Not implemented yet.") + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) + if cvl.CVL_NOT_IMPLEMENTED != cvSess.ValidateFields("", "", "") { + t.Errorf("Not implemented yet.") + } + cvl.ValidationSessClose(cvSess) } - cvl.ValidationSessClose(cvSess) } func TestValidateEditConfig_Two_Updates_Positive(t *testing.T) { @@ -3209,7 +3280,8 @@ func TestValidateEditConfig_Use_Updated_Data_As_Create_DependentData_Positive(t }, }) - cvSess := NewTestSession(t) + d := getMDBInstance(hostDBName) + cvSess := NewTestSession(t, d) cfgData := []cmn.CVLEditConfigData{ cmn.CVLEditConfigData{ @@ -3352,169 +3424,189 @@ func TestValidateEditConfig_EmptyNode_Positive(t *testing.T) { } func TestSortDepTables(t *testing.T) { - cvSess, _ := NewCvlSession() - - result, _ := cvSess.SortDepTables([]string{"PORT", "ACL_RULE", "ACL_TABLE"}) + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) - expectedResult := []string{"ACL_RULE", "ACL_TABLE", "PORT"} + result, _ := cvSess.SortDepTables([]string{"PORT", "ACL_RULE", "ACL_TABLE"}) - if len(expectedResult) != len(result) { - t.Errorf("Validation failed, returned value = %v", result) - return - } + expectedResult := []string{"ACL_RULE", "ACL_TABLE", "PORT"} - for i := 0; i < len(expectedResult); i++ { - if result[i] != expectedResult[i] { + if len(expectedResult) != len(result) { t.Errorf("Validation failed, returned value = %v", result) - break + return } - } - cvl.ValidationSessClose(cvSess) + for i := 0; i < len(expectedResult); i++ { + if result[i] != expectedResult[i] { + t.Errorf("Validation failed, returned value = %v", result) + break + } + } + + cvl.ValidationSessClose(cvSess) + } } func TestSortDepTablesWithMultiListTargetRaw(t *testing.T) { - cvSess, _ := NewCvlSession() + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) - result, _ := cvSess.SortDepList([]string{"VLAN_SUB_INTERFACE", "OSPFV2_INTERFACE"}) + result, _ := cvSess.SortDepList([]string{"VLAN_SUB_INTERFACE", "OSPFV2_INTERFACE"}) - expectedResult := []string{"OSPFV2_INTERFACE", "VLAN_SUB_INTERFACE_IPADDR", "VLAN_SUB_INTERFACE"} + expectedResult := []string{"OSPFV2_INTERFACE", "VLAN_SUB_INTERFACE_IPADDR", "VLAN_SUB_INTERFACE"} - for i := 0; i < len(expectedResult); i++ { - if result[i] != expectedResult[i] { - t.Errorf("Validation failed, returned value = %v", result) - break + for i := 0; i < len(expectedResult); i++ { + if result[i] != expectedResult[i] { + t.Errorf("Validation failed, returned value = %v", result) + break + } } - } - cvl.ValidationSessClose(cvSess) + cvl.ValidationSessClose(cvSess) + } } func TestSortDepTablesWithMultiListTarget(t *testing.T) { - cvSess, _ := NewCvlSession() - - result, _ := cvSess.SortDepTables([]string{"VLAN_SUB_INTERFACE", "OSPFV2_INTERFACE"}) + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) - expectedResult := []string{"OSPFV2_INTERFACE", "VLAN_SUB_INTERFACE"} + result, _ := cvSess.SortDepTables([]string{"VLAN_SUB_INTERFACE", "OSPFV2_INTERFACE"}) - if len(expectedResult) != len(result) { - t.Errorf("Validation failed, returned value = %v", result) - return - } + expectedResult := []string{"OSPFV2_INTERFACE", "VLAN_SUB_INTERFACE"} - for i := 0; i < len(expectedResult); i++ { - if result[i] != expectedResult[i] { + if len(expectedResult) != len(result) { t.Errorf("Validation failed, returned value = %v", result) - break + return } - } - cvl.ValidationSessClose(cvSess) + for i := 0; i < len(expectedResult); i++ { + if result[i] != expectedResult[i] { + t.Errorf("Validation failed, returned value = %v", result) + break + } + } + cvl.ValidationSessClose(cvSess) + } } func TestGetOrderedTables(t *testing.T) { - cvSess, _ := NewCvlSession() - - result, _ := cvSess.GetOrderedTables("sonic-vlan") + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) - expectedResult := []string{"VLAN_MEMBER", "VLAN"} + result, _ := cvSess.GetOrderedTables("sonic-vlan") - if len(expectedResult) != len(result) { - t.Errorf("Validation failed, returned value = %v", result) - return - } + expectedResult := []string{"VLAN_MEMBER", "VLAN"} - for i := 0; i < len(expectedResult); i++ { - if result[i] != expectedResult[i] { + if len(expectedResult) != len(result) { t.Errorf("Validation failed, returned value = %v", result) - break + return } - } - cvl.ValidationSessClose(cvSess) + for i := 0; i < len(expectedResult); i++ { + if result[i] != expectedResult[i] { + t.Errorf("Validation failed, returned value = %v", result) + break + } + } + + cvl.ValidationSessClose(cvSess) + } } func TestGetOrderedDepTables(t *testing.T) { - cvSess, _ := NewCvlSession() - - result, _ := cvSess.GetOrderedDepTables("sonic-vlan", "VLAN") + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) - expectedResult := []string{"VLAN_MEMBER", "VLAN"} + result, _ := cvSess.GetOrderedDepTables("sonic-vlan", "VLAN") - if len(expectedResult) != len(result) { - t.Errorf("Validation failed, returned value = %v", result) - return - } + expectedResult := []string{"VLAN_MEMBER", "VLAN"} - for i := 0; i < len(expectedResult); i++ { - if result[i] != expectedResult[i] { + if len(expectedResult) != len(result) { t.Errorf("Validation failed, returned value = %v", result) - break + return } - } - cvl.ValidationSessClose(cvSess) + for i := 0; i < len(expectedResult); i++ { + if result[i] != expectedResult[i] { + t.Errorf("Validation failed, returned value = %v", result) + break + } + } + + cvl.ValidationSessClose(cvSess) + } } func TestGetDepTables(t *testing.T) { - cvSess, _ := NewCvlSession() + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) - result, _ := cvSess.GetDepTables("sonic-acl", "ACL_RULE") + result, _ := cvSess.GetDepTables("sonic-acl", "ACL_RULE") - expectedResult := []string{"ACL_RULE", "ACL_TABLE", "MIRROR_SESSION", "PORT", "PORTCHANNEL"} + expectedResult := []string{"ACL_RULE", "ACL_TABLE", "MIRROR_SESSION", "PORT", "PORTCHANNEL"} - sort.Strings(result) - sort.Strings(expectedResult) - if !reflect.DeepEqual(result, expectedResult) { - t.Errorf("Validation failed, returned value = %v", result) - } + sort.Strings(result) + sort.Strings(expectedResult) + if !reflect.DeepEqual(result, expectedResult) { + t.Errorf("Validation failed, returned value = %v", result) + } - cvl.ValidationSessClose(cvSess) + cvl.ValidationSessClose(cvSess) + } } func TestDependentOnExtension(t *testing.T) { - cvSess, _ := NewCvlSession() - defer cvl.ValidationSessClose(cvSess) - - // Test GetDepTables API - result, _ := cvSess.GetDepTables("sonic-spanning-tree", "STP_VLAN") - expectedResult := []string{"STP_VLAN", "VLAN", "STP", "PORT", "PORTCHANNEL"} - sort.Strings(result) - sort.Strings(expectedResult) - if !reflect.DeepEqual(result, expectedResult) { - t.Errorf("TestDependentOnExtension: Validation of GetDepTables failed, returned value = %v", result) - return - } + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) + defer cvl.ValidationSessClose(cvSess) + + // Test GetDepTables API + result, _ := cvSess.GetDepTables("sonic-spanning-tree", "STP_VLAN") + expectedResult := []string{"STP_VLAN", "VLAN", "STP", "PORT", "PORTCHANNEL"} + sort.Strings(result) + sort.Strings(expectedResult) + if !reflect.DeepEqual(result, expectedResult) { + t.Errorf("TestDependentOnExtension: Validation of GetDepTables failed, returned value = %v", result) + return + } - // Test GetOrderedDepTables API - result, _ = cvSess.GetOrderedDepTables("sonic-spanning-tree", "STP") - expectedResult = []string{"STP_PORT", "STP_VLAN", "STP"} - sort.Strings(result) - sort.Strings(expectedResult) - if !reflect.DeepEqual(result, expectedResult) { - t.Errorf("TestDependentOnExtension: Validation of GetOrderedDepTables failed, returned value = %v", result) - return - } + // Test GetOrderedDepTables API + result, _ = cvSess.GetOrderedDepTables("sonic-spanning-tree", "STP") + expectedResult = []string{"STP_PORT", "STP_VLAN", "STP"} + sort.Strings(result) + sort.Strings(expectedResult) + if !reflect.DeepEqual(result, expectedResult) { + t.Errorf("TestDependentOnExtension: Validation of GetOrderedDepTables failed, returned value = %v", result) + return + } - // Test GetOrderedTables API - result, _ = cvSess.GetOrderedTables("sonic-spanning-tree") - expectedResult = []string{"STP", "STP_PORT", "STP_VLAN", "STP_VLAN_PORT"} - sort.Strings(result) - sort.Strings(expectedResult) - if !reflect.DeepEqual(result, expectedResult) { - t.Errorf("TestDependentOnExtension: Validation of GetOrderedTables failed, returned value = %v", result) - return - } + // Test GetOrderedTables API + result, _ = cvSess.GetOrderedTables("sonic-spanning-tree") + expectedResult = []string{"STP", "STP_PORT", "STP_VLAN", "STP_VLAN_PORT"} + sort.Strings(result) + sort.Strings(expectedResult) + if !reflect.DeepEqual(result, expectedResult) { + t.Errorf("TestDependentOnExtension: Validation of GetOrderedTables failed, returned value = %v", result) + return + } - // Test SortDepTables API - result, _ = cvSess.SortDepTables([]string{"STP_VLAN", "STP", "STP_PORT"}) - expectedResult = []string{"STP_VLAN", "STP_PORT", "STP"} - sort.Strings(result) - sort.Strings(expectedResult) - if !reflect.DeepEqual(result, expectedResult) { - t.Errorf("TestDependentOnExtension: Validation of SortDepTables failed, returned value = %v", result) - return + // Test SortDepTables API + result, _ = cvSess.SortDepTables([]string{"STP_VLAN", "STP", "STP_PORT"}) + expectedResult = []string{"STP_VLAN", "STP_PORT", "STP"} + sort.Strings(result) + sort.Strings(expectedResult) + if !reflect.DeepEqual(result, expectedResult) { + t.Errorf("TestDependentOnExtension: Validation of SortDepTables failed, returned value = %v", result) + return + } } } @@ -3584,7 +3676,8 @@ func TestGetDepDataForDelete(t *testing.T) { }, }) - cvSess, _ := NewCvlSession() + d := getMDBInstance(hostDBName) + cvSess, _ := NewCvlSession(d) depEntries := cvSess.GetDepDataForDelete("PORT|Ethernet7") @@ -3601,46 +3694,49 @@ func TestGetDepDataForDelete(t *testing.T) { } func TestMaxElements_All_Entries_In_Request(t *testing.T) { - cvSess := NewTestSession(t) - - cfgData := []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{ - cmn.VALIDATE_ALL, - cmn.OP_CREATE, - "VXLAN_TUNNEL|tun1", - map[string]string{ - "src_ip": "20.1.1.1", + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess := NewTestSession(t, d) + + cfgData := []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{ + cmn.VALIDATE_ALL, + cmn.OP_CREATE, + "VXLAN_TUNNEL|tun1", + map[string]string{ + "src_ip": "20.1.1.1", + }, + false, }, - false, - }, - } + } - //Check addition of first element - cvlErrInfo, _ := cvSess.ValidateEditConfig(cfgData) - verifyErr(t, cvlErrInfo, Success) + //Check addition of first element + cvlErrInfo, _ := cvSess.ValidateEditConfig(cfgData) + verifyErr(t, cvlErrInfo, Success) - cfgData1 := []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{ - cmn.VALIDATE_ALL, - cmn.OP_CREATE, - "VXLAN_TUNNEL|tun2", - map[string]string{ - "src_ip": "30.1.1.1", + cfgData1 := []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{ + cmn.VALIDATE_ALL, + cmn.OP_CREATE, + "VXLAN_TUNNEL|tun2", + map[string]string{ + "src_ip": "30.1.1.1", + }, + false, }, - false, - }, - } + } - //Try to validate addition of second element - cvlErrInfo, _ = cvSess.ValidateEditConfig(cfgData1) - verifyErr(t, cvlErrInfo, CVLErrorInfo{ - ErrCode: CVL_SYNTAX_ERROR, - TableName: "VXLAN_TUNNEL", - Keys: []string{"tun2"}, - Msg: "Max elements limit reached", - ConstraintErrMsg: "Max elements limit 1 reached", - ErrAppTag: "too-many-elements", - }) + //Try to validate addition of second element + cvlErrInfo, _ = cvSess.ValidateEditConfig(cfgData1) + verifyErr(t, cvlErrInfo, CVLErrorInfo{ + ErrCode: CVL_SYNTAX_ERROR, + TableName: "VXLAN_TUNNEL", + Keys: []string{"tun2"}, + Msg: "Max elements limit reached", + ConstraintErrMsg: "Max elements limit 1 reached", + ErrAppTag: "too-many-elements", + }) + } } func TestMaxElements_Entries_In_Redis(t *testing.T) { @@ -3674,7 +3770,8 @@ func TestMaxElements_Entries_In_Redis(t *testing.T) { }) t.Run("delete_and_create", func(tt *testing.T) { - cvSess := NewTestSession(tt) + d := getMDBInstance(hostDBName) + cvSess := NewTestSession(tt, d) cfgData1 := []CVLEditConfigData{{ cmn.VALIDATE_ALL, @@ -3715,53 +3812,56 @@ func TestMaxElements_Entries_In_Redis(t *testing.T) { } func TestValidateEditConfig_Two_Create_Requests_Positive(t *testing.T) { - cvSess := NewTestSession(t) - - cfgDataVlan := []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{ - cmn.VALIDATE_ALL, - cmn.OP_CREATE, - "VLAN|Vlan21", - map[string]string{ - "vlanid": "21", + for _, dbName := range MdbNames { + d := getMDBInstance(dbName) + cvSess := NewTestSession(t, d) + + cfgDataVlan := []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{ + cmn.VALIDATE_ALL, + cmn.OP_CREATE, + "VLAN|Vlan21", + map[string]string{ + "vlanid": "21", + }, + false, }, - false, - }, - } + } - cvlErrInfo, _ := cvSess.ValidateEditConfig(cfgDataVlan) - if !verifyErr(t, cvlErrInfo, Success) { - return - } + cvlErrInfo, _ := cvSess.ValidateEditConfig(cfgDataVlan) + if !verifyErr(t, cvlErrInfo, Success) { + return + } - cfgDataVlan = []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{ - cmn.VALIDATE_NONE, - cmn.OP_CREATE, - "VLAN|Vlan21", - map[string]string{ - "vlanid": "21", - }, - false, - }, - cmn.CVLEditConfigData{ - cmn.VALIDATE_ALL, - cmn.OP_CREATE, - "STP_VLAN|Vlan21", - map[string]string{ - "enabled": "true", - "forward_delay": "15", - "hello_time": "2", - "max_age": "20", - "priority": "327", - "vlanid": "21", + cfgDataVlan = []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{ + cmn.VALIDATE_NONE, + cmn.OP_CREATE, + "VLAN|Vlan21", + map[string]string{ + "vlanid": "21", + }, + false, + }, + cmn.CVLEditConfigData{ + cmn.VALIDATE_ALL, + cmn.OP_CREATE, + "STP_VLAN|Vlan21", + map[string]string{ + "enabled": "true", + "forward_delay": "15", + "hello_time": "2", + "max_age": "20", + "priority": "327", + "vlanid": "21", + }, + false, }, - false, - }, - } + } - cvlErrInfo, _ = cvSess.ValidateEditConfig(cfgDataVlan) - verifyErr(t, cvlErrInfo, Success) + cvlErrInfo, _ = cvSess.ValidateEditConfig(cfgDataVlan) + verifyErr(t, cvlErrInfo, Success) + } } func TestValidateEditConfig_Two_Delete_Requests_Positive(t *testing.T) { @@ -3783,7 +3883,8 @@ func TestValidateEditConfig_Two_Delete_Requests_Positive(t *testing.T) { }, }) - cvSess := NewTestSession(t) + d := getMDBInstance(hostDBName) + cvSess := NewTestSession(t, d) cfgDataVlan := []cmn.CVLEditConfigData{ cmn.CVLEditConfigData{ @@ -3848,7 +3949,8 @@ func TestValidateEditConfig_Multi_Delete_MultiKey_Same_Session_Positive(t *testi }, }, }) - cvSess := NewTestSession(t) + d := getMDBInstance(hostDBName) + cvSess := NewTestSession(t, d) cfgData := []cmn.CVLEditConfigData{ cmn.CVLEditConfigData{ @@ -3953,46 +4055,49 @@ func TestValidateEditConfig_Update_Leaf_List_Max_Elements_Negative(t *testing.T) } func TestValidationTimeStats(t *testing.T) { - cvl.ClearValidationTimeStats() + for _, dbName := range MdbNames { + cvl.ClearValidationTimeStats() - stats := cvl.GetValidationTimeStats() + stats := cvl.GetValidationTimeStats() - if stats.Hits != 0 || stats.Time != 0 || stats.Peak != 0 { - t.Errorf("TestValidationTimeStats : clearing stats failed") - return - } + if stats.Hits != 0 || stats.Time != 0 || stats.Peak != 0 { + t.Errorf("TestValidationTimeStats : clearing stats failed") + return + } - cvSess, _ := NewCvlSession() + d := getMDBInstance(dbName) + cvSess, _ := NewCvlSession(d) - cfgData := []cmn.CVLEditConfigData{ - cmn.CVLEditConfigData{ - cmn.VALIDATE_ALL, - cmn.OP_CREATE, - "VRF|VrfTest", - map[string]string{ - "fallback": "true", + cfgData := []cmn.CVLEditConfigData{ + cmn.CVLEditConfigData{ + cmn.VALIDATE_ALL, + cmn.OP_CREATE, + "VRF|VrfTest", + map[string]string{ + "fallback": "true", + }, + false, }, - false, - }, - } + } - cvSess.ValidateEditConfig(cfgData) + cvSess.ValidateEditConfig(cfgData) - cvl.ValidationSessClose(cvSess) + cvl.ValidationSessClose(cvSess) - stats = cvl.GetValidationTimeStats() + stats = cvl.GetValidationTimeStats() - if stats.Hits == 0 || stats.Time == 0 || stats.Peak == 0 { - t.Errorf("TestValidationTimeStats : getting stats failed") - return - } + if stats.Hits == 0 || stats.Time == 0 || stats.Peak == 0 { + t.Errorf("TestValidationTimeStats : getting stats failed") + return + } - //Clear stats again and check - cvl.ClearValidationTimeStats() + //Clear stats again and check + cvl.ClearValidationTimeStats() - stats = cvl.GetValidationTimeStats() + stats = cvl.GetValidationTimeStats() - if stats.Hits != 0 || stats.Time != 0 || stats.Peak != 0 { - t.Errorf("TestValidationTimeStats : clearing stats failed") + if stats.Hits != 0 || stats.Time != 0 || stats.Peak != 0 { + t.Errorf("TestValidationTimeStats : clearing stats failed") + } } } diff --git a/cvl/internal/util/util.go b/cvl/internal/util/util.go index 34511946e..2fd36a5f4 100644 --- a/cvl/internal/util/util.go +++ b/cvl/internal/util/util.go @@ -41,6 +41,7 @@ static void ly_set_log_callback(int enable) { */ import "C" import ( + "bufio" "encoding/json" "fmt" "io" @@ -57,6 +58,7 @@ import ( set "github.com/Workiva/go-datastructures/set" "github.com/go-redis/redis/v7" log "github.com/golang/glog" + "path/filepath" ) var CVL_SCHEMA string = "schema/" @@ -66,6 +68,22 @@ const CVL_LOG_FILE = "/tmp/cvl.log" const SONIC_DB_CONFIG_FILE string = "/var/run/redis/sonic-db/database_config.json" const ENV_VAR_SONIC_DB_CONFIG_FILE = "DB_CONFIG_PATH" +var DEFAULT_ASIC_CONF_FILE_PATH = "/usr/share/sonic/platform/asic.conf" +var DEFAULT_GLOBALDB_FILE_PATH = "/var/run/redis/sonic-db/database_global.json" +var NumAsic = 1 +var multiDbsConfigMap = make(map[string]map[string]interface{}) + +type DbGlobal struct { + Includes []DbInclude `json:"INCLUDES"` + Version string `json:"VERSION"` + KeySeperator string `json:"KEY_SEPERATOR"` +} + +type DbInclude struct { + Include string `json:"include"` + Namespace string `json:"namespace"` +} + var sonic_db_config = make(map[string]interface{}) type Formatter func(string) string @@ -92,12 +110,54 @@ func init() { logFileMutex = &sync.Mutex{} //Initialize DB settings - dbCfgInit() + if path, ok := os.LookupEnv("ASIC_CONFIG_PATH"); ok { + DEFAULT_ASIC_CONF_FILE_PATH = path + } + if path, ok := os.LookupEnv("DB_GLOBAL_CONFIG_PATH"); ok { + DEFAULT_GLOBALDB_FILE_PATH = path + } + + NumAsic = getNumAsic() + if !IsMultiAsic() { + dbCfgInit(SONIC_DB_CONFIG_FILE, "host") + } else { + globalDbInfo := loadGlobalDatabase(DEFAULT_GLOBALDB_FILE_PATH) + for namespace, path := range globalDbInfo { + dbCfgInit(path, namespace) + } + } + redisOptions = &redis.Options{} formatterFunctionsMap = make(map[string]Formatter) } +func loadGlobalDatabase(globalDbFilePath string) map[string]string { + var globalDbCfg DbGlobal + + data, err := os.ReadFile(globalDbFilePath) + if err != nil { + panic(err) + } else { + err = json.Unmarshal([]byte(data), &globalDbCfg) + if err != nil { + panic(err) + } + } + + var dbConfigMap = make(map[string]string) + var pwd = filepath.Dir(globalDbFilePath) + "/" + for i := 0; i < len(globalDbCfg.Includes); i++ { + if i == 0 { + dbConfigMap["host"] = pwd + globalDbCfg.Includes[0].Include + } else { + include := globalDbCfg.Includes[i] + dbConfigMap[include.Namespace] = pwd + include.Include + } + } + return dbConfigMap +} + var cvlCfgMap map[string]string var isLogToFile bool var logFileName string = CVL_LOG_FILE @@ -165,6 +225,46 @@ var Tracing bool = false var traceFlags uint16 = 0 +func IsMultiAsic() bool { + return NumAsic > 0 +} + +func getNumAsic() int { + file, err := os.Open(DEFAULT_ASIC_CONF_FILE_PATH) + if err != nil { + log.Warning("Cannot find the asic.conf file, set num_asic to 1 by default") + return 1 + } + + defer file.Close() + + scanner := bufio.NewScanner(file) + scanner.Split(bufio.ScanLines) + var text []string + for scanner.Scan() { + text = append(text, scanner.Text()) + } + + var numAsics = 1 + for _, line := range text { + tokens := strings.Split(line, "=") + if len(tokens) != 2 { + continue + } + + if strings.ToLower(tokens[0]) == "num_asic" { + num, err := strconv.Atoi(tokens[1]) + if err != nil { + log.Warning("invalid line in asic.config") + continue + } + numAsics = num + } + } + + return numAsics +} + func SetTrace(on bool) { if on { Tracing = true @@ -453,7 +553,8 @@ func SkipSemanticValidation() bool { // Function to read Redis DB configuration from file. // In absence of the file, it uses default config for CONFIG_DB // so that CVL UT will pass in development environment. -func dbCfgInit() { +func dbCfgInit(dbConfigPath string, multiDbName string) { + var sonic_db_config = make(map[string]interface{}) defaultDBConfig := `{ "INSTANCES": { "redis":{ @@ -478,8 +579,8 @@ func dbCfgInit() { dbCfgFile := "" //Check if multi-db config file is present - if _, errF := os.Stat(SONIC_DB_CONFIG_FILE); !os.IsNotExist(errF) { - dbCfgFile = SONIC_DB_CONFIG_FILE + if _, errF := os.Stat(dbConfigPath); !os.IsNotExist(errF) { + dbCfgFile = dbConfigPath } else { //Check if multi-db config file is specified in environment if fileName := os.Getenv(ENV_VAR_SONIC_DB_CONFIG_FILE); fileName != "" { @@ -509,10 +610,12 @@ func dbCfgInit() { panic(err) } } + multiDbsConfigMap[multiDbName] = sonic_db_config } // Get list of DB -func getDbList() map[string]interface{} { +func getDbList(multiDbName string) map[string]interface{} { + var sonic_db_config = multiDbsConfigMap[multiDbName] db_list, ok := sonic_db_config["DATABASES"].(map[string]interface{}) if !ok { panic(fmt.Errorf("DATABASES' is not valid key in %s!", @@ -523,6 +626,8 @@ func getDbList() map[string]interface{} { // Get DB instance based on given DB name func getDbInst(dbName string) map[string]interface{} { + dbName, multiDbName := getDBNames(dbName) + var sonic_db_config = multiDbsConfigMap[multiDbName] db, ok := sonic_db_config["DATABASES"].(map[string]interface{})[dbName] if !ok { panic(fmt.Errorf("database name '%v' is not valid in %s !", @@ -543,7 +648,8 @@ func getDbInst(dbName string) map[string]interface{} { // GetDbSeparator Get DB separator based on given DB name func GetDbSeparator(dbName string) string { - db_list := getDbList() + dbName, multiDbName := getDBNames(dbName) + db_list := getDbList(multiDbName) separator, ok := db_list[dbName].(map[string]interface{})["separator"] if !ok { panic(fmt.Errorf("'separator' is not a valid field in %s !", @@ -554,7 +660,8 @@ func GetDbSeparator(dbName string) string { // GetDbId Get DB id on given db name func GetDbId(dbName string) int { - db_list := getDbList() + dbName, multiDbName := getDBNames(dbName) + db_list := getDbList(multiDbName) id, ok := db_list[dbName].(map[string]interface{})["id"] if !ok { panic(fmt.Errorf("'id' is not a valid field in %s !", @@ -594,6 +701,15 @@ func GetDbPassword(dbName string) string { return password } +func getDbPort(dbName string) int { + inst := getDbInst(dbName) + port, ok := inst["port"] + if !ok { + panic(fmt.Errorf("'port' is not a valid field")) + } + return int(port.(float64)) +} + // GetDbTcpAddr Get DB TCP endpoint func GetDbTcpAddr(dbName string) string { inst := getDbInst(dbName) @@ -602,12 +718,7 @@ func GetDbTcpAddr(dbName string) string { panic(fmt.Errorf("'hostname' is not a valid field in %s !", SONIC_DB_CONFIG_FILE)) } - - port, ok1 := inst["port"] - if !ok1 { - panic(fmt.Errorf("'port' is not a valid field in %s !", - SONIC_DB_CONFIG_FILE)) - } + port := getDbPort(dbName) return fmt.Sprintf("%v:%v", hostname, port) } @@ -701,7 +812,16 @@ func UpdateRedisOptions(opts *redis.Options) { redisOptions = opts } +func getDBNames(str string) (string, string) { + if strings.Contains(str, ".") { + parts := strings.SplitN(str, ".", 2) + return parts[0], parts[1] + } + return str, "host" +} + func getRedisOptions(dbName string) *redis.Options { + // dbName = dbName + Namespace var dbNetwork, dbAddr string // need to create copy of redisOptions because few attributes diff --git a/models/yang/annotations/openconfig-channel-monitor-annot.yang b/models/yang/annotations/openconfig-channel-monitor-annot.yang index 9448af936..41680f623 100644 --- a/models/yang/annotations/openconfig-channel-monitor-annot.yang +++ b/models/yang/annotations/openconfig-channel-monitor-annot.yang @@ -5,115 +5,117 @@ module openconfig-channel-monitor-annot { namespace "http://openconfig.net/yang/annotation/oc-chan-monitor-annot"; prefix "oc-chan-monitor-annot"; + import sonic-extensions { prefix sonic-ext; } import openconfig-extensions { prefix oc-ext; } + import openconfig-interfaces { prefix oc-if; } + import openconfig-platform { prefix oc-platform; } import openconfig-transport-types { prefix oc-opt-types; } import openconfig-channel-monitor { prefix oc-chan-monitor; } deviation /oc-chan-monitor:channel-monitors { deviate add { - sonic-ext:table-name "OTN_OCM"; + sonic-ext:get-namespace "ocm_get_namespace_xfmr"; } } deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor { deviate add { - sonic-ext:key-transformer "oc_name_key_xfmr"; - sonic-ext:table-transformer "otn_table_xfmr"; + sonic-ext:table-name "OCM"; + sonic-ext:key-transformer "ocm_name_key_xfmr"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:config { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels { deviate add { + sonic-ext:db-name "STATE_DB"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:config/oc-chan-monitor:monitor-port { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel { deviate add { - sonic-ext:field-name "monitor-port"; + sonic-ext:table-name "OCM_CHANNEL_TABLE"; + sonic-ext:key-transformer "ocm_channel_key_xfmr"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:config/oc-chan-monitor:name { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state { deviate add { - sonic-ext:field-transformer "oc_name_field_xfmr"; + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OCM_CHANNEL_TABLE"; + sonic-ext:key-transformer "ocm_channel_key_xfmr"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:state { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state/oc-chan-monitor:lower-frequency { deviate add { - sonic-ext:db-name "STATE_DB"; - sonic-ext:table-name "OTN_OCM_TABLE"; - sonic-ext:key-transformer "oc_name_key_xfmr"; + sonic-ext:field-transformer "ocm_lower_frequency_field_xfmr"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:state/oc-chan-monitor:monitor-port { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state/oc-chan-monitor:upper-frequency { deviate add { - sonic-ext:field-name "monitor-port"; + sonic-ext:field-transformer "ocm_upper_frequency_field_xfmr"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:state/oc-chan-monitor:name { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state/oc-chan-monitor:power { deviate add { - sonic-ext:field-transformer "oc_name_field_xfmr"; + sonic-ext:field-name "power"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state/oc-chan-monitor:target-power { deviate add { - sonic-ext:table-transformer "otn_table_xfmr"; + sonic-ext:field-name "target-power"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:lower-frequency { deviate add { - sonic-ext:db-name "STATE_DB"; - sonic-ext:table-name "OTN_OCM_CHANNEL_TABLE"; - sonic-ext:table-transformer "otn_table_xfmr"; - sonic-ext:key-transformer "ocm_channel_key_xfmr"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:lower-frequency { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:upper-frequency { deviate add { - sonic-ext:field-name "lower-frequency"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:upper-frequency { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:name { deviate add { - sonic-ext:field-name "upper-frequency"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:config { deviate add { } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state/oc-chan-monitor:upper-frequency { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:config/oc-chan-monitor:name { deviate add { } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state/oc-chan-monitor:power { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:config/oc-chan-monitor:monitor-port { deviate add { - sonic-ext:field-name "power"; + sonic-ext:field-name "monitor-port"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state/oc-chan-monitor:target-power { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:state { deviate add { - sonic-ext:field-name "target-power"; + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OCM_TABLE"; + sonic-ext:key-transformer "ocm_name_key_xfmr"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:channels/oc-chan-monitor:channel/oc-chan-monitor:state/oc-chan-monitor:lower-frequency { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:state/oc-chan-monitor:monitor-port { deviate add { + sonic-ext:field-name "monitor-port"; } } - deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:name { + deviation /oc-chan-monitor:channel-monitors/oc-chan-monitor:channel-monitor/oc-chan-monitor:state/oc-chan-monitor:name { deviate add { } } diff --git a/models/yang/annotations/openconfig-optical-amplifier-annot.yang b/models/yang/annotations/openconfig-optical-amplifier-annot.yang index 0061ef5aa..b4dd342a6 100644 --- a/models/yang/annotations/openconfig-optical-amplifier-annot.yang +++ b/models/yang/annotations/openconfig-optical-amplifier-annot.yang @@ -10,65 +10,67 @@ module openconfig-optical-amplifier-annot { deviation /oc-opt-amp:optical-amplifier { deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:get-namespace "oa_name_get_namespace_xfmr"; } } deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers { deviate add { - sonic-ext:table-name "OTN_OA"; + sonic-ext:table-name "AMPLIFIER"; } } deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier { deviate add { - sonic-ext:key-transformer "oc_name_key_xfmr"; - sonic-ext:table-transformer "otn_table_xfmr"; + sonic-ext:key-transformer "oa_name_key_xfmr"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:name { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config { deviate add { } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:target-gain-tilt { deviate add { + sonic-ext:field-name "target-gain-tilt"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:name { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:min-gain { deviate add { - sonic-ext:field-transformer "oc_name_field_xfmr"; + sonic-ext:field-name "min-gain"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:type { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:max-gain { deviate add { - sonic-ext:field-name "type"; + sonic-ext:field-name "max-gain"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:target-gain { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:max-output-power { deviate add { - sonic-ext:field-name "target-gain"; + sonic-ext:field-name "max-output-power"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:min-gain { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:target-output-power { deviate add { - sonic-ext:field-name "min-gain"; + sonic-ext:field-name "target-output-power"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:max-gain { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:amp-mode { deviate add { - sonic-ext:field-name "max-gain"; + sonic-ext:field-name "amp-mode"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:target-gain-tilt { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:target-gain { deviate add { - sonic-ext:field-name "target-gain-tilt"; + sonic-ext:field-name "target-gain"; } } @@ -78,21 +80,21 @@ module openconfig-optical-amplifier-annot { } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:amp-mode { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:name { deviate add { - sonic-ext:field-name "amp-mode"; + sonic-ext:field-transformer "oa_name_field_xfmr"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:target-output-power { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:fiber-type-profile { deviate add { - sonic-ext:field-name "target-output-power"; + sonic-ext:field-name "fiber-type-profile"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:max-output-power { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:type { deviate add { - sonic-ext:field-name "max-output-power"; + sonic-ext:field-name "type"; } } @@ -102,23 +104,23 @@ module openconfig-optical-amplifier-annot { } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:config/oc-opt-amp:fiber-type-profile { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state { deviate add { - sonic-ext:field-name "fiber-type-profile"; + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "AMPLIFIER_TABLE"; + sonic-ext:key-transformer "oa_name_key_xfmr"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:ingress-port { deviate add { - sonic-ext:db-name "STATE_DB"; - sonic-ext:table-name "OTN_OA_TABLE"; - sonic-ext:key-transformer "oc_name_key_xfmr"; + sonic-ext:field-name "ingress-port"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:name { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:target-gain-tilt { deviate add { - sonic-ext:field-transformer "oc_name_field_xfmr"; + sonic-ext:field-name "target-gain-tilt"; } } @@ -128,34 +130,53 @@ module openconfig-optical-amplifier-annot { } } + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:gain-range { + deviate add { + sonic-ext:field-name "gain-range"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:fiber-type-profile { + deviate add { + sonic-ext:field-name "fiber-type-profile"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:name { + deviate add { + sonic-ext:field-transformer "oa_name_field_xfmr"; + } + } + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:target-gain { deviate add { sonic-ext:field-name "target-gain"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:min-gain { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:component { deviate add { - sonic-ext:field-name "min-gain"; + sonic-ext:field-name "component"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:max-gain { + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:target-output-power { deviate add { - sonic-ext:field-name "max-gain"; + sonic-ext:field-name "target-output-power"; } } - - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:target-gain-tilt { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:max-output-power { deviate add { - sonic-ext:field-name "target-gain-tilt"; + sonic-ext:field-name "max-output-power"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:gain-range { + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:egress-port { deviate add { - sonic-ext:field-name "gain-range"; + sonic-ext:field-name "egress-port"; } } @@ -165,237 +186,731 @@ module openconfig-optical-amplifier-annot { } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:target-output-power { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:enabled { deviate add { - sonic-ext:field-name "target-output-power"; + sonic-ext:field-name "enabled"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:max-output-power { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:name { deviate add { - sonic-ext:field-name "max-output-power"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:enabled { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels { deviate add { - sonic-ext:field-name "enabled"; + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OSC_TABLE"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:fiber-type-profile { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel { deviate add { - sonic-ext:field-name "fiber-type-profile"; + sonic-ext:key-transformer "osc_key_xfmr"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:component { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:config { deviate add { - sonic-ext:field-name "component"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:ingress-port { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:config/oc-opt-amp:interface { deviate add { - sonic-ext:field-name "ingress-port"; + sonic-ext:field-transformer "osc_interface_field_xfmr"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:egress-port { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state { deviate add { - sonic-ext:field-name "egress-port"; + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OSC_TABLE"; + sonic-ext:key-transformer "osc_key_xfmr"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-frequency { deviate add { + sonic-ext:field-name "output-frequency"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain/oc-opt-amp:instant { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:interface { deviate add { - sonic-ext:field-name "actual-gain"; + sonic-ext:field-transformer "osc_interface_field_xfmr"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain-tilt { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:interface { deviate add { } - } - - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain-tilt/oc-opt-amp:instant { + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-power { deviate add { - sonic-ext:field-name "actual-gain-tilt"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OSC"; + sonic-ext:key-transformer "osc_output_power_counter_key_xfmr"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-total { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-power/oc-opt-amp:instant { deviate add { + sonic-ext:field-name "instant"; } - } - - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-total/oc-opt-amp:instant { + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-power/oc-opt-amp:avg { deviate add { - sonic-ext:field-name "input-power-total"; + sonic-ext:field-name "avg"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-c-band { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-power/oc-opt-amp:min { deviate add { + sonic-ext:field-name "min"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-c-band/oc-opt-amp:instant { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-power/oc-opt-amp:max { deviate add { - sonic-ext:field-name "input-power-c-band"; + sonic-ext:field-name "max"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-l-band { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-power/oc-opt-amp:interval { deviate add { + sonic-ext:field-name "interval"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-l-band/oc-opt-amp:instant { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-power/oc-opt-amp:min-time { deviate add { - sonic-ext:field-name "input-power-l-band"; + sonic-ext:field-name "min-time"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-total { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-power/oc-opt-amp:max-time { deviate add { + sonic-ext:field-name "max-time"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-total/oc-opt-amp:instant { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:laser-bias-current { deviate add { - sonic-ext:field-name "output-power-total"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OSC"; + sonic-ext:key-transformer "osc_laser_bias_current_counter_key_xfmr"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-c-band { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:instant { deviate add { + sonic-ext:field-name "instant"; } - } - - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-c-band/oc-opt-amp:instant { + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:min { deviate add { - sonic-ext:field-name "output-power-c-band"; + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:input-power { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OSC"; + sonic-ext:key-transformer "osc_input_power_counter_key_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:input-power/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:input-power/oc-opt-amp:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:input-power/oc-opt-amp:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:input-power/oc-opt-amp:max { + deviate add { + sonic-ext:field-name "max"; } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:input-power/oc-opt-amp:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:input-power/oc-opt-amp:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:input-power/oc-opt-amp:max-time { + deviate add { + sonic-ext:field-name "max-time"; } } deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-l-band { deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "AMPLIFIER"; + sonic-ext:key-transformer "oa_counter_output_powerL_key_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-l-band/oc-opt-amp:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-l-band/oc-opt-amp:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-l-band/oc-opt-amp:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-l-band/oc-opt-amp:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-l-band/oc-opt-amp:max-time { + deviate add { + sonic-ext:field-name "max-time"; } } deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-l-band/oc-opt-amp:instant { deviate add { - sonic-ext:field-name "output-power-l-band"; + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-l-band/oc-opt-amp:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:optical-return-loss { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "AMPLIFIER"; + sonic-ext:key-transformer "oa_counter_optical_return_loss_key_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:optical-return-loss/oc-opt-amp:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:optical-return-loss/oc-opt-amp:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:optical-return-loss/oc-opt-amp:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:optical-return-loss/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:optical-return-loss/oc-opt-amp:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:optical-return-loss/oc-opt-amp:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:optical-return-loss/oc-opt-amp:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:min-gain { + deviate add { + sonic-ext:field-name "min-gain"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-c-band { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "AMPLIFIER"; + sonic-ext:key-transformer "oa_counter_output_powerC_key_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-c-band/oc-opt-amp:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-c-band/oc-opt-amp:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-c-band/oc-opt-amp:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-c-band/oc-opt-amp:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-c-band/oc-opt-amp:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-c-band/oc-opt-amp:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-c-band/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "instant"; } } deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:laser-bias-current { deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "AMPLIFIER"; + sonic-ext:key-transformer "oa_counter_laser_bias_key_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:max-time { + deviate add { + sonic-ext:field-name "max-time"; } } deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:instant { deviate add { - sonic-ext:field-name "laser-bias-current"; + sonic-ext:field-name "instant"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:optical-return-loss { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:avg { deviate add { + sonic-ext:field-name "avg"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:optical-return-loss/oc-opt-amp:instant { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:min { deviate add { - sonic-ext:field-name "optical-return-loss"; + sonic-ext:field-name "min"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-c-band { deviate add { - sonic-ext:table-name "OTN_OSC"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "AMPLIFIER"; + sonic-ext:key-transformer "oa_counter_input_powerC_key_xfmr"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-c-band/oc-opt-amp:instant { deviate add { - sonic-ext:key-transformer "osc_key_xfmr"; - sonic-ext:table-transformer "otn_table_xfmr"; + sonic-ext:field-name "instant"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:interface { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-c-band/oc-opt-amp:avg { deviate add { + sonic-ext:field-name "avg"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:config { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-c-band/oc-opt-amp:min { deviate add { + sonic-ext:field-name "min"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:config/oc-opt-amp:interface { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-c-band/oc-opt-amp:max { deviate add { - sonic-ext:field-transformer "osc_interface_xfmr"; + sonic-ext:field-name "max"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-c-band/oc-opt-amp:interval { deviate add { - sonic-ext:db-name "STATE_DB"; - sonic-ext:table-name "OTN_OSC_TABLE"; - sonic-ext:key-transformer "osc_key_xfmr"; + sonic-ext:field-name "interval"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:interface { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-c-band/oc-opt-amp:min-time { deviate add { - sonic-ext:field-transformer "osc_interface_xfmr"; + sonic-ext:field-name "min-time"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:input-power { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-c-band/oc-opt-amp:max-time { deviate add { + sonic-ext:field-name "max-time"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:input-power/oc-opt-amp:instant { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:gain-range { deviate add { - sonic-ext:field-name "input-power"; + sonic-ext:field-name "gain-range"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-power { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-total { deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "AMPLIFIER"; + sonic-ext:key-transformer "oa_counter_output_power_total_key_xfmr"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-power/oc-opt-amp:instant { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-total/oc-opt-amp:max-time { deviate add { - sonic-ext:field-name "output-power"; + sonic-ext:field-name "max-time"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:laser-bias-current { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-total/oc-opt-amp:instant { deviate add { + sonic-ext:field-name "instant"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:laser-bias-current/oc-opt-amp:instant { + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-total/oc-opt-amp:avg { deviate add { - sonic-ext:field-name "laser-bias-current"; + sonic-ext:field-name "avg"; } } - deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:supervisory-channels/oc-opt-amp:supervisory-channel/oc-opt-amp:state/oc-opt-amp:output-frequency { + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-total/oc-opt-amp:min { deviate add { - sonic-ext:field-name "output-frequency"; + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-total/oc-opt-amp:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-total/oc-opt-amp:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:output-power-total/oc-opt-amp:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-total { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "AMPLIFIER"; + sonic-ext:key-transformer "oa_counter_input_power_total_key_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-total/oc-opt-amp:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-total/oc-opt-amp:min-time { + deviate add { + sonic-ext:field-name "min-time"; } } + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-total/oc-opt-amp:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-total/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-total/oc-opt-amp:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-total/oc-opt-amp:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-total/oc-opt-amp:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "AMPLIFIER"; + sonic-ext:key-transformer "oa_counter_actual_gain_key_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain/oc-opt-amp:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain/oc-opt-amp:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain/oc-opt-amp:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain/oc-opt-amp:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain/oc-opt-amp:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain/oc-opt-amp:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-l-band { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "AMPLIFIER"; + sonic-ext:key-transformer "oa_counter_input_powerL_key_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-l-band/oc-opt-amp:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-l-band/oc-opt-amp:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-l-band/oc-opt-amp:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-l-band/oc-opt-amp:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-l-band/oc-opt-amp:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-l-band/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:input-power-l-band/oc-opt-amp:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:max-gain { + deviate add { + sonic-ext:field-name "max-gain"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain-tilt { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "AMPLIFIER"; + sonic-ext:key-transformer "oa_counter_actual_gain_tilt_key_xfmr"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain-tilt/oc-opt-amp:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain-tilt/oc-opt-amp:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain-tilt/oc-opt-amp:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain-tilt/oc-opt-amp:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain-tilt/oc-opt-amp:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain-tilt/oc-opt-amp:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-amp:optical-amplifier/oc-opt-amp:amplifiers/oc-opt-amp:amplifier/oc-opt-amp:state/oc-opt-amp:actual-gain-tilt/oc-opt-amp:min { + deviate add { + sonic-ext:field-name "min"; + } + } } + diff --git a/models/yang/annotations/openconfig-optical-attenuator-annot.yang b/models/yang/annotations/openconfig-optical-attenuator-annot.yang index c7d0bbd06..1901b77f5 100644 --- a/models/yang/annotations/openconfig-optical-attenuator-annot.yang +++ b/models/yang/annotations/openconfig-optical-attenuator-annot.yang @@ -1,154 +1,278 @@ module openconfig-optical-attenuator-annot { - yang-version "1"; - - namespace "http://openconfig.net/yang/annotation/oc-opt-att-annot"; - prefix "oc-opt-att-annot"; - - import sonic-extensions { prefix sonic-ext; } - import openconfig-optical-attenuator { prefix oc-opt-att; } - - deviation /oc-opt-att:optical-attenuator { - deviate add { - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators { - deviate add { - sonic-ext:table-name "OTN_ATTENUATOR"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator { - deviate add { - sonic-ext:key-transformer "oc_name_key_xfmr"; - sonic-ext:table-transformer "otn_table_xfmr"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config { - deviate add { - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:name { - deviate add { - sonic-ext:field-transformer "oc_name_field_xfmr"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:attenuation-mode { - deviate add { - sonic-ext:field-name "attenuation-mode"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:target-output-power { - deviate add { - sonic-ext:field-name "target-output-power"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:attenuation { - deviate add { - sonic-ext:field-name "attenuation"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:enabled { - deviate add { - sonic-ext:field-name "enabled"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state { - deviate add { - sonic-ext:db-name "STATE_DB"; - sonic-ext:table-name "OTN_ATTENUATOR_TABLE"; - sonic-ext:key-transformer "oc_name_key_xfmr"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:name { - deviate add { - sonic-ext:field-transformer "oc_name_field_xfmr"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:attenuation-mode { - deviate add { - sonic-ext:field-name "attenuation-mode"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:target-output-power { - deviate add { - sonic-ext:field-name "target-output-power"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:attenuation { - deviate add { - sonic-ext:field-name "attenuation"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:enabled { - deviate add { - sonic-ext:field-name "enabled"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:component { - deviate add { - sonic-ext:field-name "component"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:ingress-port { - deviate add { - sonic-ext:field-name "ingress-port"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:egress-port { - deviate add { - sonic-ext:field-name "egress-port"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:actual-attenuation { - deviate add { - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:actual-attenuation/oc-opt-att:instant { - deviate add { - sonic-ext:field-name "actual-attenuation"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:output-power-total { - deviate add { - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:output-power-total/oc-opt-att:instant { - deviate add { - sonic-ext:field-name "output-power-total"; - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:optical-return-loss { - deviate add { - } - } - - deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:optical-return-loss/oc-opt-att:instant { - deviate add { - sonic-ext:field-name "optical-return-loss"; - } - } + yang-version "1"; -} + namespace "http://openconfig.net/yang/annotation/oc-opt-att-annot"; + prefix "oc-opt-att-annot"; + + import openconfig-platform { prefix oc-platform; } + import openconfig-types { prefix oc-types; } + import openconfig-extensions { prefix oc-ext; } + import openconfig-optical-attenuator { prefix oc-opt-att; } + import sonic-extensions { prefix sonic-ext; } + + deviation /oc-opt-att:optical-attenuator { + deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:get-namespace "attn_name_get_namespace_xfmr"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators { + deviate add { + sonic-ext:table-name "ATTENUATOR"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator { + deviate add { + sonic-ext:key-transformer "attn_name_key_xfmr"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state { + deviate add{ + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "ATTENUATOR_TABLE"; + sonic-ext:key-transformer "attn_name_key_xfmr"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:actual-attenuation { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "ATTENUATOR"; + sonic-ext:key-transformer "attn_actual_attenuation_key_xfmr"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:actual-attenuation/oc-opt-att:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:actual-attenuation/oc-opt-att:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:actual-attenuation/oc-opt-att:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:actual-attenuation/oc-opt-att:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:actual-attenuation/oc-opt-att:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:actual-attenuation/oc-opt-att:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:actual-attenuation/oc-opt-att:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:optical-return-loss { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "ATTENUATOR"; + sonic-ext:key-transformer "attn_optical_return_loss_key_xfmr"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:optical-return-loss/oc-opt-att:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:optical-return-loss/oc-opt-att:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:optical-return-loss/oc-opt-att:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:optical-return-loss/oc-opt-att:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:optical-return-loss/oc-opt-att:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:optical-return-loss/oc-opt-att:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:optical-return-loss/oc-opt-att:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:attenuation-mode { + deviate add { + sonic-ext:field-name "attenuation-mode"; + } + } + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:attenuation { + deviate add { + sonic-ext:field-name "attenuation"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:component { + deviate add { + sonic-ext:field-name "component"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:ingress-port { + deviate add { + sonic-ext:field-name "ingress-port"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:egress-port { + deviate add { + sonic-ext:field-name "egress-port"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:enabled { + deviate add { + sonic-ext:field-name "enabled"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:target-output-power { + deviate add { + sonic-ext:field-name "target-output-power"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:output-power-total { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "ATTENUATOR"; + sonic-ext:key-transformer "attn_output_power_total_key_xfmr"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:output-power-total/oc-opt-att:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:output-power-total/oc-opt-att:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:output-power-total/oc-opt-att:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:output-power-total/oc-opt-att:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:output-power-total/oc-opt-att:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:output-power-total/oc-opt-att:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:output-power-total/oc-opt-att:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:state/oc-opt-att:name { + deviate add { + sonic-ext:field-transformer "attn_name_field_xfmr"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:name { + deviate add { + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config { + deviate add { + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:target-output-power { + deviate add { + sonic-ext:field-name "target-output-power"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:attenuation { + deviate add { + sonic-ext:field-name "attenuation"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:enabled { + deviate add { + sonic-ext:field-name "enabled"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:name { + deviate add { + sonic-ext:field-transformer "attn_name_field_xfmr"; + } + } + + deviation /oc-opt-att:optical-attenuator/oc-opt-att:attenuators/oc-opt-att:attenuator/oc-opt-att:config/oc-opt-att:attenuation-mode { + deviate add { + sonic-ext:field-name "attenuation-mode"; + } + } +} diff --git a/models/yang/annotations/openconfig-optical-time-domain-reflectometer-annot.yang b/models/yang/annotations/openconfig-optical-time-domain-reflectometer-annot.yang new file mode 100644 index 000000000..0a66cc22b --- /dev/null +++ b/models/yang/annotations/openconfig-optical-time-domain-reflectometer-annot.yang @@ -0,0 +1,664 @@ +module openconfig-optical-time-domain-reflectometer-annot { + + yang-version "1"; + + namespace "http://openconfig.net/yang/annotation/oc-otdr-annot"; + prefix "oc-otdr-annot"; + + import sonic-extensions { prefix sonic-ext; } + import openconfig-yang-types { prefix oc-yang; } + import openconfig-transport-types { prefix oc-opt-types; } + import openconfig-platform { prefix oc-platform; } + import openconfig-platform-types { prefix oc-platform-types; } + import openconfig-extensions { prefix oc-ext; } + import openconfig-optical-time-domain-reflectometer { prefix oc-otdr; } + + deviation /oc-otdr:otdrs { + deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:get-namespace "otdr_get_namespace_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr { + deviate add { + sonic-ext:table-name "OTDR"; + sonic-ext:key-transformer "otdr_key_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config { + deviate add { + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:repetition { + deviate add { + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:repetition/oc-otdr:start-time { + deviate add { + sonic-ext:field-name "start-time"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:repetition/oc-otdr:period { + deviate add { + sonic-ext:field-name "period"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:repetition/oc-otdr:enable { + deviate add { + sonic-ext:field-name "enable"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:name { + deviate add { + sonic-ext:field-transformer "otdr_name_field_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:parent-port { + deviate add { + sonic-ext:field-name "parent-port"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:fiber-profile { + deviate add { + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:fiber-profile/oc-otdr:refractive-index { + deviate add { + sonic-ext:field-name "refractive-index"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:fiber-profile/oc-otdr:backscatter-index { + deviate add { + sonic-ext:field-name "backscatter-index"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:fiber-profile/oc-otdr:reflection-threshold { + deviate add { + sonic-ext:field-name "reflection-threshold"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:fiber-profile/oc-otdr:splice-loss-threshold { + deviate add { + sonic-ext:field-name "splice-loss-threshold"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:fiber-profile/oc-otdr:end-of-fiber-threshold { + deviate add { + sonic-ext:field-name "end-of-fiber-threshold"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:scanning-profile { + deviate add { + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:scanning-profile/oc-otdr:pulse-width { + deviate add { + sonic-ext:field-name "pulse-width"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:scanning-profile/oc-otdr:average-time { + deviate add { + sonic-ext:field-name "average-time"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:scanning-profile/oc-otdr:output-frequency { + deviate add { + sonic-ext:field-name "output-frequency"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:config/oc-otdr:scanning-profile/oc-otdr:distance-range { + deviate add { + sonic-ext:field-name "distance-range"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state { + deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OTDR_TABLE"; + sonic-ext:key-transformer "otdr_key_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:name { + deviate add { + sonic-ext:field-transformer "otdr_name_field_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:parent-port { + deviate add { + sonic-ext:field-name "parent-port"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:specification { + deviate add { + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:specification/oc-otdr:loss-dead-zone { + deviate add { + sonic-ext:field-name "loss-dead-zone"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:specification/oc-otdr:reflection-dead-zone { + deviate add { + sonic-ext:field-name "reflection-dead-zone"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:specification/oc-otdr:dynamic-range { + deviate add { + sonic-ext:field-name "dynamic-range"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:specification/oc-otdr:distance-accuracy { + deviate add { + sonic-ext:field-name "distance-accuracy"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:specification/oc-otdr:sampling-resolution { + deviate add { + sonic-ext:field-name "sampling-resolution"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:scanning-status { + deviate add { + sonic-ext:field-name "scanning-status"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:fiber-profile { + deviate add { + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:fiber-profile/oc-otdr:reflection-threshold { + deviate add { + sonic-ext:field-name "reflection-threshold"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:fiber-profile/oc-otdr:splice-loss-threshold { + deviate add { + sonic-ext:field-name "splice-loss-threshold"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:fiber-profile/oc-otdr:end-of-fiber-threshold { + deviate add { + sonic-ext:field-name "end-of-fiber-threshold"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:fiber-profile/oc-otdr:refractive-index { + deviate add { + sonic-ext:field-name "refractive-index"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:fiber-profile/oc-otdr:backscatter-index { + deviate add { + sonic-ext:field-name "backscatter-index"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:scanning-profile { + deviate add { + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:scanning-profile/oc-otdr:average-time { + deviate add { + sonic-ext:field-name "average-time"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:scanning-profile/oc-otdr:output-frequency { + deviate add { + sonic-ext:field-name "output-frequency"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:scanning-profile/oc-otdr:distance-range { + deviate add { + sonic-ext:field-name "distance-range"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:scanning-profile/oc-otdr:pulse-width { + deviate add { + sonic-ext:field-name "pulse-width"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:repetition { + deviate add { + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:repetition/oc-otdr:start-time { + deviate add { + sonic-ext:field-name "start-time"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:repetition/oc-otdr:period { + deviate add { + sonic-ext:field-name "period"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:state/oc-otdr:repetition/oc-otdr:enable { + deviate add { + sonic-ext:field-name "enable"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results { + deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:db-name "STATE_DB"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result { + deviate add { + sonic-ext:table-name "OTDR_TABLE"; + sonic-ext:key-transformer "otdr_history_state_key_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:trace/oc-otdr:data { + deviate add { + sonic-ext:field-name "data"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:trace/oc-otdr:update-time { + deviate add { + sonic-ext:field-name "update-time"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:scan-time { + deviate add { + //sonic-ext:field-name "scan-time"; + sonic-ext:field-transformer "otdr_history_scan_time_field_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:scanning-profile/oc-otdr:pulse-width { + deviate add { + sonic-ext:field-name "pulse-width"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:scanning-profile/oc-otdr:average-time { + deviate add { + sonic-ext:field-name "average-time"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:scanning-profile/oc-otdr:output-frequency { + deviate add { + sonic-ext:field-name "output-frequency"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:scanning-profile/oc-otdr:distance-range { + deviate add { + sonic-ext:field-name "distance-range"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:events { + deviate add { + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:events/oc-otdr:event { + deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OTDR_EVENT_TABLE"; + sonic-ext:key-transformer "otdr_history_events_state_key_xfmr"; + } + } + + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:events/oc-otdr:event/oc-otdr:index { + deviate add { + sonic-ext:field-name "index"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:events/oc-otdr:event/oc-otdr:type { + deviate add { + sonic-ext:field-name "type"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:events/oc-otdr:event/oc-otdr:length { + deviate add { + sonic-ext:field-name "length"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:events/oc-otdr:event/oc-otdr:loss { + deviate add { + sonic-ext:field-name "loss"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:events/oc-otdr:event/oc-otdr:reflection { + deviate add { + sonic-ext:field-name "reflection"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:events/oc-otdr:event/oc-otdr:accumulate-loss { + deviate add { + sonic-ext:field-name "accumulate-loss"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:events/oc-otdr:scan-time { + deviate add { + sonic-ext:field-transformer "otdr_history_scan_time_field_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:events/oc-otdr:span-distance { + deviate add { + sonic-ext:field-name "span-distance"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:history-results/oc-otdr:result/oc-otdr:events/oc-otdr:span-loss { + deviate add { + sonic-ext:field-name "span-loss"; + } + } + + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result { + deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OTDR_TABLE"; + sonic-ext:key-transformer "otdr_baseline_state_key_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:scanning-profile { + deviate add { + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:scanning-profile/oc-otdr:distance-range { + deviate add { + sonic-ext:field-name "distance-range"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:scanning-profile/oc-otdr:pulse-width { + deviate add { + sonic-ext:field-name "pulse-width"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:scanning-profile/oc-otdr:average-time { + deviate add { + sonic-ext:field-name "average-time"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:scanning-profile/oc-otdr:output-frequency { + deviate add { + sonic-ext:field-name "output-frequency"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:events { + deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OTDR_TABLE"; + sonic-ext:key-transformer "otdr_baseline_state_key_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:events/oc-otdr:span-loss { + deviate add { + sonic-ext:field-name "span-loss"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:events/oc-otdr:event { + deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OTDR_EVENT_TABLE"; + sonic-ext:key-transformer "otdr_baseline_events_state_key_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:events/oc-otdr:event/oc-otdr:loss { + deviate add { + sonic-ext:field-name "loss"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:events/oc-otdr:event/oc-otdr:reflection { + deviate add { + sonic-ext:field-name "reflection"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:events/oc-otdr:event/oc-otdr:accumulate-loss { + deviate add { + sonic-ext:field-name "accumulate-loss"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:events/oc-otdr:event/oc-otdr:index { + deviate add { + sonic-ext:field-name "index"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:events/oc-otdr:event/oc-otdr:type { + deviate add { + sonic-ext:field-name "type"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:events/oc-otdr:event/oc-otdr:length { + deviate add { + sonic-ext:field-name "length"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:events/oc-otdr:scan-time { + deviate add { + sonic-ext:field-name "scan-time"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:events/oc-otdr:span-distance { + deviate add { + sonic-ext:field-name "span-distance"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:trace { + deviate add { + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:trace/oc-otdr:data { + deviate add { + sonic-ext:field-name "data"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:baseline-result/oc-otdr:trace/oc-otdr:update-time { + deviate add { + sonic-ext:field-name "update-time"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result { + deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OTDR_TABLE"; + sonic-ext:key-transformer "otdr_current_state_key_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:events { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OTDR_TABLE"; + sonic-ext:key-transformer "otdr_current_state_key_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:events/oc-otdr:event { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OTDR_EVENT_TABLE"; + sonic-ext:key-transformer "otdr_current_events_state_key_xfmr"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:events/oc-otdr:event/oc-otdr:index { + deviate add { + sonic-ext:field-name "index"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:events/oc-otdr:event/oc-otdr:type { + deviate add { + sonic-ext:field-name "type"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:events/oc-otdr:event/oc-otdr:length { + deviate add { + sonic-ext:field-name "length"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:events/oc-otdr:event/oc-otdr:loss { + deviate add { + sonic-ext:field-name "loss"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:events/oc-otdr:event/oc-otdr:reflection { + deviate add { + sonic-ext:field-name "reflection"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:events/oc-otdr:event/oc-otdr:accumulate-loss { + deviate add { + sonic-ext:field-name "accumulate-loss"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:events/oc-otdr:scan-time { + deviate add { + sonic-ext:field-name "scan-time"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:events/oc-otdr:span-distance { + deviate add { + sonic-ext:field-name "span-distance"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:events/oc-otdr:span-loss { + deviate add { + sonic-ext:field-name "span-loss"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:trace { + deviate add { + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:trace/oc-otdr:data { + deviate add { + sonic-ext:field-name "data"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:trace/oc-otdr:update-time { + deviate add { + sonic-ext:field-name "update-time"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:scanning-profile { + deviate add { + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:scanning-profile/oc-otdr:average-time { + deviate add { + sonic-ext:field-name "average-time"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:scanning-profile/oc-otdr:output-frequency { + deviate add { + sonic-ext:field-name "output-frequency"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:scanning-profile/oc-otdr:distance-range { + deviate add { + sonic-ext:field-name "distance-range"; + } + } + + deviation /oc-otdr:otdrs/oc-otdr:otdr/oc-otdr:current-result/oc-otdr:scanning-profile/oc-otdr:pulse-width { + deviate add { + sonic-ext:field-name "pulse-width"; + } + } + + +} + diff --git a/models/yang/annotations/openconfig-platform-annot.yang b/models/yang/annotations/openconfig-platform-annot.yang new file mode 100644 index 000000000..ac23724f6 --- /dev/null +++ b/models/yang/annotations/openconfig-platform-annot.yang @@ -0,0 +1,1520 @@ +module openconfig-platform-annot { + + yang-version "1"; + + namespace "http://openconfig.net/yang/annotation/oc-platform-annot"; + prefix "oc-platform-annot"; + + import sonic-extensions { prefix sonic-ext; } + import openconfig-if-ethernet { prefix oc-eth; } + import openconfig-interfaces { prefix oc-if; } + import openconfig-lldp { prefix oc-lldp; } + import ietf-yang-types { prefix yang; } + import openconfig-extensions { prefix oc-ext; } + import openconfig-yang-types { prefix oc-yang; } + import openconfig-types { prefix oc-types; } + import openconfig-transport-types { prefix oc-opt-types; } + import openconfig-platform { prefix oc-platform; } + import openconfig-platform-transceiver { prefix oc-transceiver; } + import openconfig-terminal-device { prefix oc-opt-term; } + + deviation /oc-platform:components { + deviate add { + sonic-ext:table-transformer "pfm_table_xfmr"; + sonic-ext:get-namespace "td_get_namespace_xfmr"; + sonic-ext:post-transformer "pfm_post_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component { + deviate add { + sonic-ext:key-transformer "component_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:config/oc-platform:name { + deviate add { + sonic-ext:field-transformer "component_field_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-transformer "pfm_table_xfmr"; + sonic-ext:key-transformer "component_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:state/oc-platform:name { + deviate add { + sonic-ext:field-transformer "component_field_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:state/oc-platform:serial-no { + deviate add { + sonic-ext:field-name "serial-no"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:state/oc-platform:part-no { + deviate add { + sonic-ext:field-name "part-no"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:state/oc-platform:mfg-name{ + deviate add { + sonic-ext:field-name "mfg-name"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:state/oc-platform:mfg-date { + deviate add { + sonic-ext:field-name "mfg-date"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:state/oc-platform:hardware-version { + deviate add { + sonic-ext:field-name "hardware-version"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:state/oc-platform:software-version { + deviate add { + sonic-ext:field-name "software-version"; + } + } + + + + deviation /oc-platform:components/oc-platform:component/oc-platform:state/oc-platform:oper-status { + deviate add { + sonic-ext:field-name "oper-status"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:state/oc-platform:empty { + deviate add { + sonic-ext:field-name "empty"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:state/oc-platform:removable { + deviate add { + sonic-ext:field-name "removable"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:state/oc-platform:parent { + deviate add { + sonic-ext:field-name "parent"; + } + } + + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel { + deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:table-name "OCH"; + sonic-ext:key-transformer "component_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:config { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:config/oc-opt-term:frequency { + deviate add { + sonic-ext:field-name "frequency"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:config/oc-opt-term:target-output-power { + deviate add { + sonic-ext:field-name "target-output-power"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:config/oc-opt-term:operational-mode { + deviate add { + sonic-ext:field-name "operational-mode"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "OCH_TABLE"; + sonic-ext:key-transformer "component_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:frequency { + deviate add { + sonic-ext:field-name "frequency"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:target-output-power { + deviate add { + sonic-ext:field-name "target-output-power"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:operational-mode { + deviate add { + sonic-ext:field-name "operational-mode"; + } + } + + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:chromatic-dispersion { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OCH"; + sonic-ext:key-transformer "och_chromatic_dispersion_counter_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:chromatic-dispersion/oc-opt-term:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:chromatic-dispersion/oc-opt-term:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:chromatic-dispersion/oc-opt-term:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:chromatic-dispersion/oc-opt-term:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:chromatic-dispersion/oc-opt-term:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:chromatic-dispersion/oc-opt-term:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:chromatic-dispersion/oc-opt-term:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-mode-dispersion { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OCH"; + sonic-ext:key-transformer "och_pmd_counter_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-mode-dispersion/oc-opt-term:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-mode-dispersion/oc-opt-term:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-mode-dispersion/oc-opt-term:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-mode-dispersion/oc-opt-term:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-mode-dispersion/oc-opt-term:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-mode-dispersion/oc-opt-term:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-mode-dispersion/oc-opt-term:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:second-order-polarization-mode-dispersion { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OCH"; + sonic-ext:key-transformer "och_second_pmd_counter_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:second-order-polarization-mode-dispersion/oc-opt-term:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:second-order-polarization-mode-dispersion/oc-opt-term:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:second-order-polarization-mode-dispersion/oc-opt-term:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:second-order-polarization-mode-dispersion/oc-opt-term:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:second-order-polarization-mode-dispersion/oc-opt-term:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:second-order-polarization-mode-dispersion/oc-opt-term:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:second-order-polarization-mode-dispersion/oc-opt-term:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-dependent-loss { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OCH"; + sonic-ext:key-transformer "och_pd_loss_counter_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-dependent-loss/oc-opt-term:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-dependent-loss/oc-opt-term:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-dependent-loss/oc-opt-term:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-dependent-loss/oc-opt-term:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-dependent-loss/oc-opt-term:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-dependent-loss/oc-opt-term:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:polarization-dependent-loss/oc-opt-term:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:osnr { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OCH"; + sonic-ext:key-transformer "och_osnr_counter_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:osnr/oc-opt-term:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:osnr/oc-opt-term:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:osnr/oc-opt-term:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:osnr/oc-opt-term:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:osnr/oc-opt-term:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:osnr/oc-opt-term:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:osnr/oc-opt-term:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:carrier-frequency-offset { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OCH"; + sonic-ext:key-transformer "och_cfo_counter_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:carrier-frequency-offset/oc-opt-term:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:carrier-frequency-offset/oc-opt-term:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:carrier-frequency-offset/oc-opt-term:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:carrier-frequency-offset/oc-opt-term:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:carrier-frequency-offset/oc-opt-term:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:carrier-frequency-offset/oc-opt-term:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:carrier-frequency-offset/oc-opt-term:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:output-power { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OCH"; + sonic-ext:key-transformer "och_output_power_counter_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:output-power/oc-opt-term:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:output-power/oc-opt-term:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:output-power/oc-opt-term:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:output-power/oc-opt-term:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:output-power/oc-opt-term:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:output-power/oc-opt-term:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:output-power/oc-opt-term:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:input-power { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OCH"; + sonic-ext:key-transformer "och_input_power_counter_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:input-power/oc-opt-term:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:input-power/oc-opt-term:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:input-power/oc-opt-term:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:input-power/oc-opt-term:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:input-power/oc-opt-term:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:input-power/oc-opt-term:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:input-power/oc-opt-term:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:laser-bias-current { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OCH"; + sonic-ext:key-transformer "och_laser_bias_counter_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:laser-bias-current/oc-opt-term:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:laser-bias-current/oc-opt-term:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:laser-bias-current/oc-opt-term:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:laser-bias-current/oc-opt-term:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:laser-bias-current/oc-opt-term:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:laser-bias-current/oc-opt-term:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-opt-term:optical-channel/oc-opt-term:state/oc-opt-term:laser-bias-current/oc-opt-term:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port { + deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "PORT_TABLE"; + sonic-ext:key-transformer "optical_port_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:config { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:config/oc-line-com:admin-state { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "PORT_TABLE"; + sonic-ext:key-transformer "optical_port_key_xfmr"; + } + } + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:admin-state { + deviate add { + sonic-ext:field-name "admin-state"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:optical-port-type { + deviate add { + sonic-ext:field-name "optical-port-type"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:input-power { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "PORT"; + sonic-ext:key-transformer "optical_port_input_power_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:input-power/oc-line-com:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:input-power/oc-line-com:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:input-power/oc-line-com:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:input-power/oc-line-com:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:input-power/oc-line-com:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:input-power/oc-line-com:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:input-power/oc-line-com:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:output-power { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "PORT"; + sonic-ext:key-transformer "optical_port_output_power_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:output-power/oc-line-com:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:output-power/oc-line-com:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:output-power/oc-line-com:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:output-power/oc-line-com:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:output-power/oc-line-com:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:output-power/oc-line-com:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:port/oc-line-com:optical-port/oc-line-com:state/oc-line-com:output-power/oc-line-com:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:state/oc-platform:memory/oc-platform:available { + deviate add { + sonic-ext:field-name "memory-available"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-platform:state/oc-platform:memory/oc-platform:utilized { + deviate add { + sonic-ext:field-name "memory-utilized"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver { + deviate add { + sonic-ext:table-name "TRANSCEIVER"; + sonic-ext:key-transformer "pfm_transceiver_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:config { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:config/oc-transceiver:enabled { + deviate add { + sonic-ext:field-name "enabled"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:config/oc-transceiver:form-factor-preconf { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:config/oc-transceiver:ethernet-pmd-preconf { + deviate add { + sonic-ext:field-name "ethernet-pmd-preconf"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:config/oc-transceiver:fec-mode { + deviate add { + sonic-ext:field-name "fec-mode"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:config/oc-transceiver:module-functional-type { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "TRANSCEIVER_TABLE"; + sonic-ext:key-transformer "pfm_transceiver_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:enabled { + deviate add { + sonic-ext:field-name "enabled"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:form-factor-preconf { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:ethernet-pmd-preconf { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:fec-mode { + deviate add { + sonic-ext:field-name "fec-mode"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:module-functional-type { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:pre-fec-ber { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:pre-fec-ber/oc-transceiver:instant { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:pre-fec-ber/oc-transceiver:avg { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:pre-fec-ber/oc-transceiver:min { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:pre-fec-ber/oc-transceiver:max { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:pre-fec-ber/oc-transceiver:interval { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:pre-fec-ber/oc-transceiver:min-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:pre-fec-ber/oc-transceiver:max-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:post-fec-ber { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:post-fec-ber/oc-transceiver:instant { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:post-fec-ber/oc-transceiver:avg { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:post-fec-ber/oc-transceiver:min { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:post-fec-ber/oc-transceiver:max { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:post-fec-ber/oc-transceiver:interval { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:post-fec-ber/oc-transceiver:min-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:post-fec-ber/oc-transceiver:max-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:supply-voltage { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:supply-voltage/oc-transceiver:instant { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:supply-voltage/oc-transceiver:avg { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:supply-voltage/oc-transceiver:min { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:supply-voltage/oc-transceiver:max { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:supply-voltage/oc-transceiver:interval { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:supply-voltage/oc-transceiver:min-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:supply-voltage/oc-transceiver:max-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:present { + deviate add { + sonic-ext:field-name "present"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:form-factor { + deviate add { + sonic-ext:field-name "form-factor"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:connector-type { + deviate add { + sonic-ext:field-name "connector-type"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:vendor { + deviate add { + sonic-ext:field-name "vendor"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:vendor-part { + deviate add { + sonic-ext:field-name "vendor-part"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:vendor-rev { + deviate add { + sonic-ext:field-name "vendor-rev"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:ethernet-pmd { + deviate add { + sonic-ext:field-name "ethernet-pmd"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:sonet-sdh-compliance-code { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:otn-compliance-code { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:serial-no { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:date-code { + deviate add { + sonic-ext:field-name "date-code"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:fault-condition { + deviate add { + sonic-ext:field-name "fault-condition"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:fec-status { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:fec-uncorrectable-blocks { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:fec-uncorrectable-words { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:fec-corrected-bytes { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:fec-corrected-bits { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:output-power { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:instant { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:avg { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:min { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:max { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:interval { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:min-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:max-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:input-power { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:instant { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:avg { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:min { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:max { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:interval { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:min-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:max-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:laser-bias-current { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:instant { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:avg { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:min { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:max { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:interval { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:min-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:max-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "PHYSICAL_CHANNEL_TABLE"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel { + deviate add { + sonic-ext:key-transformer "pfm_transceiver_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:config { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:config/oc-transceiver:index { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:config/oc-transceiver:associated-optical-channel { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:config/oc-transceiver:description { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:config/oc-transceiver:tx-laser { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:config/oc-transceiver:target-output-power { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "PHYSICAL_CHANNEL_TABLE"; + sonic-ext:key-transformer "pfm_transceiver_key_xfmr"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:index { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:associated-optical-channel { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:description { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:tx-laser { + deviate add { + sonic-ext:field-name "tx-laser"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:target-output-power { + deviate add { + sonic-ext:field-name "target-output-power"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-temperature { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-temperature/oc-transceiver:instant { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-temperature/oc-transceiver:avg { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-temperature/oc-transceiver:min { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-temperature/oc-transceiver:max { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-temperature/oc-transceiver:interval { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-temperature/oc-transceiver:min-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-temperature/oc-transceiver:max-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:target-frequency-deviation { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:target-frequency-deviation/oc-transceiver:instant { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:target-frequency-deviation/oc-transceiver:avg { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:target-frequency-deviation/oc-transceiver:min { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:target-frequency-deviation/oc-transceiver:max { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:target-frequency-deviation/oc-transceiver:interval { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:target-frequency-deviation/oc-transceiver:min-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:target-frequency-deviation/oc-transceiver:max-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:tec-current { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:tec-current/oc-transceiver:instant { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:tec-current/oc-transceiver:avg { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:tec-current/oc-transceiver:min { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:tec-current/oc-transceiver:max { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:tec-current/oc-transceiver:interval { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:tec-current/oc-transceiver:min-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:tec-current/oc-transceiver:max-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-age { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:output-frequency { + deviate add { + sonic-ext:field-name "output-frequency"; + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:output-power { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:instant { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:avg { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:min { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:max { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:interval { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:min-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:output-power/oc-transceiver:max-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:input-power { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:instant { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:avg { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:min { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:max { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:interval { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:min-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:input-power/oc-transceiver:max-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-bias-current { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:instant { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:avg { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:min { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:max { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:interval { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:min-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:state/oc-transceiver:laser-bias-current/oc-transceiver:max-time { + deviate add { + } + } + + deviation /oc-platform:components/oc-platform:component/oc-transceiver:transceiver/oc-transceiver:physical-channels/oc-transceiver:channel/oc-transceiver:index { + deviate add { + } + } +} diff --git a/models/yang/annotations/openconfig-system-annot.yang b/models/yang/annotations/openconfig-system-annot.yang index 28f03b27e..ce2af79ca 100644 --- a/models/yang/annotations/openconfig-system-annot.yang +++ b/models/yang/annotations/openconfig-system-annot.yang @@ -2,72 +2,1980 @@ module openconfig-system-annot { yang-version "1"; - namespace "http://openconfig.net/yang/openconfig-system-annot"; + namespace "http://openconfig.net/yang/annotation/oc-sys-annot"; prefix "oc-sys-annot"; + import openconfig-procmon { prefix oc-proc; } + import openconfig-alarms { prefix oc-alarms; } + import openconfig-inet-types { prefix oc-inet; } + import openconfig-yang-types { prefix oc-yang; } + import openconfig-extensions { prefix oc-ext; } + import openconfig-aaa { prefix oc-aaa; } + import openconfig-system-logging { prefix oc-log; } + import openconfig-system-management { prefix oc-sys-mgmt; } + import openconfig-types { prefix oc-types; } + import openconfig-system-terminal { prefix oc-sys-term; } + import openconfig-messages { prefix oc-messages; } import openconfig-system { prefix oc-sys; } import sonic-extensions {prefix sonic-ext; } import openconfig-system-grpc { prefix oc-sys-grpc; } import gnsi-pathz { prefix gnsi-pathz; } import openconfig-gnsi-credentialz { prefix oc-gnsi-credz; } + deviation /oc-sys:system { + deviate add { + sonic-ext:table-name "SYSTEM"; + } + } + + deviation /oc-sys:system/oc-sys:telnet-server { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:config/oc-sys:enable { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:config/oc-sys:timeout { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:config/oc-sys:rate-limit { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:config/oc-sys:session-limit { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:state/oc-sys:rate-limit { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:state/oc-sys:session-limit { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:state/oc-sys:enable { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:state/oc-sys:timeout { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ssh-server { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:config/oc-sys:timeout { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:config/oc-sys:enable { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:config/oc-sys:protocol-version { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:config/oc-sys:rate-limit { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:config/oc-sys:session-limit { + deviate add { + } + } + deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:state { deviate add { - sonic-ext:db-name "STATE_DB"; + sonic-ext:db-name "STATE_DB"; sonic-ext:subtree-transformer "ssh_server_state_xfmr"; } } - deviation /oc-sys:system/oc-sys-grpc:grpc-servers { + deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:state/oc-sys:session-limit { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:state/oc-sys:timeout { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:state/oc-sys:enable { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:state/oc-sys:protocol-version { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:state/oc-sys:rate-limit { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys-grpc:grpc-servers { deviate add { sonic-ext:key-transformer "grpc_server_key_xfmr"; sonic-ext:subtree-transformer "grpc_server_xfmr"; } } - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state { + deviation /oc-sys:system/oc-sys:state { deviate add { - sonic-ext:db-name "STATE_DB"; - sonic-ext:table-name "CREDENTIALS"; - sonic-ext:key-name "GLOME_CONFIG"; } } - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state/oc-gnsi-credz:active-glome-key-version { + deviation /oc-sys:system/oc-sys:state/oc-sys:domain-name { deviate add { - sonic-ext:field-name "key_version"; } } - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state/oc-gnsi-credz:active-glome-key-created-on { + deviation /oc-sys:system/oc-sys:state/oc-sys:login-banner { deviate add { - sonic-ext:field-name "last_updated"; } } - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state/oc-gnsi-credz:enabled { + deviation /oc-sys:system/oc-sys:state/oc-sys:motd-banner { deviate add { - sonic-ext:field-name "enabled"; } } - deviation /oc-sys:system/oc-gnsi-credz:console { + deviation /oc-sys:system/oc-sys:state/oc-sys:current-datetime { deviate add { - sonic-ext:db-name "STATE_DB"; - sonic-ext:subtree-transformer "console_counters_xfmr"; } } -    deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:state { -      deviate add { -        sonic-ext:db-name "STATE_DB"; -        sonic-ext:subtree-transformer "authz_policy_xfmr"; -      } -    } - deviation /oc-sys:system/gnsi-pathz:gnmi-pathz-policies { + deviation /oc-sys:system/oc-sys:state/oc-sys:boot-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:state/oc-sys:hostname { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:clock { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:clock/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:clock/oc-sys:state/oc-sys:timezone-name { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:clock/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:clock/oc-sys:config/oc-sys:timezone-name { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:memory { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:memory/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:memory/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:memory/oc-sys:state/oc-sys:reserved { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:memory/oc-sys:state/oc-sys:physical { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:state/oc-sys:search { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:servers { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:port { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:port { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:config/oc-sys:hostname { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:config/oc-sys:alias { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:config/oc-sys:ipv4-address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:config/oc-sys:ipv6-address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:state/oc-sys:alias { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:state/oc-sys:ipv4-address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:state/oc-sys:ipv6-address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:state/oc-sys:hostname { deviate add { - sonic-ext:key-transformer "pathz_policies_key_xfmr"; - sonic-ext:subtree-transformer "pathz_policies_xfmr"; } } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:hostname { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:dns/oc-sys:config/oc-sys:search { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:config/oc-sys:ntp-source-address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:config/oc-sys:enable-ntp-auth { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:config/oc-sys:enabled { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:state/oc-sys:enabled { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:state/oc-sys:ntp-source-address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:state/oc-sys:auth-mismatch { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:state/oc-sys:enable-ntp-auth { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:key-id { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:config/oc-sys:key-value { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:config/oc-sys:key-id { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:config/oc-sys:key-type { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:state/oc-sys:key-type { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:state/oc-sys:key-value { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:state/oc-sys:key-id { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:port { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:version { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:association-type { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:iburst { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:prefer { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:iburst { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:association-type { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:poll-interval { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:prefer { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:offset { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:root-delay { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:stratum { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:version { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:root-dispersion { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:port { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:config/oc-sys:motd-banner { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:config/oc-sys:hostname { + deviate add { + sonic-ext:field-name "hostname"; + } + } + + deviation /oc-sys:system/oc-sys:config/oc-sys:domain-name { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:config/oc-sys:login-banner { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:min-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:max-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:instant { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:avg { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:min { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:max { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:interval { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:interval { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:min-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:max-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:instant { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:avg { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:min { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:max { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:max-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:instant { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:avg { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:min { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:max { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:interval { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:min-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:min { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:max { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:interval { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:min-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:max-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:instant { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:avg { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:avg { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:min { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:max { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:interval { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:min-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:max-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:instant { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:min-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:max-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:instant { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:avg { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:min { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:max { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:interval { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:index { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:instant { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:avg { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:min { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:max { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:interval { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:min-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:max-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:min { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:max { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:interval { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:min-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:max-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:instant { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:avg { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:index { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:alarms { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "CURALARM_TABLE"; + sonic-ext:get-namespace "oc_sys_get_namespace_xfmr"; + } + } + + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm { + deviate add { + sonic-ext:key-transformer "oc_system_alarm_key_xfmr"; + } + } + + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:id { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "CURALARM_TABLE"; + sonic-ext:key-transformer "oc_system_alarm_key_xfmr"; + sonic-ext:get-namespace "oc_sys_get_namespace_xfmr"; + } + } + + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:type-id { + deviate add { + sonic-ext:field-name "type-id"; + } + } + + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:id { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:resource { + deviate add { + sonic-ext:field-name "resource"; + } + } + + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:text { + deviate add { + sonic-ext:field-name "text"; + } + } + + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:time-created { + deviate add { + sonic-ext:field-name "time-created"; + } + } + + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:severity { + deviate add { + sonic-ext:field-name "severity"; + } + } + + deviation /oc-sys:system/oc-sys:processes { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:processes/oc-sys:process { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:pid { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:cpu-usage-user { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:cpu-utilization { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:name { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:memory-utilization { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:memory-usage { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:start-time { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:cpu-usage-system { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:args { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:pid { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:uptime { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:config/oc-sys:accounting-method { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:state/oc-sys:accounting-method { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:event-type { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:config/oc-sys:event-type { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:config/oc-sys:record { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:state/oc-sys:event-type { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:state/oc-sys:record { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:state/oc-sys:source-address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:state/oc-sys:port { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:state/oc-sys:secret-key { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:config/oc-sys:source-address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:config/oc-sys:port { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:config/oc-sys:secret-key { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:source-address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:retransmit-attempts { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:auth-port { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:acct-port { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:counters { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:counters/oc-sys:retried-access-requests { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:counters/oc-sys:access-accepts { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:counters/oc-sys:access-rejects { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:counters/oc-sys:timeout-access-requests { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:secret-key { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:config/oc-sys:auth-port { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:config/oc-sys:acct-port { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:config/oc-sys:secret-key { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:config/oc-sys:source-address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:config/oc-sys:retransmit-attempts { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:timeout { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:name { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:messages-sent { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:messages-received { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:connection-opens { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:connection-closes { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:timeout { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:connection-timeouts { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:errors-received { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:connection-failures { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:name { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:connection-aborts { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:name { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:config/oc-sys:name { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:config/oc-sys:type { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:state/oc-sys:type { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:state/oc-sys:name { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "CREDENTIALS"; + sonic-ext:key-name "GLOME_CONFIG"; + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state/oc-gnsi-credz:active-glome-key-version { + deviate add { + sonic-ext:field-name "key_version"; + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state/oc-gnsi-credz:active-glome-key-created-on { + deviate add { + sonic-ext:field-name "last_updated"; + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc- sys:state/oc-gnsi-credz:enabled { + deviate add { + sonic-ext:field-name "enabled"; + } + } + + deviation /oc-sys:system/oc-gnsi-credz:console { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:subtree-transformer "console_counters_xfmr"; + } + } +   + deviation /oc-sys:system/gnsi-pathz:gnmi-pathz-policies { + deviate add { + sonic-ext:key-transformer "pathz_policies_key_xfmr"; + sonic-ext:subtree-transformer "pathz_policies_xfmr"; + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:state/oc-sys:admin-password { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:state/oc-sys:admin-password-hashed { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:state/oc-sys:admin-username { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:config/oc-sys:admin-password-hashed { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:config/oc-sys:admin-password { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:username { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:config/oc-sys:ssh-key { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:config/oc-sys:role { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:config/oc-sys:username { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:config/oc-sys:password { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:config/oc-sys:password-hashed { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state/oc-sys:ssh-key { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state/oc-sys:role { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state/oc-sys:username { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state/oc-sys:password { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state/oc-sys:password-hashed { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:config/oc-sys:authentication-method { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:state/oc-sys:authentication-method { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:config/oc-sys:authorization-method { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:state { + deviate add { + sonic-ext:db-name "STATE_DB"; +        sonic-ext:subtree-transformer "authz_policy_xfmr"; + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:state/oc-sys:authorization-method { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events/oc-sys:event { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events/oc-sys:event/oc-sys:event-type { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events/oc-sys:event/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events/oc-sys:event/oc-sys:config/oc-sys:event-type { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events/oc-sys:event/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events/oc-sys:event/oc-sys:state/oc-sys:event-type { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:config/oc-sys:service { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:config/oc-sys:enabled { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:state/oc-sys:enabled { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:state/oc-sys:service { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:service { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:config/oc-sys:severity { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:message { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:message/oc-sys:msgid { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:message/oc-sys:msg { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:message/oc-sys:priority { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:message/oc-sys:app-name { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:message/oc-sys:procid { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:severity { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:console { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:severity { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:config/oc-sys:severity { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:config/oc-sys:facility { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:state/oc-sys:severity { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:state/oc-sys:facility { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:facility { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:facility { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:severity { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:config/oc-sys:facility { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:config/oc-sys:severity { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:state/oc-sys:severity { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:state/oc-sys:facility { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:host { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:config { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:config/oc-sys:host { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:config/oc-sys:source-address { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:config/oc-sys:remote-port { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:state { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:state/oc-sys:remote-port { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:state/oc-sys:host { + deviate add { + } + } + + deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:state/oc-sys:source-address { + deviate add { + } + } + } diff --git a/models/yang/annotations/openconfig-telemetry-annot.yang b/models/yang/annotations/openconfig-telemetry-annot.yang new file mode 100644 index 000000000..606f64d41 --- /dev/null +++ b/models/yang/annotations/openconfig-telemetry-annot.yang @@ -0,0 +1,257 @@ +module openconfig-telemetry-annot { + + yang-version "1"; + + namespace "http://openconfig.net/yang/annotation/oc-telemetry-annot"; + prefix "oc-telemetry-annot"; + + import sonic-extensions { prefix sonic-ext; } + import openconfig-telemetry { prefix oc-telemetry; } + + deviation /oc-telemetry:telemetry-system { + deviate add { + sonic-ext:post-transformer "telemetry_client_sync_post_xfmr"; + sonic-ext:get-namespace "telemetry_get_namespace_xfmr"; + } + } + + + deviation /oc-telemetry:telemetry-system/oc-telemetry:sensor-groups { + deviate add { + sonic-ext:table-name "SENSOR_GROUP"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:sensor-groups/oc-telemetry:sensor-group { + deviate add { + sonic-ext:key-transformer "telemetry_sensor_group_id_key_xfmr"; + sonic-ext:get-namespace "telemetry_get_namespace_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:sensor-groups/oc-telemetry:sensor-group/oc-telemetry:config/oc-telemetry:sensor-group-id { + deviate add { + sonic-ext:field-transformer "telemetry_sensor_group_id_field_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:sensor-groups/oc-telemetry:sensor-group/oc-telemetry:sensor-paths{ + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:sensor-groups/oc-telemetry:sensor-group/oc-telemetry:sensor-paths/oc-telemetry:sensor-path { + deviate add { + sonic-ext:key-transformer "telemetry_sensor_path_key_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:sensor-groups/oc-telemetry:sensor-group/oc-telemetry:sensor-paths/oc-telemetry:sensor-path/oc-telemetry:config/oc-telemetry:path { + deviate add { + sonic-ext:field-name "sensor-paths"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:destination-groups { + deviate add { + sonic-ext:table-name "DESTINATION_GROUP"; + sonic-ext:get-namespace "telemetry_get_namespace_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:destination-groups/oc-telemetry:destination-group { + deviate add { + sonic-ext:key-transformer "telemetry_group_id_key_xfmr"; + sonic-ext:get-namespace "telemetry_get_namespace_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:destination-groups/oc-telemetry:destination-group/oc-telemetry:config { + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:destination-groups/oc-telemetry:destination-group/oc-telemetry:config/oc-telemetry:group-id { + deviate add { + sonic-ext:field-transformer "telemetry_group_id_field_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:destination-groups/oc-telemetry:destination-group/oc-telemetry:destinations { + deviate add { + sonic-ext:table-name "DESTINATION"; + sonic-ext:get-namespace "telemetry_get_namespace_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:destination-groups/oc-telemetry:destination-group/oc-telemetry:destinations/oc-telemetry:destination { + deviate add { + sonic-ext:key-transformer "telemetry_destination_key_xfmr"; + sonic-ext:get-namespace "telemetry_get_namespace_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:destination-groups/oc-telemetry:destination-group/oc-telemetry:destinations/oc-telemetry:destination/oc-telemetry:destination-address { + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:destination-groups/oc-telemetry:destination-group/oc-telemetry:destinations/oc-telemetry:destination/oc-telemetry:destination-port { + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:destination-groups/oc-telemetry:destination-group/oc-telemetry:destinations/oc-telemetry:destination/oc-telemetry:config { + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:destination-groups/oc-telemetry:destination-group/oc-telemetry:destinations/oc-telemetry:destination/oc-telemetry:config/oc-telemetry:destination-address { + deviate add { + sonic-ext:field-transformer "telemetry_destination_address_field_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:destination-groups/oc-telemetry:destination-group/oc-telemetry:destinations/oc-telemetry:destination/oc-telemetry:config/oc-telemetry:destination-port { + deviate add { + sonic-ext:field-transformer "telemetry_destination_port_field_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:destination-groups/oc-telemetry:destination-group/oc-telemetry:group-id { + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions { + deviate add { + sonic-ext:get-namespace "telemetry_get_namespace_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions { + deviate add { + sonic-ext:table-name "PERSISTENT_SUBSCRIPTION"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription { + deviate add { + sonic-ext:key-transformer "telemetry_persistent_subscription_key_xfmr"; + sonic-ext:get-namespace "telemetry_get_namespace_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:config { + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:config/oc-telemetry:name { + deviate add { + sonic-ext:field-transformer "telemetry_persistent_subscription_field_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:config/oc-telemetry:local-source-address { + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:config/oc-telemetry:originated-qos-marking { + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:config/oc-telemetry:protocol { + deviate add { + sonic-ext:field-name "protocol"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:config/oc-telemetry:encoding { + deviate add { + sonic-ext:field-name "encoding"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:sensor-profiles { + deviate add { + sonic-ext:table-name "SENSOR_PROFILE"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:sensor-profiles/oc-telemetry:sensor-profile { + deviate add { + sonic-ext:key-transformer "telemetry_sensor_profile_key_xfmr"; + sonic-ext:get-namespace "telemetry_get_namespace_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:sensor-profiles/oc-telemetry:sensor-profile/oc-telemetry:sensor-group { + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:sensor-profiles/oc-telemetry:sensor-profile/oc-telemetry:config { + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:sensor-profiles/oc-telemetry:sensor-profile/oc-telemetry:config/oc-telemetry:suppress-redundant { + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:sensor-profiles/oc-telemetry:sensor-profile/oc-telemetry:config/oc-telemetry:sensor-group { + deviate add { + sonic-ext:field-transformer "telemetry_sensor_profile_field_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:sensor-profiles/oc-telemetry:sensor-profile/oc-telemetry:config/oc-telemetry:sample-interval { + deviate add { + sonic-ext:field-name "sample-interval"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:sensor-profiles/oc-telemetry:sensor-profile/oc-telemetry:config/oc-telemetry:heartbeat-interval { + deviate add { + sonic-ext:field-name "heartbeat-interval"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:destination-groups { + deviate add { + sonic-ext:table-name "SUBSCRIPTION_DESTINATION_GROUP"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:destination-groups/oc-telemetry:destination-group { + deviate add { + sonic-ext:key-transformer "telemetry_sub_dest_group_id_key_xfmr"; + sonic-ext:get-namespace "telemetry_get_namespace_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:destination-groups/oc-telemetry:destination-group/oc-telemetry:group-id { + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:destination-groups/oc-telemetry:destination-group/oc-telemetry:config { + deviate add { + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:destination-groups/oc-telemetry:destination-group/oc-telemetry:config/oc-telemetry:group-id { + deviate add { + sonic-ext:field-transformer "telemetry_sub_dest_group_id_field_xfmr"; + } + } + + deviation /oc-telemetry:telemetry-system/oc-telemetry:subscriptions/oc-telemetry:persistent-subscriptions/oc-telemetry:persistent-subscription/oc-telemetry:name { + deviate add { + } + } +} diff --git a/models/yang/annotations/openconfig-terminal-device-annot.yang b/models/yang/annotations/openconfig-terminal-device-annot.yang new file mode 100644 index 000000000..574ddde79 --- /dev/null +++ b/models/yang/annotations/openconfig-terminal-device-annot.yang @@ -0,0 +1,1070 @@ +module openconfig-terminal-device-annot { + + yang-version "1"; + + namespace "http://openconfig.net/yang/annotation/oc-terminal-device-annot"; + prefix "oc-terminal-device-annot"; + + import sonic-extensions { prefix sonic-ext; } + import openconfig-if-ethernet { prefix oc-eth; } + import openconfig-interfaces { prefix oc-if; } + import openconfig-lldp { prefix oc-lldp; } + import ietf-yang-types { prefix yang; } + import openconfig-extensions { prefix oc-ext; } + import openconfig-yang-types { prefix oc-yang; } + import openconfig-types { prefix oc-types; } + import openconfig-transport-types { prefix oc-opt-types; } + import openconfig-platform { prefix oc-platform; } + import openconfig-platform-transceiver { prefix oc-transceiver; } + import openconfig-terminal-device { prefix oc-opt-term; } + + deviation /oc-opt-term:terminal-device { + deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:post-transformer "terminal_device_post_xfmr"; + sonic-ext:get-namespace "td_get_namespace_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels { + deviate add { + sonic-ext:table-name "LOGICAL_CHANNEL"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel { + deviate add { + sonic-ext:key-transformer "logical_channel_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:index { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config/oc-opt-term:logical-channel-type { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config/oc-opt-term:description { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config/oc-opt-term:test-signal { + deviate add { + sonic-ext:field-name "test-signal"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config/oc-opt-term:loopback-mode { + deviate add { + sonic-ext:field-name "loopback-mode"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config/oc-opt-term:admin-state { + deviate add { + sonic-ext:field-name "admin-state"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config/oc-opt-term:client-mapping-mode { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config/oc-opt-term:trib-protocol { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config/oc-opt-term:index { + deviate add { + sonic-ext:field-transformer "logical_channel_field_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config/oc-opt-term:rate-class { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "LOGICAL_CHANNEL_TABLE"; + sonic-ext:key-transformer "logical_channel_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:rate-class { + deviate add { + sonic-ext:field-name "rate-class"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:description { + deviate add { + sonic-ext:field-name "description"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:logical-channel-type { + deviate add { + sonic-ext:field-name "logical-channel-type"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:test-signal { + deviate add { + sonic-ext:field-name "test-signal"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:loopback-mode { + deviate add { + sonic-ext:field-name "loopback-mode"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:admin-state { + deviate add { + sonic-ext:field-name "admin-state"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:trib-protocol { + deviate add { + sonic-ext:field-name "trib-protocol"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:client-mapping-mode { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:link-state { + deviate add { + sonic-ext:field-name "link-state"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:index { + deviate add { + sonic-ext:field-transformer "logical_channel_field_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet { + deviate add { + sonic-ext:table-name "ETHERNET"; + sonic-ext:key-transformer "logical_channel_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:config { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:config/oc-opt-term:client-als { + deviate add { + sonic-ext:field-name "client-als"; + } + } + + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:config/oc-opt-term:als-delay { + deviate add { + sonic-ext:field-name "als-delay"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state { + deviate add { + sonic-ext:subtree-transformer "ethernet_subtree_xfmr"; + sonic-ext:subscribe-on-change "enable"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:in-8021q-frames { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:in-pcs-errored-seconds { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:out-pcs-bip-errors { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:in-block-errors { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:fec-uncorrectable-blocks { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:out-block-errors { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:in-pcs-severely-errored-seconds { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:in-mac-control-frames { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:in-pcs-bip-errors { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:in-jabber-frames { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:out-mac-pause-frames { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:esnr { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:min-time { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:max-time { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:instant { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:avg { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:min { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:max { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:interval { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:in-fragment-frames { + deviate add { + } + } + + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:als-delay { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:state/oc-opt-term:client-als { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config/oc-opt-term:description { + deviate add { + sonic-ext:field-name "description"; + // not found in schema but present in config_db.json in sonic-utilities + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config/oc-opt-term:test-signal { + deviate add { + sonic-ext:field-name "test-signal"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config/oc-opt-term:loopback-mode { + deviate add { + sonic-ext:field-name "loopback-mode"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:config/oc-opt-term:admin-state { + deviate add { + sonic-ext:field-name "admin-state"; + } + } + + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "LOGICAL_CHANNEL_TABLE"; + sonic-ext:key-transformer "logical_channel_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:rate-class { + deviate add { + sonic-ext:field-name "rate-class"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:description { + deviate add { + sonic-ext:field-name "description"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:logical-channel-type { + deviate add { + sonic-ext:field-name "logical-channel-type"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:test-signal { + deviate add { + sonic-ext:field-name "test-signal"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:loopback-mode { + deviate add { + sonic-ext:field-name "loopback-mode"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:admin-state { + deviate add { + sonic-ext:field-name "admin-state"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:trib-protocol { + deviate add { + sonic-ext:field-name "trib-protocol"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:state/oc-opt-term:link-state { + deviate add { + sonic-ext:field-name "link-state"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "LLDP_TABLE"; + sonic-ext:key-transformer "logical_channel_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:config { + deviate add { + } + } + + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:state/oc-opt-term:enabled { + deviate add { + sonic-ext:field-name "enabled"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:state/oc-opt-term:snooping { + deviate add { + sonic-ext:field-name "snooping"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors { + deviate add { + sonic-ext:db-name "STATE_DB"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "NEIGHBOR_TABLE"; + sonic-ext:key-transformer "neighbor_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:config { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "NEIGHBOR_TABLE"; + sonic-ext:key-transformer "neighbor_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state/oc-opt-term:port-description { + deviate add { + sonic-ext:field-name "port-description"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state/oc-opt-term:last-update { + deviate add { + sonic-ext:field-name "last-update"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:config/oc-opt-term:id { + deviate add { + sonic-ext:field-transformer "neighbor_field_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state/oc-opt-term:id { + deviate add { + sonic-ext:field-transformer "neighbor_field_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state/oc-opt-term:port-id-type { + deviate add { + sonic-ext:field-name "port-id-type"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state/oc-opt-term:port-id { + deviate add { + sonic-ext:field-name "port-id"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state/oc-opt-term:chassis-id-type { + deviate add { + sonic-ext:field-name "chassis-id-type"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state/oc-opt-term:ttl { + deviate add { + sonic-ext:field-name "ttl"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state/oc-opt-term:age { + deviate add { + sonic-ext:field-name "age"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state/oc-opt-term:chassis-id { + deviate add { + sonic-ext:field-name "chassis-id"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state/oc-opt-term:management-address-type { + deviate add { + sonic-ext:field-name "management-address-type"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state/oc-opt-term:system-description { + deviate add { + sonic-ext:field-name "system-description"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state/oc-opt-term:management-address { + deviate add { + sonic-ext:field-name "management-address"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:state/oc-opt-term:system-name { + deviate add { + sonic-ext:field-name "system-name"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments { + deviate add { + //sonic-ext:get-namespace "td_get_namespace_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment { + deviate add { + sonic-ext:table-name "ASSIGNMENT"; + sonic-ext:key-transformer "assignment_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:index { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:config { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:config/oc-opt-term:mapping { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:config/oc-opt-term:index { + deviate add { + sonic-ext:field-transformer "assignment_field_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:config/oc-opt-term:description { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:config/oc-opt-term:assignment-type { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:config/oc-opt-term:logical-channel { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:config/oc-opt-term:optical-channel { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:config/oc-opt-term:allocation { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:config/oc-opt-term:tributary-slot-index { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "ASSIGNMENT_TABLE"; + sonic-ext:key-transformer "assignment_key_xfmr"; + } + } + + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:state/oc-opt-term:mapping { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:state/oc-opt-term:index { + deviate add { + sonic-ext:field-transformer "assignment_field_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:state/oc-opt-term:description { + deviate add { + sonic-ext:field-name "description"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:state/oc-opt-term:assignment-type { + deviate add { + sonic-ext:field-name "assignment-type"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:state/oc-opt-term:logical-channel { + deviate add { + sonic-ext:field-transformer "ass_logical_field_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:state/oc-opt-term:optical-channel { + deviate add { + sonic-ext:field-name "optical-channel"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:state/oc-opt-term:allocation { + deviate add { + sonic-ext:field-name "allocation"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:logical-channel-assignments/oc-opt-term:assignment/oc-opt-term:state/oc-opt-term:tributary-slot-index { + deviate add { + sonic-ext:field-name "tributary-slot-index"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn { + deviate add { + sonic-ext:table-name "OTN"; + sonic-ext:key-transformer "logical_channel_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state { + deviate add { + sonic-ext:table-name "OTN_TABLE"; + sonic-ext:db-name "STATE_DB"; + sonic-ext:key-transformer "logical_channel_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:fec-corrected-bytes { + deviate add { + sonic-ext:table-name "OTN"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:key-transformer "otn_counter_key_xfmr"; + sonic-ext:field-name "fec-corrected-bytes"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:fec-corrected-bits { + deviate add { + sonic-ext:table-name "OTN"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:key-transformer "otn_counter_key_xfmr"; + sonic-ext:field-name "fec-corrected-bits"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:pre-fec-ber { + deviate add { + sonic-ext:table-name "OTN"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:key-transformer "otn_pre_fec_ber_counter_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:pre-fec-ber/oc-opt-term:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:pre-fec-ber/oc-opt-term:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:pre-fec-ber/oc-opt-term:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:pre-fec-ber/oc-opt-term:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:pre-fec-ber/oc-opt-term:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:pre-fec-ber/oc-opt-term:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:pre-fec-ber/oc-opt-term:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:code-violations { + deviate add { + sonic-ext:table-name "OTN"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:key-transformer "otn_counter_key_xfmr"; + sonic-ext:field-name "code-violations"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:errored-blocks { + deviate add { + sonic-ext:table-name "OTN"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:key-transformer "otn_counter_key_xfmr"; + sonic-ext:field-name "errored-blocks"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:tributary-slot-granularity { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:fec-uncorrectable-blocks { + deviate add { + sonic-ext:table-name "OTN"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:key-transformer "otn_counter_key_xfmr"; + sonic-ext:field-name "fec-uncorrectable-blocks"; + } + } + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:tti-msg-auto { + deviate add { + sonic-ext:field-name "tti-msg-auto"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:esnr { + deviate add { + sonic-ext:table-name "OTN"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:key-transformer "otn_esnr_counter_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:esnr/oc-opt-term:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:fec-uncorrectable-words { + deviate add { + sonic-ext:table-name "OTN"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:key-transformer "otn_counter_key_xfmr"; + sonic-ext:field-name "fec-uncorrectable-words"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:tti-msg-expected { + deviate add { + sonic-ext:field-name "tti-msg-expected"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:tti-msg-recv { + deviate add { + sonic-ext:field-name "tti-msg-recv"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:errored-seconds { + deviate add { + sonic-ext:table-name "OTN"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:key-transformer "otn_counter_key_xfmr"; + sonic-ext:field-name "errored-seconds"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:tti-msg-transmit { + deviate add { + sonic-ext:field-name "tti-msg-transmit"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:severely-errored-seconds { + deviate add { + sonic-ext:table-name "OTN"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:key-transformer "otn_counter_key_xfmr"; + sonic-ext:field-name "severely-errored-seconds"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:rdi-msg { + deviate add { + sonic-ext:field-name "rdi-msg"; + } + } + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:unavailable-seconds { + deviate add { + sonic-ext:table-name "OTN"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:key-transformer "otn_counter_key_xfmr"; + sonic-ext:field-name "unavailable-seconds"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:post-fec-ber { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OTN"; + sonic-ext:key-transformer "otn_post_fec_ber_counter_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:post-fec-ber/oc-opt-term:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:post-fec-ber/oc-opt-term:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:post-fec-ber/oc-opt-term:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:post-fec-ber/oc-opt-term:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:post-fec-ber/oc-opt-term:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:post-fec-ber/oc-opt-term:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:post-fec-ber/oc-opt-term:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:q-value { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "OTN"; + sonic-ext:key-transformer "otn_qvalue_counter_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:q-value/oc-opt-term:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:q-value/oc-opt-term:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:q-value/oc-opt-term:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:q-value/oc-opt-term:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:q-value/oc-opt-term:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:q-value/oc-opt-term:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:q-value/oc-opt-term:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:state/oc-opt-term:background-block-errors { + deviate add { + sonic-ext:table-name "OTN"; + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:key-transformer "otn_counter_key_xfmr"; + sonic-ext:field-name "background-block-errors"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:-channel/oc-opt-term:otn/oc-opt-term:config { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:config/oc-opt-term:tti-msg-expected { + deviate add { + sonic-ext:field-name "tti-msg-expected"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:config/oc-opt-term:tti-msg-auto { + deviate add { + sonic-ext:field-name "tti-msg-auto"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:config/oc-opt-term:tributary-slot-granularity { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:otn/oc-opt-term:config/oc-opt-term:tti-msg-transmit { + deviate add { + sonic-ext:field-name "tti-msg-transmit"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:operational-modes { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "MODE_TABLE"; + sonic-ext:get-namespace "td_get_namespace_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:operational-modes/oc-opt-term:mode { + deviate add { + sonic-ext:key-transformer "mode_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:operational-modes/oc-opt-term:mode/oc-opt-term:config { + deviate add { + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:operational-modes/oc-opt-term:mode/oc-opt-term:state { + deviate add { + sonic-ext:table-name "MODE_TABLE"; + sonic-ext:key-transformer "mode_key_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:operational-modes/oc-opt-term:mode/oc-opt-term:state/oc-opt-term:vendor-id { + deviate add { + sonic-ext:field-name "vendor-id"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:operational-modes/oc-opt-term:mode/oc-opt-term:config/oc-opt-term:mode-id { + deviate add { + sonic-ext:field-transformer "mode_field_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:operational-modes/oc-opt-term:mode/oc-opt-term:state/oc-opt-term:mode-id { + deviate add { + sonic-ext:field-transformer "mode_field_xfmr"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:operational-modes/oc-opt-term:mode/oc-opt-term:state/oc-opt-term:description { + deviate add { + sonic-ext:field-name "description"; + } + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:operational-modes/oc-opt-term:mode/oc-opt-term:mode-id { + deviate add { + } + } + +} diff --git a/models/yang/annotations/openconfig-test-xfmr-annot.yang b/models/yang/annotations/openconfig-test-xfmr-annot.yang new file mode 100644 index 000000000..c76098642 --- /dev/null +++ b/models/yang/annotations/openconfig-test-xfmr-annot.yang @@ -0,0 +1,173 @@ +module openconfig-test-xfmr-annot { + + yang-version "1"; + + namespace "http://openconfig.net/yang/annotation/oc-test-xfmr-annot"; + prefix "oc-test-xfmr-annot"; + + import openconfig-extensions { prefix oc-ext; } + import openconfig-test-xfmr { prefix oc-test-xfmr; } + import sonic-extensions { prefix sonic-ext; } + + deviation /oc-test-xfmr:test-xfmr { + deviate add { + sonic-ext:pre-transformer "test_pre_xfmr"; + sonic-ext:post-transformer "test_post_xfmr"; + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group { + deviate add { + sonic-ext:table-name "TEST_SENSOR_GROUP"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:config/oc-test-xfmr:group-colors { + deviate add { + sonic-ext:field-name "colors"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:state/oc-test-xfmr:group-colors { + deviate add { + sonic-ext:field-name "colors"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:state/oc-test-xfmr:counters { + deviate add { + sonic-ext:table-name "TEST_SENSOR_GROUP_COUNTERS"; + sonic-ext:db-name "COUNTERS_DB"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types { + deviate add { + sonic-ext:table-name "NONE"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type { + deviate add { + sonic-ext:table-transformer "test_sensor_type_tbl_xfmr"; + sonic-ext:key-transformer "test_sensor_type_key_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type/oc-test-xfmr:config/oc-test-xfmr:type { + deviate add { + sonic-ext:field-transformer "test_sensor_type_field_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type/oc-test-xfmr:config/oc-test-xfmr:exclude-filter { + deviate add { + sonic-ext:field-transformer "exclude_filter_field_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type/oc-test-xfmr:state/oc-test-xfmr:type { + deviate add { + sonic-ext:field-transformer "test_sensor_type_field_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type/oc-test-xfmr:state/oc-test-xfmr:exclude-filter { + deviate add { + sonic-ext:field-transformer "exclude_filter_field_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type/oc-test-xfmr:sensor-a-light-sensors { + deviate add { + sonic-ext:table-name "NONE"; + sonic-ext:get-validate "light_sensor_validate"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type/oc-test-xfmr:sensor-a-light-sensors/oc-test-xfmr:sensor-a-light-sensor { + deviate add { + sonic-ext:table-name "TEST_SENSOR_A_LIGHT_SENSOR_TABLE"; + sonic-ext:key-transformer "sensor_a_light_sensor_key_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-components/oc-test-xfmr:test-sensor-component { + deviate add { + sonic-ext:table-name "TEST_SENSOR_COMPONENT_TABLE"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-zones { + deviate add { + sonic-ext:table-name "NONE"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-zones/oc-test-xfmr:test-sensor-zone { + deviate add { + sonic-ext:table-name "TEST_SENSOR_ZONE_TABLE"; + sonic-ext:key-transformer "test_sensor_zone_key_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set { + deviate add { + sonic-ext:table-name "TEST_SET_TABLE"; + sonic-ext:key-transformer "test_set_key_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set/oc-test-xfmr:config/oc-test-xfmr:type { + deviate add { + sonic-ext:field-transformer "test_set_type_field_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set/oc-test-xfmr:config/oc-test-xfmr:name { + deviate add { + sonic-ext:field-transformer "test_set_name_field_xfmr"; + } + } + + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set/oc-test-xfmr:config/oc-test-xfmr:description { + deviate add { + sonic-ext:field-transformer "test_set_description_field_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set/oc-test-xfmr:state/oc-test-xfmr:name { + deviate add { + sonic-ext:field-transformer "test_set_name_field_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set/oc-test-xfmr:state/oc-test-xfmr:type { + deviate add { + sonic-ext:field-transformer "test_set_type_field_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set/oc-test-xfmr:state/oc-test-xfmr:description { + deviate add { + sonic-ext:field-transformer "test_set_description_field_xfmr"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:interfaces { + deviate add { + sonic-ext:subtree-transformer "test_port_bindings_xfmr"; + sonic-ext:virtual-table "true"; + } + } + + deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:global-sensor { + deviate add { + sonic-ext:table-name "TEST_SENSOR_GLOBAL"; + sonic-ext:key-name "global_sensor"; + } + } +} + diff --git a/models/yang/annotations/openconfig-transport-line-protection-annot.yang b/models/yang/annotations/openconfig-transport-line-protection-annot.yang new file mode 100644 index 000000000..394eef857 --- /dev/null +++ b/models/yang/annotations/openconfig-transport-line-protection-annot.yang @@ -0,0 +1,638 @@ +module openconfig-transport-line-protection-annot { + + yang-version ""; + + namespace "http://openconfig.net/yang/annotation/oc-line-protect-annot"; + prefix "oc-line-protect-annot"; + + import openconfig-extensions { prefix oc-ext; } + import openconfig-types { prefix oc-types; } + import openconfig-platform { prefix oc-platform; } + import openconfig-transport-line-protection { prefix oc-line-protect; } + import sonic-extensions { prefix sonic-ext; } + + deviation /oc-line-protect:aps { + deviate add { + sonic-ext:subscribe-on-change "enable"; + sonic-ext:get-namespace "aps_name_get_namespace_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules { + deviate add { + sonic-ext:table-name "APS"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module { + deviate add { + sonic-ext:key-transformer "aps_name_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:config { + deviate add { + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:config/oc-line-protect:force-to-port { + deviate add { + sonic-ext:field-name "force-to-port"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:config/oc-line-protect:name { + deviate add { + sonic-ext:field-transformer "aps_name_field_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "APS_TABLE"; + sonic-ext:key-transformer "aps_name_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:state/oc-line-protect:primary-switch-hysteresis { + deviate add { + sonic-ext:field-name "primary-switch-hysteresis"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:state/oc-line-protect:primary-switch-threshold { + deviate add { + sonic-ext:field-name "primary-switch-threshold"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:state/oc-line-protect:relative-switch-threshold-offset { + deviate add { + sonic-ext:field-name "relative-switch-threshold-offset"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:state/oc-line-protect:force-to-port { + deviate add { + sonic-ext:field-name "force-to-port"; //type enumersation need to check how it is working.. + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:state/oc-line-protect:hold-off-time { + deviate add { + sonic-ext:field-name "hold-off-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:state/oc-line-protect:active-path { + deviate add { + sonic-ext:field-name "active-path"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:state/oc-line-protect:revertive { + deviate add { + sonic-ext:field-name "revertive"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:state/oc-line-protect:secondary-switch-threshold { + deviate add { + sonic-ext:field-name "secondary-switch-threshold"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:state/oc-line-protect:relative-switch-threshold { + deviate add { + sonic-ext:field-name "relative-switch-threshold"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:state/oc-line-protect:name { + deviate add { + sonic-ext:field-transformer "aps_name_field_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:state/oc-line-protect:wait-to-restore-time { + deviate add { + sonic-ext:field-name "wait-to-restore-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports { + deviate add { + sonic-ext:table-name "APS_PORT"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-output { + deviate add { + sonic-ext:key-transformer "aps_port_commonOut_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-output/oc-line-protect:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "APS_PORT_TABLE"; + sonic-ext:key-transformer "aps_port_commonOut_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-output/oc-line-protect:state/oc-line-protect:target-attenuation { + deviate add { + sonic-ext:field-name "target-attenuation"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-output/oc-line-protect:state/oc-line-protect:optical-power { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "APS_PORT"; + sonic-ext:key-transformer "aps_counter_commonOut_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-output/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-output/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-output/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-output/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-output/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-output/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-output/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-output/oc-line-protect:state/oc-line-protect:attenuation { + deviate add { + sonic-ext:field-name "attenuation"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-output/oc-line-protect:config { + deviate add { + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in { + deviate add { + sonic-ext:key-transformer "aps_port_LinePrimaryIn_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in/oc-line-protect:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "APS_PORT_TABLE"; + sonic-ext:key-transformer "aps_port_LinePrimaryIn_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in/oc-line-protect:state/oc-line-protect:enabled { + deviate add { + sonic-ext:field-name "enabled"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in/oc-line-protect:state/oc-line-protect:attenuation { + deviate add { + sonic-ext:field-name "attenuation"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in/oc-line-protect:state/oc-line-protect:optical-power { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "APS_PORT"; + sonic-ext:key-transformer "aps_counter_linePrimaryIn_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in/oc-line-protect:state/oc-line-protect:target-attenuation { + deviate add { + sonic-ext:field-name "target-attenuation"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-in/oc-line-protect:config { + deviate add { + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-out { + deviate add { + sonic-ext:key-transformer "aps_port_LinePrimaryOut_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-out/oc-line-protect:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "APS_PORT_TABLE"; + sonic-ext:key-transformer "aps_port_LinePrimaryOut_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-out/oc-line-protect:state/oc-line-protect:optical-power { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "APS_PORT"; + sonic-ext:key-transformer "aps_counter_linePrimaryOut_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-out/oc-line-protect:state/oc-line-protect:target-attenuation { + deviate add { + sonic-ext:field-name "target-attenuation"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-out/oc-line-protect:state/oc-line-protect:attenuation { + deviate add { + sonic-ext:field-name "attenuation"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-primary-out/oc-line-protect:config { + deviate add { + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in { + deviate add { + sonic-ext:key-transformer "aps_port_lineSecondaryIn_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in/oc-line-protect:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "APS_PORT_TABLE"; + sonic-ext:key-transformer "aps_port_lineSecondaryIn_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in/oc-line-protect:state/oc-line-protect:attenuation { + deviate add { + sonic-ext:field-name "attenuation"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in/oc-line-protect:state/oc-line-protect:optical-power { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "APS_PORT"; + sonic-ext:key-transformer "aps_counter_lineSecondaryIn_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in/oc-line-protect:state/oc-line-protect:enabled { + deviate add { + sonic-ext:field-name "enabled"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in/oc-line-protect:state/oc-line-protect:target-attenuation { + deviate add { + sonic-ext:field-name "target-attenuation"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-in/oc-line-protect:config { + deviate add { + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-out { + deviate add { + sonic-ext:key-transformer "aps_port_lineSecondaryOut_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-out/oc-line-protect:config { + deviate add { + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-out/oc-line-protect:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "APS_PORT_TABLE"; + sonic-ext:key-transformer "aps_port_lineSecondaryOut_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-out/oc-line-protect:state/oc-line-protect:target-attenuation { + deviate add { + sonic-ext:field-name "target-attenuation"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-out/oc-line-protect:state/oc-line-protect:attenuation { + deviate add { + sonic-ext:field-name "attenuation"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-out/oc-line-protect:state/oc-line-protect:optical-power { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "APS_PORT"; + sonic-ext:key-transformer "aps_counter_lineSecondaryOut_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:line-secondary-out/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in { + deviate add { + sonic-ext:key-transformer "aps_port_commonIn_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in/oc-line-protect:config { + deviate add { + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in/oc-line-protect:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "APS_PORT_TABLE"; + sonic-ext:key-transformer "aps_port_commonIn_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in/oc-line-protect:state/oc-line-protect:optical-power { + deviate add { + sonic-ext:db-name "COUNTERS_DB"; + sonic-ext:table-name "APS_PORT"; + sonic-ext:key-transformer "aps_counter_commonIn_key_xfmr"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:min { + deviate add { + sonic-ext:field-name "min"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:max { + deviate add { + sonic-ext:field-name "max"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:interval { + deviate add { + sonic-ext:field-name "interval"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:max-time { + deviate add { + sonic-ext:field-name "max-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:min-time { + deviate add { + sonic-ext:field-name "min-time"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:instant { + deviate add { + sonic-ext:field-name "instant"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in/oc-line-protect:state/oc-line-protect:optical-power/oc-line-protect:avg { + deviate add { + sonic-ext:field-name "avg"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in/oc-line-protect:state/oc-line-protect:enabled { + deviate add { + sonic-ext:field-name "enabled"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in/oc-line-protect:state/oc-line-protect:target-attenuation { + deviate add { + sonic-ext:field-name "target-attenuation"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:ports/oc-line-protect:common-in/oc-line-protect:state/oc-line-protect:attenuation { + deviate add { + sonic-ext:field-name "attenuation"; + } + } + + deviation /oc-line-protect:aps/oc-line-protect:aps-modules/oc-line-protect:aps-module/oc-line-protect:name { + deviate add { + } + } +} diff --git a/models/yang/annotations/openconfig-wavelength-router-annot.yang b/models/yang/annotations/openconfig-wavelength-router-annot.yang new file mode 100644 index 000000000..8dfaf07a3 --- /dev/null +++ b/models/yang/annotations/openconfig-wavelength-router-annot.yang @@ -0,0 +1,377 @@ +module openconfig-wavelength-router-annot { + + yang-version "1"; + + namespace "http://openconfig.net/yang/annotation/oc-wave-router-annot"; + prefix "oc-wave-router-annot"; + + import openconfig-extensions { prefix oc-ext; } + import openconfig-platform { prefix oc-platform; } + import openconfig-transport-types { prefix oc-opt-types; } + import openconfig-wavelength-router { prefix oc-wave-router; } + import sonic-extensions { prefix sonic-ext; } + + deviation /oc-wave-router:wavelength-router { + deviate add { + sonic-ext:post-transformer "media_channel_post_xfmr"; + sonic-ext:subscribe-on-change "enable"; + sonic-ext:get-namespace "media_channel_get_namespace_xfmr"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels { + deviate add { + sonic-ext:table-name "MEDIA_CHANNEL"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel { + deviate add { + sonic-ext:key-transformer "media_channel_key_xfmr"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:index { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:ase-injection-mode { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:lower-frequency { + deviate add { + sonic-ext:field-name "lower-frequency"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:admin-status { + deviate add { + sonic-ext:field-name "admin-status"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:ase-control-mode { + deviate add { + sonic-ext:field-name "ase-control-mode"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:super-channel-parent { + deviate add { + sonic-ext:field-name "super-channel-parent"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:max-undershoot-compensation { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:max-overshoot-compensation { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:ase-injection-threshold { + deviate add { + sonic-ext:field-name "ase-injection-threshold"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:attenuation-control-mode { + deviate add { + sonic-ext:field-name "attenuation-control-mode"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:index { + deviate add { + sonic-ext:field-transformer "media_channel_field_xfmr"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:super-channel { + deviate add { + sonic-ext:field-name "super-channel"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:media-channel-injection-offset { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:upper-frequency { + deviate add { + sonic-ext:field-name "upper-frequency"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:attenuation-control-range { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:ase-injection-delta { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:config/oc-wave-router:name { + deviate add { + sonic-ext:field-name "name"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "MEDIA_CHANNEL_TABLE"; + sonic-ext:key-transformer "media_channel_key_xfmr"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:ase-injection-mode { + deviate add { + sonic-ext:field-name "ase-injection-mode"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:ase-control-mode { + deviate add { + sonic-ext:field-name "ase-control-mode"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:ase-injection-delta { + deviate add { + sonic-ext:field-name "ase-injection-delta"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:attenuation-control-range { + deviate add { + sonic-ext:field-name "attenuation-control-range"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:index { + deviate add { + sonic-ext:field-transformer "media_channel_field_xfmr"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:name { + deviate add { + sonic-ext:field-name "name"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:oper-status { + deviate add { + sonic-ext:field-name "oper-status"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:super-channel { + deviate add { + sonic-ext:field-name "super-channel"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:ase-injection-threshold { + deviate add { + sonic-ext:field-name "ase-injection-threshold"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:media-channel-injection-offset { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:max-overshoot-compensation { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:ase-status { + deviate add { + sonic-ext:field-name "ase-status"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:max-undershoot-compensation { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:lower-frequency { + deviate add { + sonic-ext:field-name "lower-frequency"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:attenuation-control-mode { + deviate add { + sonic-ext:field-name "attenuation-control-mode"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:upper-frequency { + deviate add { + sonic-ext:field-name "upper-frequency"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:super-channel-parent { + deviate add { + sonic-ext:field-name "super-channel-parent"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:state/oc-wave-router:admin-status { + deviate add { + sonic-ext:field-name "admin-status"; + } + } + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:source { + deviate add { + //sonic-ext:table-name "MEDIA_CHANNEL"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:source/oc-wave-router:config { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:source/oc-wave-router:config/oc-wave-router:port-name { + deviate add { + sonic-ext:field-name "source-port-name"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:source/oc-wave-router:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "MEDIA_CHANNEL_TABLE"; + sonic-ext:key-transformer "media_channel_key_xfmr"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:source/oc-wave-router:state/oc-wave-router:port-name { + deviate add { + sonic-ext:field-name "source-port-name"; + } + } +deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:dest { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:dest/oc-wave-router:config { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:dest/oc-wave-router:config/oc-wave-router:port-name { + deviate add { + sonic-ext:field-name "dest-port-name"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:dest/oc-wave-router:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "MEDIA_CHANNEL_TABLE"; + sonic-ext:key-transformer "media_channel_key_xfmr"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:dest/oc-wave-router:state/oc-wave-router:port-name { + deviate add { + sonic-ext:field-name "dest-port-name"; + + } + } + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:spectrum-power-profile { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:spectrum-power-profile/oc-wave-router:distribution { + deviate add { + sonic-ext:table-name "MEDIA_CHANNEL_DISTRIBUTION"; + sonic-ext:key-transformer "media_channel_distribution_key_xfmr"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:spectrum-power-profile/oc-wave-router:distribution/oc-wave-router:lower-frequency { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:spectrum-power-profile/oc-wave-router:distribution/oc-wave-router:upper-frequency { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:spectrum-power-profile/oc-wave-router:distribution/oc-wave-router:config { + deviate add { + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:spectrum-power-profile/oc-wave-router:distribution/oc-wave-router:config/oc-wave-router:target-power { + deviate add { + sonic-ext:field-name "target-power"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:spectrum-power-profile/oc-wave-router:distribution/oc-wave-router:config/oc-wave-router:lower-frequency { + deviate add { + sonic-ext:field-transformer "media_channel_lf_field_xfmr"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:spectrum-power-profile/oc-wave-router:distribution/oc-wave-router:config/oc-wave-router:upper-frequency { + deviate add { + sonic-ext:field-transformer "media_channel_uf_field_xfmr"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:spectrum-power-profile/oc-wave-router:distribution/oc-wave-router:state { + deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "MEDIA_CHANNEL_DISTRIBUTION_TABLE"; + sonic-ext:key-transformer "media_channel_distribution_key_xfmr"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:spectrum-power-profile/oc-wave-router:distribution/oc-wave-router:state/oc-wave-router:upper-frequency { + deviate add { + sonic-ext:field-transformer "media_channel_uf_field_xfmr"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:spectrum-power-profile/oc-wave-router:distribution/oc-wave-router:state/oc-wave-router:target-power { + deviate add { + sonic-ext:field-name "target-power"; + } + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:media-channels/oc-wave-router:channel/oc-wave-router:spectrum-power-profile/oc-wave-router:distribution/oc-wave-router:state/oc-wave-router:lower-frequency { + deviate add { + sonic-ext:field-transformer "media_channel_lf_field_xfmr"; + } + } +} + diff --git a/models/yang/annotations/sonic-test-xfmr-annot.yang b/models/yang/annotations/sonic-test-xfmr-annot.yang new file mode 100644 index 000000000..31a1034e6 --- /dev/null +++ b/models/yang/annotations/sonic-test-xfmr-annot.yang @@ -0,0 +1,62 @@ +module sonic-test-xfmr-annot { + + yang-version "1"; + + namespace "http://openconfig.net/yang/annotation/sonic-test-xfmr-annot"; + prefix "sonic-test-xfmr-annot"; + + import sonic-test-xfmr { prefix sonic-test-xfmr; } + + deviation /sonic-test-xfmr:sonic-test-xfmr { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } + + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_SENSOR_MODE_TABLE/sonic-test-xfmr:TEST_SENSOR_MODE_TABLE_LIST { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + sonic-ext:key-transformer "test_sensor_mode_key_xfmr"; + } + } + + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_SENSOR_A_TABLE/sonic-test-xfmr:TEST_SENSOR_A_TABLE_LIST { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } + + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_SENSOR_GROUP/sonic-test-xfmr:TEST_SENSOR_GROUP_LIST { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } + + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_INTERFACE_MODE_TABLE/sonic-test-xfmr:TEST_INTERFACE_MODE_TABLE_LIST { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } + + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_SENSOR_GLOBAL + { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } + + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_CABLE_LENGTH/sonic-test-xfmr:TEST_CABLE_LENGTH_LIST + { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } + + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_SENSOR_MODE_TABLE/sonic-test-xfmr:TEST_SENSOR_MODE_TABLE_LIST + { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } +} + diff --git a/models/yang/common/openconfig-platform-transceiver.yang b/models/yang/common/openconfig-platform-transceiver.yang index 5a43801fe..2c2cee442 100644 --- a/models/yang/common/openconfig-platform-transceiver.yang +++ b/models/yang/common/openconfig-platform-transceiver.yang @@ -281,6 +281,7 @@ module openconfig-platform-transceiver { component and the module-functional-type is TYPE_DIGITAL_COHERENT_OPTIC this grouping will NOT be used as the data will be within the optical-channel."; + } } @@ -436,6 +437,24 @@ module openconfig-platform-transceiver { reference "QSFP-DD CMIS 5.0 Table 8-78"; } + uses physical-channel-state-extended { + when "../../../state/module-functional-type = 'oc-opt-types:TYPE_STANDARD_OPTIC'" { + description + "When the physical channel is of TYPE_STANDARD_OPTIC, the + extended state will be used"; + } + } + } + + grouping physical-channel-state-extended { + description + "Extended operational state data for physical client channels + for applications where the full physical channel config and + state are used. In some cases, such as when the physical + channel has a leafref to an optical channel component and the + module-functional-type is TYPE_DIGITAL_COHERENT_OPTIC this + grouping will NOT be used."; + uses output-optical-frequency; uses optical-power-state; } diff --git a/models/yang/common/openconfig-telemetry-types.yang b/models/yang/common/openconfig-telemetry-types.yang new file mode 100644 index 000000000..66c0bf6b5 --- /dev/null +++ b/models/yang/common/openconfig-telemetry-types.yang @@ -0,0 +1,124 @@ +module openconfig-telemetry-types { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/telemetry-types"; + + prefix "oc-telemetry-types"; + + import openconfig-extensions { prefix oc-ext; } + + + // meta + organization "OpenConfig working group"; + + contact + "OpenConfig working group + www.openconfig.net"; + + description + "This module defines type and identities used by the OpenConfig + telemetry model."; + + oc-ext:openconfig-version "0.4.2"; + + revision "2018-11-21" { + description + "Add OpenConfig module metadata extensions."; + reference "0.4.2"; + } + + revision "2017-08-24" { + description + "Minor formatting fixes"; + reference "0.4.1"; + } + + revision "2017-02-20" { + description + "Fixes for YANG 1.0 compliance, add types module"; + reference "0.4.0"; + } + + revision "2016-04-05" { + description + "OpenConfig public release"; + reference "0.2.0"; + } + + // OpenConfig specific extensions for module metadata. + oc-ext:regexp-posix; + oc-ext:catalog-organization "openconfig"; + oc-ext:origin "openconfig"; + + // identity statements + + identity DATA_ENCODING_METHOD { + description + "Base identity for supported encoding for configuration and + operational state data"; + } + + identity ENC_XML { + base DATA_ENCODING_METHOD; + description + "XML encoding"; + } + + identity ENC_JSON_IETF { + base DATA_ENCODING_METHOD; + description + "JSON encoded based on IETF draft standard"; + reference + "draft-ietf-netmod-yang-json"; + } + + identity ENC_PROTO3 { + base DATA_ENCODING_METHOD; + description + "Protocol buffers v3"; + reference + "https://developers.google.com/protocol-buffers/docs/overview"; + } + + identity STREAM_PROTOCOL { + description "Base identity for a telemetry stream protocol"; + } + + identity STREAM_SSH { + base "STREAM_PROTOCOL"; + description + "Telemetry stream is carried over a SSH connection"; + } + + identity STREAM_GRPC { + base "STREAM_PROTOCOL"; + description + "Telemetry stream is carried over via the gRPC framework"; + } + + identity STREAM_JSON_RPC { + base "STREAM_PROTOCOL"; + description + "Telemetry stream is carried via the JSON-RPC framework"; + } + + identity STREAM_THRIFT_RPC { + base "STREAM_PROTOCOL"; + description + "Telemetry stream is carried via the Apache Thrift framework"; + } + + identity STREAM_WEBSOCKET_RPC { + base "STREAM_PROTOCOL"; + description + "Telemetry stream is carried by the WebSocket framework"; + } + + + // typedef statements + + + +} diff --git a/models/yang/common/openconfig-transport-line-common.yang b/models/yang/common/openconfig-transport-line-common.yang index 09c9c3855..e195d37f9 100644 --- a/models/yang/common/openconfig-transport-line-common.yang +++ b/models/yang/common/openconfig-transport-line-common.yang @@ -8,13 +8,14 @@ module openconfig-transport-line-common { prefix "oc-line-com"; // import some basic types -//import iana-if-type { prefix ianaift; } + import iana-if-type { prefix ianaift; } import openconfig-extensions { prefix oc-ext; } -//import openconfig-interfaces { prefix oc-if; } + import openconfig-interfaces { prefix oc-if; } import openconfig-platform { prefix oc-platform; } import openconfig-types { prefix oc-types; } import openconfig-transport-types { prefix oc-opt-types; } -//import openconfig-platform-transceiver { prefix oc-transceiver; } + import openconfig-platform-transceiver { prefix oc-transceiver; } + // meta @@ -106,8 +107,7 @@ module openconfig-transport-line-common { "Configuration data for OSC interfaces"; leaf interface { - type string; - //type oc-if:base-interface-ref; + type oc-if:base-interface-ref; description "Reference to an OSC interface"; } @@ -289,7 +289,6 @@ module openconfig-transport-line-common { uses transport-line-common-port-top; } -/***** OPLINK - not used for now //TODO:this is placeholder until SONET model is added //to interfaces model augment "/oc-if:interfaces/oc-if:interface" { @@ -305,7 +304,6 @@ module openconfig-transport-line-common { "Data related to SONET/SDH interfaces"; } } -*****/ // rpc statements diff --git a/models/yang/extensions/openconfig-terminal-device-deviation.yang b/models/yang/extensions/openconfig-terminal-device-deviation.yang new file mode 100644 index 000000000..14092f1cb --- /dev/null +++ b/models/yang/extensions/openconfig-terminal-device-deviation.yang @@ -0,0 +1,30 @@ +module openconfig-terminal-device-deviation { + + yang-version "1"; + + namespace "http://openconfig.net/yang/deviation/oc-terminal-device-deviation"; + prefix "oc-terminal-device-deviation"; + + import openconfig-extensions { prefix oc-ext; } + import openconfig-terminal-device { prefix oc-opt-term; } + + organization "SONiC"; + contact + "SONiC"; + description + "This is a deviation yang for openconfig terminal device."; + + oc-ext:openconfig-version "0.1.0"; + + revision 2020-06-23 { + description + "Initial version."; + reference "0.1.0"; + } + + deviation /oc-opt-term:terminal-device/oc-opt-term:logical-channels/oc-opt-term:channel/oc-opt-term:ethernet/oc-opt-term:lldp/oc-opt-term:neighbors/oc-opt-term:neighbor/oc-opt-term:custom-tlvs { + deviate not-supported; + } + +} + diff --git a/models/yang/extensions/openconfig-wavelength-router-deviation.yang b/models/yang/extensions/openconfig-wavelength-router-deviation.yang new file mode 100644 index 000000000..398973a45 --- /dev/null +++ b/models/yang/extensions/openconfig-wavelength-router-deviation.yang @@ -0,0 +1,29 @@ +module openconfig-wavelength-router-deviation { + + yang-version "1"; + + namespace "http://openconfig.net/yang/deviation/oc-wavelength-router-deviation"; + prefix "oc-wavelength-router-deviation"; + + import openconfig-extensions { prefix oc-ext; } + import openconfig-wavelength-router { prefix oc-wave-router; } + + organization "SONiC"; + contact + "SONiC"; + description + "This is a deviation yang for openconfig terminal device."; + + oc-ext:openconfig-version "0.1.0"; + + revision 2020-06-23 { + description + "Initial version."; + reference "0.1.0"; + } + + deviation /oc-wave-router:wavelength-router/oc-wave-router:port-spectrum-power-profiles { + deviate not-supported; + } + +} diff --git a/models/yang/openconfig-optical-time-domain-reflectometer.yang b/models/yang/openconfig-optical-time-domain-reflectometer.yang index 308b27b9c..ce68bc581 100644 --- a/models/yang/openconfig-optical-time-domain-reflectometer.yang +++ b/models/yang/openconfig-optical-time-domain-reflectometer.yang @@ -3,7 +3,7 @@ module openconfig-optical-time-domain-reflectometer { yang-version "1"; // namespace - namespace "http://openconfig.net/yang/otdr"; + namespace "http://openconfig.net/yang/optical-time-domain-reflectometer"; prefix "oc-otdr"; @@ -626,4 +626,5 @@ module openconfig-optical-time-domain-reflectometer { } } -} \ No newline at end of file +} + diff --git a/models/yang/openconfig-platform-transceiver.yang b/models/yang/openconfig-platform-transceiver.yang new file mode 100644 index 000000000..c70a4fdda --- /dev/null +++ b/models/yang/openconfig-platform-transceiver.yang @@ -0,0 +1,778 @@ +module openconfig-platform-transceiver { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/platform/transceiver"; + + prefix "oc-transceiver"; + + // import some basic types + import ietf-yang-types { prefix yang; } + import openconfig-platform { prefix oc-platform; } + import openconfig-platform-types { prefix oc-platform-types; } + import openconfig-platform-port { prefix oc-port; } + import openconfig-interfaces { prefix oc-if; } + import openconfig-transport-types { prefix oc-opt-types; } + import openconfig-types { prefix oc-types; } + import openconfig-extensions { prefix oc-ext; } + import openconfig-yang-types { prefix oc-yang; } + + + // meta + organization "OpenConfig working group"; + + contact + "OpenConfig working group + www.openconfig.net"; + + description + "This module defines configuration and operational state data + for transceivers (i.e., pluggable optics). The module should be + used in conjunction with the platform model where other + physical entity data are represented. + + In the platform model, a component of type=TRANSCEIVER is + expected to be a subcomponent of a PORT component. This + module defines a concrete schema for the associated data for + components with type=TRANSCEIVER. + + A transceiver will always contain physical-channel(s), however + when a line side optical-channel is present (i.e. ZR+ optics) + the physical-channel will reference its optical-channel. + In this case, the optical-channels components must be + subcomponents of the transceiver. The relationship between the + physical-channel and the optical-channel allows for multiple + optical-channels to be associated with a transceiver in addition + to ensuring certain leaves (i.e. output-power) are not duplicated + in multiple components. + + If a transceiver contains a digital signal processor (DSP), such + as with ZR+ optics, the modeling will utilize hierarchical + components as follows: + PORT --> TRANSCEIVER --> OPTICAL_CHANNEL(s) + The signal will then traverse through a series of + terminal-device/logical-channels as required. The first + logical-channel connected to the OPTICAL_CHANNEL will utilize the + assignment/optical-channel leaf to create the relationship. At the + conclusion of the series of logical-channels, the logical-channel + will be associated to its host / client side based on: + * If the TRANSCEIVER is directly within a router or switch, then + it will use the logical-channel ingress leaf to specify the + interface it is associated with. + * If the TRANSCEIVER is within a dedicated terminal (Layer 1) + device, then it will use the logical-channel ingress leaf to + specify a physical-channel within a TRANSCEIVER component + (i.e. gray optic) that it is associated with."; + + oc-ext:openconfig-version "0.9.0"; + + revision "2021-07-29" { + description + "Add several media-lane-based VDM defined by CMIS to physical channel"; + reference "0.9.0"; + } + + revision "2021-02-23" { + description + "Add leafref to an optical channel from a physical channel."; + reference "0.8.0"; + } + + revision "2020-05-06" { + description + "Ensure that when statements in read-write contexts reference + only read-write leaves."; + reference "0.7.1"; + } + + revision "2018-11-25" { + description + "Add augment for leafref to transceiver component; + Correct paths in physical channels leafref."; + reference "0.7.0"; + } + + revision "2018-11-21" { + description + "Add OpenConfig module metadata extensions."; + reference "0.6.1"; + } + + revision "2018-11-16" { + description + "Added transceiver FEC configuration and state"; + reference "0.6.0"; + } + + revision "2018-05-15" { + description + "Remove internal-temp state leaf, since we prefer + the generic /components/component/state/temperature + container for temperature information."; + reference "0.5.0"; + } + + revision "2018-01-22" { + description + "Fixed physical-channel path reference"; + reference "0.4.1"; + } + + revision "2017-09-18" { + description + "Use openconfig-yang-types module"; + reference "0.4.0"; + } + + revision "2017-07-08" { + description + "Adds clarification on aggregate power measurement data"; + reference "0.3.0"; + } + + revision "2016-12-22" { + description + "Adds preconfiguration data and clarified units"; + reference "0.2.0"; + } + + // OpenConfig specific extensions for module metadata. + oc-ext:regexp-posix; + oc-ext:catalog-organization "openconfig"; + oc-ext:origin "openconfig"; + + // identity statements + + // typedef statements + + // grouping statements + + grouping optical-power-state { + description + "Reusable leaves related to optical power state -- these + are read-only state values. If avg/min/max statistics are + not supported, the target is expected to just supply the + instant value"; + + container output-power { + description + "The output optical power of a physical channel in units + of 0.01dBm, which may be associated with individual + physical channels, or an aggregate of multiple physical + channels (i.e., for the overall transceiver). For an + aggregate, this may be a measurement from a photodetector + or a a calculation performed on the device by summing up + all of the related individual physical channels. + Values include the instantaneous, average, minimum, and + maximum statistics. If avg/min/max statistics are not + supported, the target is expected to just supply the + instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container input-power { + description + "The input optical power of a physical channel in units + of 0.01dBm, which may be associated with individual + physical channels, or an aggregate of multiple physical + channels (i.e., for the overall transceiver). For an + aggregate, this may be a measurement from a photodetector + or a a calculation performed on the device by summing up + all of the related individual physical channels. + Values include the instantaneous, average, minimum, and + maximum statistics. If avg/min/max statistics are not + supported, the target is expected to just supply the + instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container laser-bias-current { + description + "The current applied by the system to the transmit laser to + achieve the output power. The current is expressed in mA + with up to two decimal precision. Values include the + instantaneous, average, minimum, and maximum statistics. + If avg/min/max statistics are not supported, the target is + expected to just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-mA; + } + } + + grouping output-optical-frequency { + description + "Reusable leaves related to optical output power -- this is + typically configurable on line side and read-only on the + client-side"; + + leaf output-frequency { + type oc-opt-types:frequency-type; + description + "The frequency in MHz of the individual physical channel + (e.g. ITU C50 - 195.0THz and would be reported as + 195,000,000 MHz in this model). This attribute is not + configurable on most client ports."; + } + } + + + grouping physical-channel-config { + description + "Configuration data for physical client channels"; + + leaf index { + type uint16 { + range 0..max; + } + description + "Index of the physical channnel or lane within a physical + client port"; + } + + leaf associated-optical-channel { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "A physical channel may reference an optical channel + component. If the physical channel does make this optional + reference, then a limited set of leaves will apply within + the physical channel to avoid duplication within the optical + channel."; + } + + leaf description { + type string; + description + "Text description for the client physical channel"; + } + + leaf tx-laser { + type boolean; + description + "Enable (true) or disable (false) the transmit label for the + channel"; + } + + uses physical-channel-config-extended { + when "../../../config/module-functional-type = 'oc-opt-types:TYPE_STANDARD_OPTIC'" { + description + "When the physical channel is of TYPE_STANDARD_OPTIC, the + extended config will be used"; + } + } + } + + grouping physical-channel-config-extended { + description + "Extended configuration data for physical client channels + for applications where the full physical channel config and + state are used. In some cases, such as when the physical + channel has a leafref to an optical channel component and the + module-functional-type is TYPE_DIGITAL_COHERENT_OPTIC this + grouping will NOT be used."; + + leaf target-output-power { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "Target output optical power level of the optical channel, + expressed in increments of 0.01 dBm (decibel-milliwats)"; + } + } + + grouping physical-channel-state { + description + "Operational state data for client channels. In some cases, + such as when the physical channel has a leafref to an optical + channel component and the module-functional-type is + TYPE_DIGITAL_COHERENT_OPTIC this grouping will NOT be used."; + + leaf laser-age { + type oc-types:percentage; + description + "Laser age (0% at beginning of life, 100% end of life) in integer + percentage. This term is defined by Common Management Interface + Specification (CMIS)."; + + reference "QSFP-DD CMIS 5.0 Table 8-122"; + } + + container laser-temperature { + description + "Laser temperature for the cooled laser in degrees Celsius with 1 + decimal precision. This term is defined by Common Management + Interface Specification (CMIS). Values include the instantaneous, + average, minimum, and maximum statistics. If avg/min/max statistics + are not supported, the target is expected to just supply the + instant value."; + + reference "QSFP-DD CMIS 5.0 Table 8-122"; + + uses oc-platform-types:avg-min-max-instant-stats-precision1-celsius; + } + + container target-frequency-deviation { + description + "The difference in MHz with 1 decimal precision between the target + center frequency and the actual current center frequency . This term + is defined by Common Management Interface Specification (CMIS) and + referred to as laser frequency error or laser ferquency deviation. + Values include the instantaneous, average, minimum, and maximum + statistics. If avg/min/max statistics are not supported, the target + is expected to just supply the instant value."; + + reference "QSFP-DD CMIS 5.0 Section Table 8-122"; + + uses oc-opt-types:avg-min-max-instant-stats-precision1-mhz; + } + + container tec-current { + description + "The amount of current flowing to the TC of a cooled laser in percentage + with 2 decimal precision. This term is defined by Common Management + Interface Specification (CMIS). Values include the instantaneous, + average, minimum, and maximum statistics. If avg/min/max statistics + are not supported, the target is expected to just supply the instant + value."; + + reference "QSFP-DD CMIS 5.0 Table 8-122"; + + uses oc-opt-types:avg-min-max-instant-stats-precision2-pct; + } + + uses physical-channel-state-extended { + when "../../../state/module-functional-type = 'oc-opt-types:TYPE_STANDARD_OPTIC'" { + description + "When the physical channel is of TYPE_STANDARD_OPTIC, the + extended state will be used"; + } + } + } + + grouping physical-channel-state-extended { + description + "Extended operational state data for physical client channels + for applications where the full physical channel config and + state are used. In some cases, such as when the physical + channel has a leafref to an optical channel component and the + module-functional-type is TYPE_DIGITAL_COHERENT_OPTIC this + grouping will NOT be used."; + + uses output-optical-frequency; + uses optical-power-state; + } + + grouping physical-channel-top { + description + "Top-level grouping for physical client channels"; + + container physical-channels { + description + "Enclosing container for client channels"; + + list channel { + key "index"; + description + "List of client channels, keyed by index within a physical + client port. A physical port with a single channel would + have a single zero-indexed element"; + + leaf index { + type leafref { + path "../config/index"; + } + description + "Reference to the index number of the channel"; + } + + container config { + description + "Configuration data for physical channels"; + + uses physical-channel-config; + } + + container state { + + config false; + + description + "Operational state data for channels"; + + uses physical-channel-config; + uses physical-channel-state; + } + } + } + } + + + grouping port-transceiver-config { + description + "Configuration data for client port transceivers"; + + leaf enabled { + type boolean; + description + "Turns power on / off to the transceiver -- provides a means + to power on/off the transceiver (in the case of SFP, SFP+, + QSFP,...) or enable high-power mode (in the case of CFP, + CFP2, CFP4) and is optionally supported (device can choose to + always enable). True = power on / high power, False = + powered off"; + } + + leaf form-factor-preconf { + type identityref { + base oc-opt-types:TRANSCEIVER_FORM_FACTOR_TYPE; + } + description + "Indicates the type of optical transceiver used on this + port. If the client port is built into the device and not + pluggable, then non-pluggable is the corresponding state. If + a device port supports multiple form factors (e.g. QSFP28 + and QSFP+, then the value of the transceiver installed shall + be reported. If no transceiver is present, then the value of + the highest rate form factor shall be reported + (QSFP28, for example). + + The form factor is included in configuration data to allow + pre-configuring a device with the expected type of + transceiver ahead of deployment. The corresponding state + leaf should reflect the actual transceiver type plugged into + the system."; + } + + leaf ethernet-pmd-preconf { + type identityref { + base oc-opt-types:ETHERNET_PMD_TYPE; + } + description + "The Ethernet PMD is a property of the optical transceiver + used on the port, indicating the type of physical connection. + It is included in configuration data to allow pre-configuring + a port/transceiver with the expected PMD. The actual PMD is + indicated by the ethernet-pmd state leaf."; + } + + leaf fec-mode { + type identityref { + base oc-platform-types:FEC_MODE_TYPE; + } + description + "The FEC mode indicates the mode of operation for the + transceiver's FEC. This defines typical operational modes + and does not aim to specify more granular FEC capabilities."; + } + + leaf module-functional-type { + type identityref { + base oc-opt-types:TRANSCEIVER_MODULE_FUNCTIONAL_TYPE; + } + description + "Indicates the module functional type which represents the + functional capability of the transceiver. For example, this + would specify the module is a digital coherent optic or a + standard grey optic that performs on-off keying."; + } + } + + grouping port-transceiver-state { + description + "Operational state data for client port transceivers"; + + leaf present { + type enumeration { + enum PRESENT { + description + "Transceiver is present on the port"; + } + enum NOT_PRESENT { + description + "Transceiver is not present on the port"; + } + } + description + "Indicates whether a transceiver is present in + the specified client port."; + } + + leaf form-factor { + type identityref { + base oc-opt-types:TRANSCEIVER_FORM_FACTOR_TYPE; + } + description + "Indicates the type of optical transceiver used on this + port. If the client port is built into the device and not + pluggable, then non-pluggable is the corresponding state. If + a device port supports multiple form factors (e.g. QSFP28 + and QSFP+, then the value of the transceiver installed shall + be reported. If no transceiver is present, then the value of + the highest rate form factor shall be reported + (QSFP28, for example)."; + } + + leaf connector-type { + type identityref { + base oc-opt-types:FIBER_CONNECTOR_TYPE; + } + description + "Connector type used on this port"; + } + + leaf vendor { + type string { + length 1..16; + } + description + "Full name of transceiver vendor. 16-octet field that + contains ASCII characters, left-aligned and padded on the + right with ASCII spaces (20h)"; + } + + leaf vendor-part { + type string { + length 1..16; + } + description + "Transceiver vendor's part number. 16-octet field that + contains ASCII characters, left-aligned and padded on the + right with ASCII spaces (20h). If part number is undefined, + all 16 octets = 0h"; + } + + leaf vendor-rev { + type string { + length 1..2; + } + description + "Transceiver vendor's revision number. 2-octet field that + contains ASCII characters, left-aligned and padded on the + right with ASCII spaces (20h)"; + } + + //TODO: these compliance code leaves should be active based on + //the type of port + leaf ethernet-pmd { + type identityref { + base oc-opt-types:ETHERNET_PMD_TYPE; + } + description + "Ethernet PMD (physical medium dependent sublayer) that the + transceiver supports. The SFF/QSFP MSAs have registers for + this and CFP MSA has similar."; + } + + leaf sonet-sdh-compliance-code { + type identityref { + base oc-opt-types:SONET_APPLICATION_CODE; + } + description + "SONET/SDH application code supported by the port"; + } + + leaf otn-compliance-code { + type identityref { + base oc-opt-types:OTN_APPLICATION_CODE; + } + description + "OTN application code supported by the port"; + } + + leaf serial-no { + type string { + length 1..16; + } + description + "Transceiver serial number. 16-octet field that contains + ASCII characters, left-aligned and padded on the right with + ASCII spaces (20h). If part serial number is undefined, all + 16 octets = 0h"; + } + + leaf date-code { + type oc-yang:date-and-time; + description + "Representation of the transceiver date code, typically + stored as YYMMDD. The time portion of the value is + undefined and not intended to be read."; + } + + leaf fault-condition { + type boolean; + description + "Indicates if a fault condition exists in the transceiver"; + } + + leaf fec-status { + type identityref { + base oc-platform-types:FEC_STATUS_TYPE; + } + description + "Operational status of FEC"; + } + + leaf fec-uncorrectable-blocks { + type yang:counter64; + description + "The number of blocks that were uncorrectable by the FEC"; + } + + leaf fec-uncorrectable-words { + type yang:counter64; + description + "The number of words that were uncorrectable by the FEC"; + } + + leaf fec-corrected-bytes { + type yang:counter64; + description + "The number of bytes that were corrected by the FEC"; + } + + leaf fec-corrected-bits { + type yang:counter64; + description + "The number of bits that were corrected by the FEC"; + } + + container pre-fec-ber { + description + "Bit error rate before forward error correction -- computed + value with 18 decimal precision. Note that decimal64 + supports values as small as i x 10^-18 where i is an + integer. Values smaller than this should be reported as 0 + to inidicate error free or near error free performance. + Values include the instantaneous, average, minimum, and + maximum statistics. If avg/min/max statistics are not + supported, the target is expected to just supply the + instant value"; + + uses oc-opt-types:avg-min-max-instant-stats-precision18-ber; + } + + container post-fec-ber { + description + "Bit error rate after forward error correction -- computed + value with 18 decimal precision. Note that decimal64 + supports values as small as i x 10^-18 where i is an + integer. Values smaller than this should be reported as 0 + to inidicate error free or near error free performance. + Values include the instantaneous, average, minimum, and + maximum statistics. If avg/min/max statistics are not + supported, the target is expected to just supply the + instant value"; + + uses oc-opt-types:avg-min-max-instant-stats-precision18-ber; + } + + container supply-voltage { + description + "Supply voltage to the transceiver in volts with 2 decimal + precision. Values include the instantaneous, average, minimum, + and maximum statistics. If avg/min/max statistics are not + supported, the target is expected to just supply the instant + value."; + + uses oc-platform-types:avg-min-max-instant-stats-precision2-volts; + } + + uses optical-power-state; + } + + grouping port-transceiver-top { + description + "Top-level grouping for client port transceiver data"; + + container transceiver { + description + "Top-level container for client port transceiver data"; + + container config { + description + "Configuration data for client port transceivers"; + + uses port-transceiver-config; + } + + container state { + + config false; + + description + "Operational state data for client port transceivers"; + + uses port-transceiver-config; + uses port-transceiver-state; + } + // physical channels are associated with a transceiver + // component + uses physical-channel-top; + } + } + + // data definition statements + + // augment statements + + augment "/oc-platform:components/oc-platform:component" { + description + "Adding transceiver data to physical inventory. This subtree is + only valid when the type of the component is TRANSCEIVER."; + + uses port-transceiver-top; + } + + augment "/oc-if:interfaces/oc-if:interface/oc-if:state" { + description + "Adds a reference from an interface to the corresponding + transceiver component."; + + leaf transceiver { + type leafref { + path "/oc-platform:components/" + + "oc-platform:component[oc-platform:name=current()/../oc-port:hardware-port]/" + + "oc-platform:subcomponents/oc-platform:subcomponent/" + + "oc-platform:name"; + } + description + "Provides a reference to the transceiver subcomponent that + corresponds to the physical port component for this interface. + The device must only populate this leaf with a reference to + a component of type TRANSCEIVER."; + } + } + + augment "/oc-if:interfaces/oc-if:interface/oc-if:state" { + description + "Adds a reference from the base interface to its corresponding + physical channels."; + + leaf-list physical-channel { + type leafref { + path "/oc-platform:components/" + + "oc-platform:component[oc-platform:name=current()/../oc-transceiver:transceiver]/" + + "oc-transceiver:transceiver/" + + "oc-transceiver:physical-channels/oc-transceiver:channel/" + + "oc-transceiver:index"; + } + description + "For a channelized interface, list of references to the + physical channels (lanes) corresponding to the interface. + The physical channels are elements of a transceiver component + in the platform model."; + } + } + + // rpc statements + + // notification statements + +} diff --git a/models/yang/openconfig-telemetry.yang b/models/yang/openconfig-telemetry.yang new file mode 100644 index 000000000..54ebb989f --- /dev/null +++ b/models/yang/openconfig-telemetry.yang @@ -0,0 +1,782 @@ +module openconfig-telemetry { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/telemetry"; + + prefix "oc-telemetry"; + + // import some basic types + import openconfig-inet-types { prefix oc-inet; } + import openconfig-extensions { prefix oc-ext; } + import openconfig-telemetry-types { prefix oc-telemetry-types; } + + // meta + organization "OpenConfig working group"; + + contact + "OpenConfig working group www.openconfig.net"; + + description + "Data model which creates the configuration for the telemetry + systems and functions on the device."; + + oc-ext:openconfig-version "0.5.1"; + + revision "2018-11-21" { + description + "Add OpenConfig module metadata extensions."; + reference "0.5.1"; + } + + revision "2018-08-17" { + description + "Update telemetry model to comply with the OpenConfig + style for lists and their containers. Remove subscription + exclusions."; + reference "0.5.0"; + } + + revision "2017-08-24" { + description + "Minor formatting fixes"; + reference "0.4.1"; + } + + revision "2017-02-20" { + description + "Fixes for YANG 1.0 compliance, add types module"; + reference "0.4.0"; + } + + revision "2016-04-05" { + description + "OpenConfig public release"; + reference "0.2.0"; + } + + // OpenConfig specific extensions for module metadata. + oc-ext:regexp-posix; + oc-ext:catalog-organization "openconfig"; + oc-ext:origin "openconfig"; + + grouping telemetry-top { + description + "Top level grouping for telemetry configuration and operational + state data"; + + container telemetry-system { + description + "Top level configuration and state for the + device's telemetry system."; + + container sensor-groups { + description + "Top level container for sensor-groups."; + + list sensor-group { + key "sensor-group-id"; + description + "List of telemetry sensory groups on the local + system, where a sensor grouping represents a resuable + grouping of multiple paths and exclude filters."; + + leaf sensor-group-id { + type leafref { + path "../config/sensor-group-id"; + } + description + "Reference to the name or identifier of the + sensor grouping"; + } + + container config { + description + "Configuration parameters relating to the + telemetry sensor grouping"; + uses telemetry-sensor-group-config; + } + + container state { + config false; + description + "State information relating to the telemetry + sensor group"; + uses telemetry-sensor-group-config; + } + + container sensor-paths { + description + "Top level container to hold a set of sensor + paths grouped together"; + + list sensor-path { + key "path"; + description + "List of paths in the model which together + comprise a sensor grouping. Filters for each path + to exclude items are also provided."; + + leaf path { + type leafref { + path "../config/path"; + } + description + "Reference to the path of interest"; + } + + container config { + description + "Configuration parameters to configure a set + of data model paths as a sensor grouping"; + uses telemetry-sensor-path-config; + } + + container state { + config false; + description + "Configuration parameters to configure a set + of data model paths as a sensor grouping"; + uses telemetry-sensor-path-config; + } + } + } + } + } + + container destination-groups { + description + "Top level container for destination group configuration + and state."; + + list destination-group { + key "group-id"; + description + "List of destination-groups. Destination groups allow the + reuse of common telemetry destinations across the + telemetry configuration. An operator references a + set of destinations via the configurable + destination-group-identifier. + + A destination group may contain one or more telemetry + destinations"; + + leaf group-id { + type leafref { + path "../config/group-id"; + } + description + "Unique identifier for the destination group"; + } + + container config { + description + "Top level config container for destination groups"; + leaf group-id { + type string; + description + "Unique identifier for the destination group"; + } + } + + container state { + config false; + description + "Top level state container for destination groups"; + + leaf group-id { + type string; + description + "Unique identifier for destination group"; + } + } + + container destinations { + description + "The destination container lists the destination + information such as IP address and port of the + telemetry messages from the network element."; + list destination { + key "destination-address destination-port"; + description + "List of telemetry stream destinations"; + + leaf destination-address { + type leafref { + path "../config/destination-address"; + } + description + "Reference to the destination address of the + telemetry stream"; + } + + leaf destination-port { + type leafref { + path "../config/destination-port"; + } + description + "Reference to the port number of the stream + destination"; + } + + container config { + description + "Configuration parameters relating to + telemetry destinations"; + uses telemetry-stream-destination-config; + } + + container state { + config false; + description + "State information associated with + telemetry destinations"; + uses telemetry-stream-destination-config; + } + } + } + } + } + + container subscriptions { + description + "This container holds information for both persistent + and dynamic telemetry subscriptions."; + + container persistent-subscriptions { + description + "This container holds information relating to persistent + telemetry subscriptions. A persistent telemetry + subscription is configued locally on the device through + configuration, and is persistent across device restarts or + other redundancy changes."; + + list persistent-subscription { + key "name"; + + description + "List of telemetry subscriptions. A telemetry + subscription consists of a set of collection + destinations, stream attributes, and associated paths to + state information in the model (sensor data)"; + + leaf name { + type leafref { + path "../config/name"; + } + description + "Reference to the identifier of the subscription + itself. The id will be the handle to refer to the + subscription once created"; + } + + container config { + description + "Config parameters relating to the telemetry + subscriptions on the local device"; + + uses telemetry-subscription-name-config; + uses telemetry-local-source-address-config; + uses telemetry-qos-marking-config; + uses telemetry-stream-protocol-config; + uses telemetry-stream-encoding-config; + } + + container state { + config false; + description + "State parameters relating to the telemetry + subscriptions on the local device"; + + uses telemetry-subscription-name-config; + uses telemetry-subscription-config; + uses telemetry-subscription-state; + uses telemetry-local-source-address-config; + uses telemetry-qos-marking-config; + uses telemetry-stream-protocol-config; + uses telemetry-stream-encoding-config; + } + + container sensor-profiles { + description + "A sensor profile is a set of sensor groups or + individual sensor paths which are associated with a + telemetry subscription. This is the source of the + telemetry data for the subscription to send to the + defined collectors."; + list sensor-profile { + key "sensor-group"; + description + "List of telemetry sensor groups used + in the subscription"; + + leaf sensor-group { + type leafref { + path "../config/sensor-group"; + } + description + "Reference to the telemetry sensor group name"; + } + + container config { + description + "Configuration parameters related to the sensor + profile for a subscription"; + uses telemetry-sensor-profile-config; + } + + container state { + config false; + description + "State information relating to the sensor profile + for a subscription"; + uses telemetry-sensor-profile-config; + } + } + } + + container destination-groups { + description + "A subscription may specify destination addresses. + If the subscription supplies destination addresses, + the network element will be the initiator of the + telemetry streaming, sending it to the destination(s) + specified. + + If the destination set is omitted, the subscription + preconfigures certain elements such as paths and + sample intervals under a specified subscription ID. + In this case, the network element will NOT initiate an + outbound connection for telemetry, but will wait for + an inbound connection from a network management + system. + + It is expected that the network management system + connecting to the network element will reference + the preconfigured subscription ID when initiating + a subscription."; + + list destination-group { + key "group-id"; + description + "Identifier of the previously defined destination + group"; + + leaf group-id { + type leafref { + path "../config/group-id"; + } + description + "The destination group id references a configured + group of destinations for the telemetry stream."; + } + + container config { + description + "Configuration parameters related to telemetry + destinations."; + + leaf group-id { + type leafref { + path "../../../../../../../destination-groups" + + "/destination-group/group-id"; + } + description + "The destination group id references a reusable + group of destination addresses and ports for + the telemetry stream."; + } + } + + container state { + config false; + description + "State information related to telemetry + destinations"; + + leaf group-id { + type leafref { + path "../../../../../../../destination-groups" + + "/destination-group/group-id"; + } + description + "The destination group id references a reusable + group of destination addresses and ports for + the telemetry stream."; + } + } + } + } + } + } + + container dynamic-subscriptions { + description + "This container holds information relating to dynamic + telemetry subscriptions. A dynamic subscription is + typically configured through an RPC channel, and does not + persist across device restarts, or if the RPC channel is + reset or otherwise torn down."; + + + list dynamic-subscription { + key "id"; + + config false; + description + "List representation of telemetry subscriptions that + are configured via an inline RPC, otherwise known + as dynamic telemetry subscriptions."; + + leaf id { + type leafref { + path "../state/id"; + } + + description + "Reference to the identifier of the subscription + itself. The id will be the handle to refer to the + subscription once created"; + } + + container state { + config false; + description + "State information relating to dynamic telemetry + subscriptions."; + + uses telemetry-subscription-config; + uses telemetry-stream-destination-config; + uses telemetry-stream-frequency-config; + uses telemetry-heartbeat-config; + uses telemetry-suppress-redundant-config; + uses telemetry-qos-marking-config; + uses telemetry-stream-protocol-config; + uses telemetry-stream-encoding-config; + } + + container sensor-paths { + description + "Top level container to hold a set of sensor + paths grouped together"; + + list sensor-path { + key "path"; + description + "List of paths in the model which together + comprise a sensor grouping. Filters for each path + to exclude items are also provided."; + + leaf path { + type leafref { + path "../state/path"; + } + description + "Reference to the path of interest"; + } + + container state { + config false; + description + "State information for a dynamic subscription's + paths of interest"; + uses telemetry-sensor-path-config; + } + } + } + } + } + } + } + } + + // identity statements + + // typedef statements + + // grouping statements + + grouping telemetry-sensor-path-config { + description + "Configuration parameters relating to the + grouping of data model paths comprising a + sensor grouping"; + leaf path { + type string; + description + "Path to a section of operational state of interest + (the sensor)."; + } + + leaf exclude-filter { + type string; + description + "Filter to exclude certain values out of the state + values"; + //May not be necessary. Could remove. + } + } + + grouping telemetry-heartbeat-config { + description + "Configuration parameters relating to the + heartbeat of the telemetry subscription"; + leaf heartbeat-interval { + type uint64; + description + "Maximum time interval in seconds that may pass + between updates from a device to a telemetry collector. + If this interval expires, but there is no updated data to + send (such as if suppress_updates has been configured), the + device must send a telemetry message to the collector."; + } + } + + grouping telemetry-suppress-redundant-config { + description + "Configuration parameters relating to suppression of + redundant upstream updates"; + leaf suppress-redundant { + type boolean; + description + "Boolean flag to control suppression of redundant + telemetry updates to the collector platform. If this flag is + set to TRUE, then the collector will only send an update at + the configured interval if a subscribed data value has + changed. Otherwise, the device will not send an update to + the collector until expiration of the heartbeat interval."; + } + } + + grouping telemetry-sensor-profile-config { + description + "Configuration parameters relating to the sensor groups + used in the sensor profile"; + leaf sensor-group { + type leafref { + path "../../../../../../../sensor-groups/sensor-group" + + "/config/sensor-group-id"; + } + description + "Reference to the sensor group which is used in the profile"; + } + uses telemetry-stream-subscription-config; + } + + grouping telemetry-stream-subscription-config { + description + "Configuration used when the sensor is a stream based sensor."; + + uses telemetry-stream-frequency-config; + uses telemetry-heartbeat-config; + uses telemetry-suppress-redundant-config; + + } + + grouping telemetry-qos-marking-config { + description + "Config parameters relating to the quality of service + marking on device generated telemetry packets"; + + leaf originated-qos-marking { + type oc-inet:dscp; + description + "DSCP marking of packets generated by the telemetry + subsystem on the network device."; + } + } + + + grouping telemetry-sensor-group-config { + description + "Config parameters related to the sensor groups + on the device"; + leaf sensor-group-id { + type string; + description + "Name or identifier for the sensor group itself. + Will be referenced by other configuration specifying a + sensor group"; + } + } + + grouping telemetry-subscription-config { + description + "Configuration parameters relating to the telemetry + subscription"; + + leaf id { + type uint64; + description + "System generated identifer of the telemetry + subscription."; + } + } + + grouping telemetry-subscription-name-config { + description + "Configuration parameters relating to the configured + name of the telemetry subscription. The name is a user + configured string value which uniquely identifies the + subscription in the configuration database."; + + leaf name { + type string; + description + "User configured identifier of the telemetry + subscription. This value is used primarily for + subscriptions configured locally on the network + element."; + } + } + + grouping telemetry-subscription-state { + description + "State values for the telemetry subscription"; + //TODO add values + } + + grouping telemetry-stream-protocol-config { + description + "Configuration parameters relating to the + transport protocol carrying telemetry + data."; + + leaf protocol { + type identityref { + base oc-telemetry-types:STREAM_PROTOCOL; + } + description + "Selection of the transport protocol for the telemetry + stream."; + } + } + + grouping telemetry-stream-encoding-config { + description + "Configuration parameters relating to the + encoding of telemetry data to and from the + network element. The encoding method controls + specifically the wire format of the telemetry + data, and also controls which RPC framework + may be in use to exchange telemetry data."; + + leaf encoding { + type identityref { + base oc-telemetry-types:DATA_ENCODING_METHOD; + } + description + "Selection of the specific encoding or RPC framework + for telemetry messages to and from the network element."; + } + } + + grouping telemetry-stream-destination-config { + description + "Configuration parameters for the stream destinations"; + leaf destination-address { + type oc-inet:ip-address; + description + "IP address of the telemetry stream destination"; + } + leaf destination-port { + type uint16; + description + "Protocol (udp or tcp) port number for the telemetry + stream destination"; + } + } + + grouping telemetry-stream-frequency-config { + description + "Config parameters for the frequency of updates to + the collector"; + leaf sample-interval { + type uint64; + description + "Time in milliseconds between the device's sample of a + telemetry data source. For example, setting this to 100 + would require the local device to collect the telemetry + data every 100 milliseconds. There can be latency or jitter + in transmitting the data, but the sample must occur at + the specified interval. + + The timestamp must reflect the actual time when the data + was sampled, not simply the previous sample timestamp + + sample-interval. + + If sample-interval is set to 0, the telemetry sensor + becomes event based. The sensor must then emit data upon + every change of the underlying data source."; + } + } + + grouping telemetry-sensor-specification { + description + "Config related to creating telemetry sensor groups. A sensor + group is a related set of sensor paths and/or filters to + exclude items. A group is assigned a reusable identifer, so + it can be used in multiple telemetry subscriptions."; + list telemetry-sensor-group { + key "telemetry-sensor-group-id"; + description + "List of telemetry sensor groups"; + + leaf telemetry-sensor-group-id { + type string; + description + "The sensor group identifer is a reusable handle which + identifies a single sensor group. It is referenced from + the subscription configuration."; + } + uses telemetry-sensor-paths; + } + } + + grouping telemetry-sensor-paths { + description + "This grouping contains these paths to leaves or containers + in the data model which are the sources of telemetry + information."; + + list telemetry-sensor-paths { + key "telemetry-sensor-path"; + description + "A list of sensor paths and exclude filters which comprise + a sensor grouping"; + + leaf telemetry-sensor-path { + type string; + description + "The sensor path is a path to a portion of operational + state of interest in the data model"; + } + } + } + + + grouping telemetry-local-source-address-config { + description + "Config relating to the local source address for telemetry + messages"; + // TODO: Make this a reference to an interface. + leaf local-source-address { + type oc-inet:ip-address; + description + "The IP address which will be the source of packets from + the device to a telemetry collector destination."; + } + } + + // data definition statements + + uses telemetry-top; + + // augment statements + + // rpc statements + + // notification statements + +} diff --git a/models/yang/openconfig-terminal-device.yang b/models/yang/openconfig-terminal-device.yang new file mode 100644 index 000000000..f4b6c44a3 --- /dev/null +++ b/models/yang/openconfig-terminal-device.yang @@ -0,0 +1,1702 @@ +module openconfig-terminal-device { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/terminal-device"; + + prefix "oc-opt-term"; + + import openconfig-types { prefix oc-types; } + import openconfig-transport-types { prefix oc-opt-types; } + import openconfig-if-ethernet { prefix oc-eth; } + import openconfig-interfaces { prefix oc-if; } + import openconfig-platform { prefix oc-platform; } + import openconfig-platform-transceiver { prefix oc-transceiver; } + import openconfig-lldp { prefix oc-lldp; } + import openconfig-extensions { prefix oc-ext; } + import ietf-yang-types { prefix yang; } + import openconfig-yang-types { prefix oc-yang; } + + + // meta + organization "OpenConfig working group"; + + contact + "OpenConfig working group + www.openconfig.net"; + + description + "This module describes a terminal optics device model for + managing the terminal systems (client and line side) in a + DWDM transport network. + + Elements of the model: + + physical port: corresponds to a physical, pluggable client + port on the terminal device. Examples includes 10G, 40G, 100G + (e.g., 10x10G, 4x25G or 1x100G) and 400G/1T in the future. + Physical client ports will have associated operational state or + PMs. + + physical channel: a physical lane or channel in the + physical client port. Each physical client port has 1 or more + channels. An example is 100GBASE-LR4 client physical port having + 4x25G channels. Channels have their own optical PMs and can be + monitored independently within a client physical port (e.g., + channel power). Physical client channels are defined in the + model as part of a physical client port, and are modeled + primarily for reading their PMs. + + logical channel: a logical grouping of logical grooming elements + that may be assigned to subsequent grooming stages for + multiplexing / de-multiplexing, or to an optical channel for + line side transmission. The logical channels can represent, for + example, an ODU/OTU logical packing of the client + data onto the line side. Tributaries are similarly logical + groupings of demand that can be represented in this structure and + assigned to an optical channel. Note that different types of + logical channels may be present, each with their corresponding + PMs. + + optical channel: corresponds to an optical carrier and is + assigned a wavelength/frequency. Optical channels have PMs + such as power, BER, and operational mode. + + Directionality: + + To maintain simplicity in the model, the configuration is + described from client-to-line direction. The assumption is that + equivalent reverse configuration is implicit, resulting in + the same line-to-client configuration. + + Physical layout: + + The model does not assume a particular physical layout of client + and line ports on the terminal device (e.g., such as number of + ports per linecard, separate linecards for client and line ports, + etc.)."; + + oc-ext:openconfig-version "1.9.1"; + + revision "2023-12-13" { + description + "Add reference to the terminal-device-properties-guide.md doc for + operational-mode."; + reference "1.9.1"; + } + + revision "2021-07-29" { + description + "Add several coherent performance monitors to optical channel. + Re-group and add PHY-related performance monitors to optical + channel and logical channel."; + reference "1.9.0"; + } + + revision "2021-02-23" { + description + "Small additions to support ZR transceivers. Adds a new + ingress type of interface and a client mapping mode leaf."; + reference "1.8.0"; + } + + revision "2020-05-09" { + description + "Remove references from read-write contexts to read-only + contexts in when statements."; + reference "1.7.3"; + } + + revision "2019-11-28" { + description + "Additional xpath fixes in when statement"; + reference "1.7.2"; + } + + revision "2019-10-12" { + description + "Fix when statement paths"; + reference "1.7.1"; + } + + revision "2019-08-08" { + description + "Add ALS config to logical-channel/ethernet/config and remove + legacy interfaces augment for this config. Client FEC was + previosuly migrated to the components model and should not + be here anymore."; + reference "1.7.0"; + } + + revision "2019-07-26" { + description + "Add support for LLDP natively on logical-channels."; + reference "1.6.0"; + } + + revision "2018-11-21" { + description + "Add OpenConfig module metadata extensions."; + reference "1.5.1"; + } + + revision "2018-10-23" { + description + "Adds support of logical-channel tributary slot allocation to + logical-channel-assignments with different channel speeds. + Enables logical channel mapping procedure specification."; + reference "1.5.0"; + } + + revision "2018-08-28" { + description + "Adds terminal device related Ethernet counters"; + reference "1.4.0"; + } + + revision "2018-07-30" { + description + "Adds lldp snooping config leaf and augmented it to oc-lldp"; + reference "1.3.0"; + } + + revision "2018-07-26" { + description + "Adds OTN protocol counter stats of errored-blocks and + fec-uncorrectable-blocks, adds ethernet-config-ext grouping + and uses it to augment oc-eth"; + reference "1.2.0"; + } + + revision "2018-07-17" { + description + "Adds testing enum to link-state"; + reference "1.1.0"; + } + + revision "2017-07-08" { + description + "Adds test-signal"; + reference "1.0.0"; + } + + revision "2016-12-22" { + description + "Fixes and additions to terminal optics model"; + reference "0.4.0"; + } + + // OpenConfig specific extensions for module metadata. + oc-ext:regexp-posix; + oc-ext:catalog-organization "openconfig"; + oc-ext:origin "openconfig"; + + grouping terminal-input-optical-power { + description + "Reusable leaves related to input optical power"; + + leaf input-power { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "The input optical power of this port in units of 0.01dBm. + If the port is an aggregate of multiple physical channels, + this attribute is the total power or sum of all channels."; + } + } + + grouping terminal-ethernet-protocol-config { + description + "Configuration data for logical channels with Ethernet + framing"; + + leaf client-als { + type enumeration { + enum NONE { + description + "The client port will do nothing when a failure is + detected on the line port or the remote client port"; + } + enum LASER_SHUTDOWN { + description + "The client port will shut down the laser to notify the + subtending Ethernet equipment of the failure detected on + the line port or the remote client port."; + } + enum ETHERNET { + description + "The client port will propagate the local fault or remote + fault signal to the subtending Ethernet equipment."; + } + } + default ETHERNET; + description + "Sets the client port behavior that defines if the actions + of automatic laser shutdown (als), ethernet fault + propagation, or nothing will be done upon the detection + of a failure on the line port or the upstream remote + client port."; + } + + leaf als-delay { + type uint32; + units milliseconds; + default 0; + description + "The timer to delay the client-als actions on the client + port when a local or remote fault is detected on the line + port. The delay will only be valid when the client-als is + set to LASER_SHUTDOWN"; + } + } + + grouping terminal-ethernet-protocol-state { + description + "Ethernet-specific counters when logical channel + is using Ethernet protocol framing, e.g., 10GE, 100GE"; + + uses oc-eth:ethernet-interface-state-counters; + uses terminal-ethernet-protocol-state-counters; + uses terminal-phy-protocol-stats { + description + "When 400ZR/ZR+ transceivers are plugged in switches or routers, + this grouping will be attached to logical channel with Ethernet + protocol framing, in order to involve host-side fec-related + error performances."; + } + } + + grouping terminal-ethernet-protocol-state-counters { + description + "Ethernet-specific counters for terminal devices when + logical channel is using Ethernet protocol framing, + e.g., 10GE, 100GE"; + + // ingress counters + + leaf in-pcs-bip-errors { + type oc-yang:counter64; + description + "The number of received bit interleaved parity (BIP) errors + at the physical coding sublayer (PCS). If the interface + consists of multiple lanes, this will be the sum of all + errors on the lane"; + } + + leaf in-pcs-errored-seconds { + type oc-yang:counter64; + description + "The number of seconds that physical coding sublayer (PCS) + errors have crossed a sytem defined threshold indicating the + link is erroring"; + } + + leaf in-pcs-severely-errored-seconds { + type oc-yang:counter64; + description + "The number of seconds that physical coding sublayer (PCS) + errors have crossed a system defined threshold indicating the + link is severely erroring"; + } + + leaf in-pcs-unavailable-seconds { + type oc-yang:counter64; + description + "The number of seconds that physical coding sublayer (PCS) + errors have crossed a system defined threshold indicating the + link is unavailable"; + } + + // egress counters + + leaf out-pcs-bip-errors { + type oc-yang:counter64; + description + "The number of transmitted bit interleaved parity (BIP) errors + at the physical coding sublayer (PCS). If the interface + consists of multiple lanes, this will be the sum of all + errors on the lane"; + } + + leaf out-crc-errors { + type oc-yang:counter64; + description + "Number of FCS/CRC error check failures sent on the interface"; + } + + leaf out-block-errors { + type oc-yang:counter64; + description + "The number of transmitted errored blocks. Error detection + codes are capable of detecting whether one or more errors have + occurred in a given sequence of bits – the block. It is + normally not possible to determine the exact number of errored + bits within the block"; + } + } + + grouping terminal-ethernet-protocol-top { + description + "Top-level grouping for data related to Ethernet protocol + framing on logical channels"; + + container ethernet { + description + "Top level container for data related to Ethernet framing + for the logical channel"; + + container config { + description + "Configuration data for Ethernet protocol framing on + logical channels"; + + uses terminal-ethernet-protocol-config; + } + + container state { + config false; + description + "Operational state data for Ethernet protocol framing + on logical channels"; + + uses terminal-ethernet-protocol-config; + uses terminal-ethernet-protocol-state; + } + + uses lldp-logical-channel-top; + } + } + + grouping lldp-logical-channel-top { + description + "Top-level grouping for LLDP data for a logical channel"; + + container lldp { + description + "LLDP data for logical channels"; + + container config { + description + "LLDP configuration data for logical channels"; + + uses lldp-logical-channel-config; + } + + container state { + config false; + description + "LLDP operational state data for logical channels"; + + uses lldp-logical-channel-config; + uses oc-lldp:lldp-interface-state; + } + + uses lldp-logical-channel-neighbor-top; + } + } + + grouping lldp-logical-channel-config { + description + "Configuration data for LLDP for logical-channels"; + + leaf enabled { + type boolean; + default "false"; + description + "Enable or disable the LLDP protocol on the logical channel."; + } + + leaf snooping { + type boolean; + default "false"; + description + "If true, LLDP PDUs are only received and processed on + the logical-channel, but are not originated by the local + agent. The PDUs are not dropped by the logical channel after + processing, but relayed to the downstream link layer + neighbors. The snooping mode is valid only when LLDP is + enabled on the logical channel. The snooping mode is useful + when a logical channel does not want its link layer neighbors + to discover itself since, for example, it is a lower-layer + logical channel."; + } + } + + grouping lldp-logical-channel-neighbor-top { + description + "Top-level grouping for the LLDP neighbor list"; + + container neighbors { + config false; + description + "Enclosing container for list of LLDP neighbors on + a logical channel"; + + list neighbor { + key "id"; + description + "List of LLDP neighbors. If the implementation only + supports one neighbor, this would always be a list with + one item. If the device and neighbor supported multiple + neighbors, which can be achieved via LLDP forwarding, then + this would be supported"; + reference + "IEEE Std 802.1AB-2016, section 7.1, Destination address"; + + leaf id { + type leafref { + path "../state/id"; + } + description + "System generated identifier for the neighbor on + the logical channel."; + } + + container config { + description + "Configuration data "; + + uses lldp-logical-channel-neighbor-config; + } + + container state { + + config false; + + description + "Operational state data "; + + uses oc-lldp:lldp-system-info-config; + uses oc-lldp:lldp-system-info-state; + uses oc-lldp:lldp-neighbor-config; + uses oc-lldp:lldp-neighbor-state; + } + + uses oc-lldp:lldp-custom-tlv-top; + } + } + } + + grouping lldp-logical-channel-neighbor-config { + description + "Configuration data for LLDP neighbors"; + } + + grouping terminal-otn-protocol-config { + description + "OTU configuration when logical channel + framing is using an OTU protocol, e.g., OTU1, OTU3, etc."; + + leaf tti-msg-transmit { + type string; + description + "Trail trace identifier (TTI) message transmitted"; + } + + leaf tti-msg-expected { + type string; + description + "Trail trace identifier (TTI) message expected"; + } + + leaf tti-msg-auto { + type boolean; + description + "Trail trace identifier (TTI) transmit message automatically + created. If true, then setting a custom transmit message + would be invalid."; + } + + leaf tributary-slot-granularity { + type identityref { + base oc-opt-types:TRIBUTARY_SLOT_GRANULARITY; + } + description + "Granularity value of OPUk or OPUCn tributary slots for OTN + signal allocation. The currently defined values follow the + existing ITU-T G.709 standard, which can be extended as + needed in future."; + } + } + + grouping terminal-otn-protocol-counter-stats { + description + "Counter based statistics containers for logical channels + using OTN framing"; + + leaf errored-seconds { + type yang:counter64; + description + "The number of seconds that at least one errored blocks + occurs, at least one code violation occurs, loss of sync is + detected or loss of signal is detected"; + } + + leaf severely-errored-seconds { + type yang:counter64; + description + "The number of seconds that loss of frame is detected OR + the number of errored blocks, code violations, loss of sync + or loss of signal is detected exceeds a predefined + threshold"; + } + + leaf unavailable-seconds { + type yang:counter64; + description + "The number of seconds during which the link is unavailable"; + } + + leaf code-violations { + type yang:counter64; + description + "For ethernet or fiberchannel links, the number of 8b/10b + coding violations. For SONET/SDH, the number of BIP (bit + interleaved parity) errors"; + } + + leaf errored-blocks { + type yang:counter64; + description + "The number of errored blocks. Error detection codes are + capable to detect whether one or more errors have occurred + in a given sequence of bits – the block. It is normally not + possible to determine the exact number of errored bits within + the block."; + reference "ITU-T Rec. G.826"; + } + + leaf fec-uncorrectable-words { + type yang:counter64; + description + "The number of words that were uncorrectable by the FEC"; + } + + leaf fec-corrected-bytes { + type yang:counter64; + description + "The number of bytes that were corrected by the FEC"; + } + + leaf fec-corrected-bits { + type yang:counter64; + description + "The number of bits that were corrected by the FEC"; + } + + leaf background-block-errors { + type yang:counter64; + description + "The number of background block errors"; + } + } + + grouping terminal-phy-protocol-stats { + description + "Counters and multi-value statistics for FEC-related error + performance"; + + leaf fec-uncorrectable-blocks { + type yang:counter64; + description + "The number of blocks or frames that were uncorrectable by + the FEC"; + } + + container pre-fec-ber { + description + "Bit error rate before forward error correction -- computed + value with 18 decimal precision. Note that decimal64 + supports values as small as i x 10^-18 where i is an + integer. Values smaller than this should be reported as 0 + to inidicate error free or near error free performance. + Values include the instantaneous, average, minimum, and + maximum statistics. If avg/min/max statistics are not + supported, the target is expected to just supply the + instant value"; + + uses oc-opt-types:avg-min-max-instant-stats-precision18-ber; + } + + container post-fec-ber { + description + "Bit error rate after forward error correction -- computed + value with 18 decimal precision. Note that decimal64 + supports values as small as i x 10^-18 where i is an + integer. Values smaller than this should be reported as 0 + to inidicate error free or near error free performance. + Values include the instantaneous, average, minimum, and + maximum statistics. If avg/min/max statistics are not + supported, the target is expected to just supply the + instant value"; + + uses oc-opt-types:avg-min-max-instant-stats-precision18-ber; + } + + container q-value { + description + "Quality value (factor) in dB of a channel with two + decimal precision. Values include the instantaneous, + average, minimum, and maximum statistics. If avg/min/max + statistics are not supported, the target is expected + to just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dB; + } + + container esnr { + description + "Electrical signal to noise ratio. Baud rate + normalized signal to noise ratio based on + error vector magnitude in dB with two decimal + precision. Values include the instantaneous, average, + minimum, and maximum statistics. If avg/min/max + statistics are not supported, the target is expected + to just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dB; + } + } + + grouping terminal-otn-protocol-state { + description + "OTU operational state when logical channel + framing is using an OTU protocol, e.g., OTU1, OTU3, etc."; + + + leaf tti-msg-recv { + type string; + description + "Trail trace identifier (TTI) message received"; + } + + leaf rdi-msg { + type string; + description + "Remote defect indication (RDI) message received"; + } + uses terminal-otn-protocol-counter-stats; + uses terminal-phy-protocol-stats { + description + "This grouping may be used when the logical-channel-type + is 'PROT_OTN."; + } + } + + grouping terminal-otn-protocol-top { + description + "Top-level grouping for data related to OTN protocol framing"; + + container otn { + description + "Top level container for OTU configuration when logical + channel framing is using an OTU protocol, e.g., OTU1, OTU3, + etc."; + + container config { + description + "Configuration data for OTN protocol framing"; + + uses terminal-otn-protocol-config; + } + + container state { + + config false; + + description + "Operational state data for OTN protocol PMs, statistics, + etc."; + + uses terminal-otn-protocol-config; + uses terminal-otn-protocol-state; + } + } + } + + grouping terminal-client-port-assignment-config { + description + "Configuration data for assigning physical client ports to + logical channels"; + + leaf index { + type uint32; + description + "Index of the client port assignment"; + } + + leaf description { + type string; + description + "Descriptive name for the client port-to-logical channel + mapping"; + } + + leaf logical-channel { + type leafref { + path "/oc-opt-term:terminal-device/oc-opt-term:logical-channels" + + "/oc-opt-term:channel/oc-opt-term:index"; + } + description + "Reference to the logical channel for this + assignment"; + } + + leaf allocation { + type decimal64 { + fraction-digits 3; + } + units Gbps; + description + "Allocation of the client physical port to the assigned + logical channel expressed in Gbps. In most cases, + the full client physical port rate is assigned to a single + logical channel."; + } + + } + + grouping terminal-client-port-assignment-state { + description + "Operational state data for assigning physical client ports + to logical channels"; + } + + grouping terminal-client-port-assignment-top { + description + "Top-level grouping for the assigment of client physical ports + to logical channels"; + //TODO: this grouping could be removed, instead reusing a common + //grouping for logical client assignment pointers + + container logical-channel-assignments { + description + "Enclosing container for client port to logical client + mappings"; + + list assignment { + key "index"; + description + "List of assignments to logical clients"; + + leaf index { + type leafref { + path "../config/index"; + } + description + "Reference to the index of this logical client + assignment"; + } + + container config { + description + "Configuration data for the logical client assignment"; + + uses terminal-client-port-assignment-config; + } + + container state { + + config false; + + description + "Operational state data for the logical client + assignment"; + + uses terminal-client-port-assignment-config; + uses terminal-client-port-assignment-state; + } + } + } + } + + + grouping terminal-logical-chan-assignment-config { + description + "Configuration data for assigning client logical channels + to line-side tributaries"; + + leaf index { + type uint32; + description + "Index of the current logical client channel to tributary + mapping"; + } + + leaf description { + type string; + description + "Name assigned to the logical client channel"; + } + + leaf assignment-type { + type enumeration { + enum LOGICAL_CHANNEL { + description + "Subsequent channel is a logical channel"; + } + enum OPTICAL_CHANNEL { + description + "Subsequent channel is a optical channel / carrier"; + } + } + description + "Each logical channel element may be assigned to subsequent + stages of logical elements to implement further grooming, or + can be assigned to a line-side optical channel for + transmission. Each assignment also has an associated + bandwidth allocation."; + } + + leaf logical-channel { + type leafref { + path "/oc-opt-term:terminal-device/" + + "oc-opt-term:logical-channels/oc-opt-term:channel/" + + "oc-opt-term:index"; + } + must "../assignment-type = 'LOGICAL_CHANNEL'" { + description + "The assignment-type must be set to LOGICAL_CHANNEL for + this leaf to be valid"; + } + description + "Reference to another stage of logical channel elements."; + } + + leaf optical-channel { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + must "../assignment-type = 'OPTICAL_CHANNEL'" { + description + "The assignment-type must be set to OPTICAL_CHANNEL for + this leaf to be valid"; + } + description + "Reference to the line-side optical channel that should + carry the current logical channel element. Use this + reference to exit the logical element stage."; + } + + leaf allocation { + type decimal64 { + fraction-digits 3; + } + units Gbps; + description + "Allocation of the logical client channel to the tributary + or sub-channel, expressed in Gbps. Please note that if the + assignment is to an OTN logical channel, the allocation must + be an integer multiplication to tributary-slot-granularity + of the OTN logical channel."; + } + + leaf tributary-slot-index { + type int32; + description + "Indicates the first tributary slot index allocated to the + client signal or logical channel in the assignment. Valid + only when the assignment is to an OTN logical channel."; + } + + leaf mapping { + type identityref { + base oc-opt-types:FRAME_MAPPING_PROTOCOL; + } + description + "Logical channel mapping procedure. Valid only when the + assignment is to an OTN logical channel."; + } + } + + grouping terminal-logical-chan-assignment-state { + description + "Operational state data for the assignment of logical client + channel to line-side tributary"; + } + + grouping terminal-logical-chan-assignment-top { + description + "Top-level grouping for the list of logical client channel-to- + tributary assignments"; + + container logical-channel-assignments { + //TODO: we need a commonly understood name for this logical + //channel structure + description + "Enclosing container for tributary assignments"; + + list assignment { + key "index"; + description + "Logical channel elements may be assigned directly to + optical channels for line-side transmission, or can be + further groomed into additional stages of logical channel + elements. The grooming can multiplex (i.e., split the + current element into multiple elements in the subsequent + stage) or de-multiplex (i.e., combine the current element + with other elements into the same element in the subsequent + stage) logical elements in each stage. + + Note that to support the ability to groom the logical + elements, the list of logical channel elements should be + populated with an entry for the logical elements at + each stage, starting with the initial assignment from the + respective client physical port. + + Each logical element assignment consists of a pointer to + an element in the next stage, or to an optical channel, + along with a bandwidth allocation for the corresponding + assignment (e.g., to split or combine signal)."; + + leaf index { + type leafref { + path "../config/index"; + } + description + "Reference to the index for the current tributary + assignment"; + } + + container config { + description + "Configuration data for tributary assignments"; + + uses terminal-logical-chan-assignment-config; + } + + container state { + + config false; + + description + "Operational state data for tributary assignments"; + + uses terminal-logical-chan-assignment-config; + uses terminal-logical-chan-assignment-state; + } + } + } + } + + grouping terminal-logical-channel-ingress-config { + description + "Configuration data for ingress signal to logical channel"; + + leaf transceiver { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "Reference to the transceiver carrying the input signal + for the logical channel. If specific physical channels + are mapped to the logical channel (as opposed to all + physical channels carried by the transceiver), they can be + specified in the list of physical channel references."; + } + + leaf-list physical-channel { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-transceiver:transceiver/" + + "oc-transceiver:physical-channels/" + + "oc-transceiver:channel/oc-transceiver:index"; + } + description + "This list should be populated with references + to the client physical channels that feed this logical + channel from the transceiver specified in the 'transceiver' + leaf, which must be specified. If this leaf-list is empty, + all physical channels in the transceiver are assumed to be + mapped to the logical channel."; + } + + leaf interface { + type oc-if:base-interface-ref; + description + "Reference to the interface carrying the input signal + for the logical channel. The ingress will specify an interface + in the case of a transceiver being utilized directly in a + router and bypassing a dedicated terminal device. When + specified, the other leaves in the ingress config must be + empty."; + } + } + + grouping terminal-logical-channel-ingress-state { + description + "Operational state data for ingress signal to logical channel"; + } + + grouping terminal-logical-channel-ingress-top { + description + "Top-level grouping for ingress signal to logical channel"; + + container ingress { + description + "Top-level container for specifying references to the + source of signal for the logical channel, either a + transceiver, individual physical channels, or an interface"; + + container config { + description + "Configuration data for the signal source for the + logical channel"; + + uses terminal-logical-channel-ingress-config; + } + + container state { + + config false; + + description + "Operational state data for the signal source for the + logical channel"; + + uses terminal-logical-channel-ingress-config; + uses terminal-logical-channel-ingress-state; + } + } + } + + grouping terminal-logical-channel-config { + description + "Configuration data for logical channels"; + + leaf index { + type uint32; + description + "Index of the current logical channel"; + } + + leaf description { + type string; + description + "Description of the logical channel"; + } + + leaf admin-state { + type oc-opt-types:admin-state-type; + description + "Sets the admin state of the logical channel"; + } + + leaf rate-class { + type identityref { + base oc-opt-types:TRIBUTARY_RATE_CLASS_TYPE; + } + description + "Rounded bit rate of the tributary signal. Exact bit rate + will be refined by protocol selection."; + } + + leaf trib-protocol { + type identityref { + base oc-opt-types:TRIBUTARY_PROTOCOL_TYPE; + } + description + "Protocol framing of the tributary signal. If this + LogicalChannel is directly connected to a Client-Port or + Optical-Channel, this is the protocol of the associated port. + If the LogicalChannel is connected to other LogicalChannels, + the TributaryProtocol of the LogicalChannels will define a + specific mapping/demapping or multiplexing/demultiplexing + function. + + Not all protocols are valid, depending on the value + of trib-rate-class. The expectation is that the NMS + will validate that a correct combination of rate class + and protocol are specfied. Basic combinations are: + + rate class: 1G + protocols: 1GE + + rate class: 2.5G + protocols: OC48, STM16 + + rate class: 10G + protocols: 10GE LAN, 10GE WAN, OC192, STM64, OTU2, OTU2e, + OTU1e, ODU2, ODU2e, ODU1e + + rate class: 40G + protocols: 40GE, OC768, STM256, OTU3, ODU3 + + rate class: 100G + protocols: 100GE, 100G MLG, OTU4, OTUCn, ODU4"; + } + + leaf logical-channel-type { + type identityref { + base oc-opt-types:LOGICAL_ELEMENT_PROTOCOL_TYPE; + } + description + "The type / stage of the logical element determines the + configuration and operational state parameters (PMs) + available for the logical element"; + } + + leaf loopback-mode { + type oc-opt-types:loopback-mode-type; + description + "Sets the loopback type on the logical channel. Setting the + mode to something besides NONE activates the loopback in + the specified mode."; + } + + leaf test-signal { + type boolean; + description + "When enabled the logical channel's DSP will generate a pseudo + randmon bit stream (PRBS) which can be used during testing."; + } + + leaf client-mapping-mode { + type identityref { + base oc-opt-types:CLIENT_MAPPING_MODE; + } + description + "The client side mapping mode internal to the device that + specifies the number of client electrical interfaces and + the data rate of each client electrical interface. For + example, a ZR+ transceiver with an optical line rate of 400G + could be configured to break out into four 100G client + signals which might connect to an interface or a + physical-channel. This would be configured on the aggregate + logical channel as MODE_4X100G. This is only valid on the + aggregate logical channel that is connected directly to the + optical-channel."; + } + } + + + grouping terminal-logical-channel-state { + description + "Operational state data for logical client channels"; + + leaf link-state { + type enumeration { + enum UP { + description + "Logical channel is operationally up"; + } + enum DOWN { + description + "Logical channel is operationally down"; + } + enum TESTING { + description + "Logical channel is under test as a result of + enabling test-signal"; + } + } + description + "Link-state of the Ethernet protocol on the logical channel, + SONET / SDH framed signal, etc."; + } + + } + + grouping terminal-logical-channel-top { + description + "Top-level grouping for logical channels"; + + container logical-channels { + description + "Enclosing container the list of logical channels"; + + list channel { + key "index"; + description + "List of logical channels"; + //TODO: naming for this list of logical elements should be + //revisited. + + leaf index { + type leafref { + path "../config/index"; + } + description + "Reference to the index of the logical channel"; + } + + container config { + description + "Configuration data for logical channels"; + + uses terminal-logical-channel-config; + + } + + container state { + + config false; + + description + "Operational state data for logical channels"; + + uses terminal-logical-channel-config; + uses terminal-logical-channel-state; + } + + uses terminal-otn-protocol-top { + when "./config/logical-channel-type = 'PROT_OTN'" { + description + "Include the OTN protocol data only when the + channel is using OTN framing."; + } + } + uses terminal-ethernet-protocol-top { + when "./config/logical-channel-type = 'PROT_ETHERNET'" { + description + "Include the Ethernet protocol statistics only when the + protocol used by the link is Ethernet."; + } + } + uses terminal-logical-channel-ingress-top; + uses terminal-logical-chan-assignment-top; + } + } + } + + + grouping terminal-optical-channel-config { + description + "Configuration data for describing optical channels"; + + leaf frequency { + type oc-opt-types:frequency-type; + description + "Frequency of the optical channel, expressed in MHz"; + } + + leaf target-output-power { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "Target output optical power level of the optical channel, + expressed in increments of 0.01 dBm (decibel-milliwats)"; + } + + leaf operational-mode { + type uint16; + description + "Vendor-specific mode identifier -- sets the operational + mode for the channel. The specified operational mode must + exist in the list of supported operational modes supplied + by the device"; + // + // Ideally, this leaf should be a leafref to the supported + // operational modes, but YANG 1.0 does not allow a r/w + // leaf to be a leafref to a r/o leaf. + reference + "https://github.com/openconfig/public/blob/master/doc/terminal-device-properties-guide.md"; + } + + leaf line-port { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "Reference to the line-side physical port that carries + this optical channel. The target port should be + a component in the physical inventory data model."; + } + } + + grouping terminal-optical-channel-state { + description + "Operational state data for optical channels"; + + leaf group-id { + type uint32; + description + "If the device places constraints on which optical + channels must be managed together (e.g., transmitted on the + same line port), it can indicate that by setting the group-id + to the same value across related optical channels."; + } + + uses oc-transceiver:optical-power-state; + + container chromatic-dispersion { + description + "Chromatic Dispersion of an optical channel in + picoseconds / nanometer (ps/nm) as reported by receiver + with two decimal precision. Values include the instantaneous, + average, minimum, and maximum statistics. If avg/min/max + statistics are not supported, the target is expected to just + supply the instant value"; + + uses oc-opt-types:avg-min-max-instant-stats-precision2-ps-nm; + } + + container polarization-mode-dispersion { + description + "Polarization Mode Dispersion of an optical channel + in picosends (ps) as reported by receiver with two decimal + precision. Values include the instantaneous, average, + minimum, and maximum statistics. If avg/min/max statistics + are not supported, the target is expected to just supply the + instant value"; + + uses oc-opt-types:avg-min-max-instant-stats-precision2-ps; + } + + container second-order-polarization-mode-dispersion { + description + "Second Order Polarization Mode Dispersion of an optical + channel in picoseconds squared (ps^2) as reported by + receiver with two decimal precision. Values include the + instantaneous, average, minimum, and maximum statistics. + If avg/min/max statistics are not supported, the target + is expected to just supply the instant value"; + + uses oc-opt-types:avg-min-max-instant-stats-precision2-ps2; + } + + container polarization-dependent-loss { + description + "Polarization Dependent Loss of an optical channel + in dB as reported by receiver with two decimal precision. + Values include the instantaneous, average, minimum, and + maximum statistics. If avg/min/max statistics are not + supported, the target is expected to just supply the + instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dB; + } + + container modulator-bias-xi { + description + "The bias on in-phase path and Polarization X of + the coherent modulator. This is represented as a percentage + with 2 decimal precision. This term is defined by OIF + Implementation Agreement for Coherent CMIS. Values include + the instantaneous, average, minimum, and maximum statistics. + If avg/min/max statistics are not supported, the target is + expected to just supply the instant value."; + + reference "IA OIF-C-CMIS-01.1 Table 7"; + + uses oc-opt-types:avg-min-max-instant-stats-precision2-pct; + } + + container modulator-bias-xq { + description + "The bias on quadrature path and Polarization X of + the coherent modulator. This is represented as a percentage + with 2 decimal precision. This term is defined by OIF + Implementation Agreement for Coherent CMIS. Values include + the instantaneous, average, minimum, and maximum statistics. + If avg/min/max statistics are not supported, the target is + expected to just supply the instant value."; + + reference "IA OIF-C-CMIS-01.1 Table 7"; + + uses oc-opt-types:avg-min-max-instant-stats-precision2-pct; + } + + container modulator-bias-yi { + description + "The bias on in-phase path and Polarization Y of + the coherent modulator. This is represented as a percentage + with 2 decimal precision. This term is defined by OIF + Implementation Agreement for Coherent CMIS. Values include + the instantaneous, average, minimum, and maximum statistics. + If avg/min/max statistics are not supported, the target is + expected to just supply the instant value."; + + reference "IA OIF-C-CMIS-01.1 Table 7"; + + uses oc-opt-types:avg-min-max-instant-stats-precision2-pct; + } + + container modulator-bias-yq { + description + "The bias on quadrature path and Polarization Y of + the coherent modulator. This is represented as a percentage + with 2 decimal precision. This term is defined by OIF + Implementation Agreement for Coherent CMIS. Values include + the instantaneous, average, minimum, and maximum statistics. + If avg/min/max statistics are not supported, the target is + expected to just supply the instant value."; + + reference "IA OIF-C-CMIS-01.1 Table 7"; + + uses oc-opt-types:avg-min-max-instant-stats-precision2-pct; + } + + container modulator-bias-x-phase { + description + "The X-Phase bias of the coherent modulator. This is + represented as a percentage with 2 decimal precision. This + term is defined by OIF Implementation Agreement for + Coherent CMIS. Values include the instantaneous, average, + minimum, and maximum statistics. If avg/min/max statistics + are not supported, the target is expected to just supply + the instant value."; + + reference "IA OIF-C-CMIS-01.1 Table 7"; + + uses oc-opt-types:avg-min-max-instant-stats-precision2-pct; + } + + container modulator-bias-y-phase { + description + "The Y-Phase bias of the coherent modulator. This is + represented as a percentage with 2 decimal precision. This + term is defined by OIF Implementation Agreement for + Coherent CMIS. Values include the instantaneous, average, + minimum, and maximum statistics. If avg/min/max statistics + are not supported, the target is expected to just supply + the instant value."; + + reference "IA OIF-C-CMIS-01.1 Table 7"; + + uses oc-opt-types:avg-min-max-instant-stats-precision2-pct; + } + + container osnr { + description + "Optical signal to noise ratio at 12.5GHz noise bandwidth + in dB with two decimal precision. Values include the + instantaneous, average, minimum, and maximum statistics. + If avg/min/max statistics are not supported, the target + is expected to just supply the instant value."; + + reference "IA OIF-C-CMIS-01.1 Table 7"; + + uses oc-types:avg-min-max-instant-stats-precision2-dB; + } + + container carrier-frequency-offset { + description + "Carrier frequency offset in MHz with 1 decimal precision. + Values include the instantaneous, average, minimum, and + maximum statistics. If avg/min/max statistics are not supported, + the target is expected to just supply the instant value."; + + reference "IA OIF-C-CMIS-01.1 Table 7"; + + uses oc-opt-types:avg-min-max-instant-stats-precision1-mhz; + } + + container sop-roc { + description + "State-of-polarization rate-of-change (SOP-ROC) in krad/s with 1 + decimal precision. This term is defined by OIF Implementation + Agreement for Coherent CMIS. Values include the instantaneous, + average, minimum, and maximum statistics. If avg/min/max + statistics are not supported, the target is expected to just + supply the instant value."; + + reference "IA OIF-C-CMIS-01.1 Table 7"; + + uses oc-opt-types:avg-min-max-instant-stats-precision1-krads; + } + + container modulation-error-ratio { + description + "Modulation error ratio in dB with two decimal precision. Values + include the instantaneous, average, minimum, and maximum statistics. + If avg/min/max statistics are not supported, the target is + expected to just supply the instant value."; + + reference "IA OIF-C-CMIS-01.1 Table 7"; + + uses oc-types:avg-min-max-instant-stats-precision2-dB; + } + + uses terminal-phy-protocol-stats { + description + "When there is no OTN framing e.g. 400ZR, this grouping will be used."; + } + } + + grouping terminal-optical-channel-top { + description + "Top-level grouping for optical channel data"; + + container optical-channel { + description + "Enclosing container for the list of optical channels"; + + container config { + description + "Configuration data for optical channels"; + + uses terminal-optical-channel-config; + } + + container state { + + config false; + + description + "Operational state data for optical channels"; + + uses terminal-optical-channel-config; + uses terminal-optical-channel-state; + } + } + } + + grouping terminal-operational-mode-config { + description + "Configuration data for vendor-supported operational modes"; + } + + grouping terminal-operational-mode-state { + description + "Operational state data for vendor-supported operational + modes"; + + leaf mode-id { + type uint16; + description + "Two-octet encoding of the vendor-defined operational + mode"; + } + + leaf description { + type string; + description + "Vendor-supplied textual description of the characteristics + of this operational mode to enable operators to select the + appropriate mode for the application."; + } + + //TODO: examples of the kind of info that would be useful to + //report in the operational mode: + //Symbol rate (32G, 40G, 43G, 64G, etc.) + //Modulation (QPSK, 8-QAM, 16-QAM, etc.) + //Differential encoding (on, off/pilot symbol, etc) + //State of polarization tracking mode (default, med. + //high-speed, etc.) + //Pulse shaping (RRC, RC, roll-off factor) + //FEC mode (SD, HD, % OH) + + leaf vendor-id { + type string; + description + "Identifier to represent the vendor / supplier of the + platform and the associated operational mode information"; + } + } + + grouping terminal-operational-mode-top { + description + "Top-level grouping for vendor-supported operational modes"; + + container operational-modes { + description + "Enclosing container for list of operational modes"; + + list mode { + key "mode-id"; + config false; + description + "List of operational modes supported by the platform. + The operational mode provides a platform-defined summary + of information such as symbol rate, modulation, pulse + shaping, etc."; + + leaf mode-id { + type leafref { + path "../state/mode-id"; + } + description + "Reference to mode-id"; + } + + container config { + description + "Configuration data for operational mode"; + + uses terminal-operational-mode-config; + } + + container state { + + config false; + + description + "Operational state data for the platform-defined + operational mode"; + + uses terminal-operational-mode-config; + uses terminal-operational-mode-state; + } + } + } + } + + grouping terminal-device-config { + description + "Configuration data for transport terminal devices at a + device-wide level"; + } + + grouping terminal-device-state { + description + "Operational state data for transport terminal devices at a + device-wide level"; + } + + grouping terminal-device-top { + description + "Top-level grouping for data for terminal devices"; + + container terminal-device { + description + "Top-level container for the terminal device"; + + container config { + description + "Configuration data for global terminal-device"; + + uses terminal-device-config; + } + + container state { + + config false; + + description + "Operational state data for global terminal device"; + + uses terminal-device-config; + uses terminal-device-state; + } + + uses terminal-logical-channel-top; + uses terminal-operational-mode-top; + + } + } + + // data definition statements + + uses terminal-device-top; + + // augment statements + + augment "/oc-platform:components/oc-platform:component" { + description + "Adding optical channel data to physical inventory. This + augmentation is only valid when the type of the component + is OPTICAL_CHANNEL."; + + uses terminal-optical-channel-top; + } +} + diff --git a/models/yang/openconfig-test-xfmr.yang b/models/yang/openconfig-test-xfmr.yang new file mode 100644 index 000000000..30fac6865 --- /dev/null +++ b/models/yang/openconfig-test-xfmr.yang @@ -0,0 +1,678 @@ +module openconfig-test-xfmr { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/test-xmfr"; + + prefix "oc-test-xfmr"; + + import openconfig-extensions { prefix oc-ext; } + + // meta + organization "OpenConfig working group"; + + contact + "OpenConfig working group www.openconfig.net"; + + description + "Data model which creates the configuration to exercise + and test transformer infrastructure that does yang-model + to/from Redis/ABNF schema data-translation."; + + oc-ext:openconfig-version "0.2.0"; + + revision "2023-04-30" { + description + "OpenConfig public release"; + reference "0.2.0"; + } + + // OpenConfig specific extensions for module metadata. + oc-ext:regexp-posix; + oc-ext:catalog-organization "openconfig"; + oc-ext:origin "openconfig"; + + identity TEST_SET_TYPE { + description + "Base identity for types of ACL sets"; + } + + identity TEST_SET_IPV4 { + base TEST_SET_TYPE; + description + "IP-layer test set with IPv4 addresses"; + } + + identity TEST_SET_IPV6 { + base TEST_SET_TYPE; + description + "IP-layer test set with IPv6 addresses"; + } + + grouping test-sensor-group-top { + description + "Top level grouping for test-sensor-group configuration and operational + state data"; + + container test-sensor-groups { + description + "Top level container for test-sensor-groups."; + + list test-sensor-group { + key "id"; + description + "List of test sensory groups on the local + system, where a sensor grouping represents a resuable + grouping of multiple types and exclude filters."; + + leaf id { + type leafref { + path "../config/id"; + } + description + "Reference to the name or identifier of the + test sensor grouping"; + } + + container config { + description + "Configuration parameters relating to the + test sensor grouping"; + uses test-sensor-group-config; + } + + container state { + config false; + description + "State information relating to the test + sensor group"; + uses test-sensor-group-config; + uses test-sensor-group-counters; + } + + container test-sensor-types { + description + "Top level container to hold a set of sensor + types grouped together"; + + list test-sensor-type { + key "type"; + description + "List of types of sensors which together + comprise a test sensor grouping. Filters for each type + to exclude items are also provided."; + + leaf type { + type leafref { + path "../config/type"; + } + description + "Reference to the type of interest"; + } + + container config { + description + "Configuration parameters to configure a set + of sensor types as a sensor grouping"; + uses test-sensor-type-config; + } + + container state { + config false; + description + "Configuration parameters to configure a set + of sensor types as a sensor grouping"; + uses test-sensor-type-config; + } + + container sensor-a-light-sensors { + description + "Top level container to hold a set of sensor + a type light sensors grouped together"; + + list sensor-a-light-sensor { + key "tag"; + description + "List of sensor a type light sensors together + comprise a test sensor a grouping."; + + leaf tag { + type leafref { + path "../config/tag"; + } + description + "Reference to the id of interest"; + } + + container config { + description + "Configuration parameters to configure a set + of ligt sensors as a sensor a grouping"; + uses sensor-a-light-sensor-config; + } + + container state { + config false; + description + "Parameters of a set ligt sensors + as a sensor a grouping"; + uses sensor-a-light-sensor-config; + } + } + } + } + } + uses test-sensor-components-top; + uses test-sensor-zones-top; + } + } + } + // identity statements + + // typedef statements + + // grouping statements + + grouping test-set-top { + description + "Access list entries variables top level container"; + + container test-sets { + description + "Access list entries variables enclosing container"; + + list test-set { + key "name type"; + description + "List of test sets"; + + leaf name { + type leafref { + path "../config/name"; + } + description + "Reference to the name list key"; + } + + leaf type { + type leafref { + path "../config/type"; + } + description + "Reference to the type list key"; + } + + container config { + description + "Test set config"; + uses test-set-config; + } + + container state { + config false; + description + "Test set state information"; + uses test-set-config; + } + } + } + } + + grouping interfaces-top { + description + "Top-level grouping for interface-specific test set data"; + + container interfaces { + description + "Enclosing container for the list of interfaces on which + test set exists"; + + list interface { + key "id"; + description + "List of interfaces on which test set exists"; + + leaf id { + type leafref { + path "../config/id"; + } + description + "Reference to the interface id list key"; + } + + container config { + description + "Configuration for test-set per-interface data"; + + uses interfaces-config; + } + + container state { + + config false; + + description + "Operational state for test-set per-interface data"; + + uses interfaces-config; + } + + uses interface-ingress-test-set-top; + } + } + } + + grouping interface-ingress-test-set-top { + description + "Top-level grouping for per-interface ingress test set data"; + + container ingress-test-sets { + description + "Enclosing container the list of ingress test sets on the interface"; + + list ingress-test-set { + key "set-name type"; + description + "List of ingress test set on the interface"; + + leaf set-name { + type leafref { + path "../config/set-name"; + } + description + "Reference to set name list key"; + } + + leaf type { + type leafref { + path "../config/type"; + } + description + "Reference to type list key"; + } + + container config { + description + "Configuration data "; + + uses interface-ingress-test-set-config; + } + + container state { + + config false; + + description + "Operational state data for interface ingress test sets"; + + uses interface-ingress-test-set-config; + } + + } + } + } + + //////////////////////////// + + grouping test-sensor-group-config { + description + "Config parameters related to the test sensor groups"; + leaf id { + type string; + description + "Name or identifier for the test sensor group itself. + Will be referenced by other configuration specifying a + sensor group"; + } + + leaf-list group-colors { + type string; + description + "Colors thta can be applied to a test sensor group."; + } + + leaf color-hold-time { + type uint32; + units seconds; + default 10; + description + "Number of seconds a color can be held on a test sonsor group."; + } + + } + + grouping test-sensor-group-counters { + description + "Definition of test sensor group counters"; + + container counters { + description + "Test sensor group counters"; + + leaf frame-in { + type uint32; + description + "The number frames received."; + } + + leaf frame-out { + type uint32; + description + "The number of frames transmitted out."; + } + } + } + + grouping test-sensor-type-config { + description + "Configuration parameters relating to the + grouping of sensor types comprising a + sensor grouping"; + leaf type { + type string { + pattern "sensora_[a-zA-Z0-9]*|sensorb_[a-zA-Z0-9]*"; + } + description + "Sensor type name"; + } + + leaf exclude-filter { + type string; + description + "Filter to exclude certain values out of the state values"; + } + } + + grouping sensor-a-light-sensor-config { + description + "Configuration parameters relating to the + grouping of sensor a light sensors"; + leaf tag { + type string { + pattern "lightsensor_[0-9]*"; + } + description + "light sensor tag-id"; + } + + leaf light-intensity-measure { + type uint32; + default 5; + description + "Light intenity needed for sensing"; + } + } + + grouping test-set-config { + description + "Test set config"; + + leaf name { + type string; + description + "The name of the test set"; + } + + leaf type { + type identityref { + base TEST_SET_TYPE; + } + description + "The type determines the type test set"; + } + + leaf description { + type string; + description + "Description, or comment, for the test set"; + } + + } + + /////////////////// + grouping test-sensor-component-config { + description + "Configuration data for sensor-components"; + + leaf name { + type string; + description + "Device name for the sensor component. "; + } + leaf type { + type enumeration { + enum TYPE1 { + description + "Component Type 1."; + } + enum TYPE2 { + description + "Component Type 2."; + } + enum TYPE3 { + description + "Component Type 3."; + } + } + } + leaf version { + type string; + description + "Version of the Component. "; + } + leaf description { + type string; + description + "Description, or comment, for the test sensor component"; + } + } + + grouping test-sensor-component-state { + description + "Operational State data for sensor components"; + leaf mfg-name { + type string; + description + "System-supplied identifier for the manufacturer of the component."; + } + + leaf mfg-date { + type string; + description + "System-supplied representation of the component's + manufacturing date."; + } + + leaf hardware-version { + type string; + description + "For hardware components, this is the hardware revision of + the component."; + } + + leaf firmware-version { + type string; + description + "For hardware components, this is the version of associated + firmware that is running on the component, if applicable."; + } + } + + grouping test-sensor-components-top { + container test-sensor-components { + description + "Enclosing container for test sensor component references"; + + list test-sensor-component { + key "name type version"; + description + "List of sensor component references"; + + leaf name { + type leafref { + path "../config/name"; + } + description + "Reference to the name of component"; + } + + leaf type { + type leafref { + path "../config/type"; + } + description + "Reference to the type of component"; + } + + leaf version { + type leafref { + path "../config/version"; + } + description + "Reference to the version of component"; + } + + container config { + description + "Configuration parameters to configure a sensor component"; + uses test-sensor-component-config; + } + + container state { + config false; + description + "Operational state parameters of a sensor component"; + uses test-sensor-component-config; + uses test-sensor-component-state; + } + } + } + } + + grouping test-sensor-zones-top { + container test-sensor-zones { + description + "Top level container to hold a set of sensor + zones grouped together"; + + list test-sensor-zone { + key "zone"; + description + "List of zones of sensors which together + comprise a test sensor grouping."; + + leaf zone { + type leafref { + path "../config/zone"; + } + description + "Reference to the sensor zone"; + } + + container config { + description + "Configuration parameters to configure zone of a sensor grouping"; + leaf zone { + type string; + description + "Reference to the sensor zone"; + } + leaf description { + type string; + description + "global sensor description"; + } + } + + container state { + config false; + description + "State data of the configured zones of a sensor grouping"; + leaf zone { + type string; + description + "Reference to the sensor zone"; + } + } + } + } + } + + + + grouping interfaces-config { + description + "Configuration data for interface references"; + + leaf id { + type string { + pattern "Eth_" + ".*"; + } + description + "identifier for the interface"; + } + } + + grouping interface-ingress-test-set-config { + description + "Configuration data for per-interface ingress test-set"; + + leaf set-name { + type leafref { + path "../../../../../../test-sets/test-set/config/name"; + } + description + "Reference to the test set name applied on ingress"; + } + + leaf type { + type leafref { + path "../../../../../../test-sets/test-set[name=current()/../set-name]" + + "/config/type"; + } + description + "Reference to the test set type applied on ingress"; + } + + } + + grouping test-global-sensor-config { + container global-sensor { + description + "Configuration data for global sensor."; + + leaf mode { + type string; + description + "global sensor mode"; + } + + leaf description { + type string; + description + "global sensor description"; + } + } + } + /////////////////// + + // data definition statements + + container test-xfmr { + description + "Top level configuration and state for the test-xfmr system."; + + uses test-sensor-group-top; + uses test-set-top; + uses interfaces-top; + uses test-global-sensor-config; + } + // augment statements + + // rpc statements + + // notification statements + +} + diff --git a/models/yang/openconfig-transport-line-common.yang b/models/yang/openconfig-transport-line-common.yang new file mode 100644 index 000000000..fd8d1fa5d --- /dev/null +++ b/models/yang/openconfig-transport-line-common.yang @@ -0,0 +1,302 @@ +module openconfig-transport-line-common { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/transport-line-common"; + + prefix "oc-line-com"; + + // import some basic types + import iana-if-type { prefix ianaift; } + import openconfig-extensions { prefix oc-ext; } + import openconfig-interfaces { prefix oc-if; } + import openconfig-platform { prefix oc-platform; } + import openconfig-types { prefix oc-types; } + import openconfig-transport-types { prefix oc-opt-types; } + import openconfig-platform-transceiver { prefix oc-transceiver; } + + + // meta + organization "OpenConfig working group"; + + contact + "OpenConfig working group + www.openconfig.net"; + + description + "This module defines common data elements for OpenConfig data + models for optical transport line system elements, such as + amplifiers and ROADMs (wavelength routers)."; + + oc-ext:openconfig-version "0.6.0"; + + revision "2019-06-03" { + description + "Add state leaf 'tilt' to optical-port"; + reference "0.6.0"; + } + + revision "2019-04-16" { + description + "Update import prefix for iana-if-type module"; + reference "0.5.2"; + } + + revision "2018-11-21" { + description + "Add OpenConfig module metadata extensions."; + reference "0.4.2"; + } + + revision "2018-07-17" { + description + "Remove leaf 'enabled' from osc-config"; + reference "0.4.1"; + } + + revision "2018-05-08" { + description + "Added leaf 'enabled' to osc-config and + leaf 'output-frequency' to osc-state"; + reference "0.4.0"; + } + + revision "2017-09-08" { + description + "Correct bug with OSC interfaces"; + reference "0.3.1"; + } + + revision "2017-07-08" { + description + "Add monitor port type and refs to hw ports, "; + reference "0.3.0"; + } + + revision "2017-03-28" { + description + "Added min/max/avg stats, status for media channels, OCM, APS"; + reference "0.2.0"; + } + + revision "2016-03-31" { + description + "Initial public release"; + reference "0.1.0"; + } + + // OpenConfig specific extensions for module metadata. + oc-ext:regexp-posix; + oc-ext:catalog-organization "openconfig"; + oc-ext:origin "openconfig"; + + // extension statements + + // feature statements + + // identity statements + + // typedef statements + + // grouping statements + + grouping optical-osc-config { + description + "Configuration data for OSC interfaces"; + + leaf interface { + type oc-if:base-interface-ref; + description + "Reference to an OSC interface"; + } + } + + grouping optical-osc-state { + description + "Operational state data for OSC interfaces"; + + container input-power { + description + "The input optical power of this port in units + of 0.01dBm. If avg/min/max statistics are not supported, + the target is expected to just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container output-power { + description + "The output optical power of this port in units + of 0.01dBm. If avg/min/max statistics are not supported, + the target is expected to just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container laser-bias-current { + description + "The current applied by the system to the transmit laser to + achieve the output power. The current is expressed in mA + with up to one decimal precision. If avg/min/max statistics + are not supported, the target is expected to just supply + the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-mA; + } + + uses oc-transceiver:output-optical-frequency; + } + + + + grouping optical-osc-top { + description + "Top-level grouping for configuration and operational state + data for optical supervisory channels (OSC) for amplifiers, + WSS/ROADM, nodes, etc."; + + container config { + description + "Configuration data for OSCs"; + + uses optical-osc-config; + } + + container state { + + config false; + + description + "Operational state data for OSCs"; + + uses optical-osc-config; + uses optical-osc-state; + } + } + + + grouping transport-line-common-port-config { + description + "Configuration data for optical line ports"; + + leaf admin-state { + type oc-opt-types:admin-state-type; + description + "Sets the admin state of the optical-port"; + } + } + + grouping transport-line-common-port-state { + description + "Operational state data describing optical line ports"; + + leaf optical-port-type { + type identityref { + base oc-opt-types:OPTICAL_PORT_TYPE; + } + description + "For physical ports belonging to optical transport + devices, this indicates the type of optical port. This is an + informational field that should be made available by the + device."; + } + + leaf tilt { + type decimal64 { + fraction-digits 2; + } + units dB; + description + "The total tilt measured on the port. This is applicable to + ports of type INGRESS and EGRESS."; + } + + container input-power { + description + "For line system device ports, this value indicates + the total input optical power of the port in units + of 0.01dBm. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + + container output-power { + description + "For line system device ports, this value indicates + the total output optical power of the port in units + of 0.01dBm. If avg/min/max statistics are not supported, + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + } + + grouping transport-line-common-port-top { + description + "Top-level grouping for optical port data"; + + container optical-port { + description + "Contains data specific to ports on optical transport + devices."; + + container config { + + description + "Operational config data for optical ports"; + + uses transport-line-common-port-config; + } + + container state { + + config false; + + description + "Operational state data for optical ports"; + + uses transport-line-common-port-config; + uses transport-line-common-port-state; + } + } + } + + + + // data definition statements + + // uses optical-osc-top; + + // augment statements + + augment "/oc-platform:components/oc-platform:component" + + "/oc-platform:port" { + description + "Adding optical port data to platform components model"; + + uses transport-line-common-port-top; + } + + //TODO:this is placeholder until SONET model is added + //to interfaces model + augment "/oc-if:interfaces/oc-if:interface" { + when "oc-if:config/oc-if:type = 'ianaift:sonet'" { + description "Additional interface configuration parameters when + the interface type is SONET/SDH"; + } + description "Adds additional SONET/SDH-specific data to + osc model"; + + container sonet { + description + "Data related to SONET/SDH interfaces"; + } + } + + // rpc statements + + // notification statements + +} diff --git a/models/yang/openconfig-transport-line-protection.yang b/models/yang/openconfig-transport-line-protection.yang new file mode 100644 index 000000000..52a7c3ce2 --- /dev/null +++ b/models/yang/openconfig-transport-line-protection.yang @@ -0,0 +1,623 @@ +module openconfig-transport-line-protection { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/optical-transport-line-protection"; + + prefix "oc-line-protect"; + + import openconfig-extensions { prefix oc-ext; } + import openconfig-types { prefix oc-types; } + import openconfig-platform { prefix oc-platform; } + + // meta + organization "OpenConfig working group"; + + contact + "OpenConfig working group + www.openconfig.net"; + + description + "This model describes configuration and operational state data + for optical line protection elements, deployed as part of a + transport line system. An Automatic Protection Switch (APS) + is typically installed in the same device as the amplifiers + and wave-router, however an APS can also be a standalone + device. In both scenarios, it serves the same purpose of + providing protection using two dark fiber pairs to ensure the + amplifiers can still receive a signal if one of the two fiber + pairs is broken. The APS port details and directionality are + shown below. The three major attributes, together with their + modifiers, define the behavior of the APS and can be prioritized + in the descending order as shown in the following table"; + + // + // Automatic Protection Switch (APS) port details and directionality. + // _________ + // | | + // | | <=== LINE-PRIMARY-IN + // | | + // COMMON-IN ===> | | ===> LINE-PRIMARY-OUT + // | | + // | APS | + // COMMON-OUT <=== | | + // | | <=== LINE-SECONDARY-IN + // | | + // | | ===> LINE-SECONDARY-OUT + // |_______| + // + // + // The interaction of configuration attributes that control the + // protection switching behavior + // +------------------+--------------------+------------------------+ + // | Attribute | Modifier | Behavior | + // +------------------+--------------------+------------------------+ + // | force-to-port | n/a | turns off switching | + // | | | by forcing to primary | + // | | | or secondary | + // +------------------+--------------------+------------------------+ + // | relative-switch | relative-threshold | if set, overrides | + // | -threshold | -offset | primary and secondary | + // | | | switch thresholds | + // +------------------+--------------------+------------------------+ + // | primary-switch | primary-switch | sets respective | + // | -threshold, | -hysteresis | threshold to switch | + // | secondary-switch | | to opposite port | + // | -threshold | | | + // +------------------+--------------------+------------------------+ + + oc-ext:openconfig-version "0.4.1"; + + revision "2018-11-21" { + description + "Add OpenConfig module metadata extensions."; + reference "0.4.1"; + } + + revision "2018-07-25" { + description + "Added wait-to-restore-time, hold-off-time, + relative-switch-threshold, relative-switch-threshold-offset, + forced-to-port, removed secondary-switch-hysteresis, and + edited the description of primary-switch-threshold, + secondary-switch-threshold, and primary-switch-hysteresis"; + reference "0.4.0"; + } + + revision "2017-09-08" { + description + "Correct bug with OSC interfaces"; + reference "0.3.1"; + } + + revision "2017-07-08" { + description + "Support multiple OCMs, add monitor port type + and refs to hw ports, "; + reference "0.3.0"; + } + + revision "2017-03-28" { + description + "Added min/max/avg stats, status for media channels, OCM, APS"; + reference "0.2.0"; + } + + revision "2016-08-05" { + description + "Initial public release"; + reference "0.1.0"; + } + + // OpenConfig specific extensions for module metadata. + oc-ext:regexp-posix; + oc-ext:catalog-organization "openconfig"; + oc-ext:origin "openconfig"; + + // extension statements + + // feature statements + + // identity statements + + identity APS_PATHS { + description + "Base identity for identifying the line paths on an + automatic protection switch"; + } + + identity PRIMARY { + base APS_PATHS; + description + "The primary line path connected to an automatic protection + switch port indicating the primary/preferred path"; + } + + identity SECONDARY { + base APS_PATHS; + description + "The secondary line path connected to an automatic protection + switch port indicating the secondary path"; + } + + // grouping statements + + grouping aps-input-port-config { + description + "Grouping for config related to unidirectional automatic + protection switch input ports"; + + leaf enabled { + type boolean; + default "true"; + description + "This leaf contains the configured, desired state of the + port. Disabling the port turns off alarm reporting for + the port"; + } + + leaf target-attenuation { + type decimal64 { + fraction-digits 2; + } + units dB; + description + "Target attenuation of the variable optical attenuator + associated with the port in increments of 0.01 dB."; + } + } + + grouping aps-output-port-config { + description + "Grouping for config related to unidirectional automatic + protection switch output ports"; + + leaf target-attenuation { + type decimal64 { + fraction-digits 2; + } + units dB; + description + "Target attenuation of the variable optical attenuator + associated with the port in increments of 0.01 dB"; + } + } + + grouping aps-input-port-state { + description + "Grouping for state related to unidirectional automatic + protection switch input ports"; + + leaf attenuation { + type decimal64 { + fraction-digits 2; + } + units dB; + description + "The attenuation of the variable optical attenuator + associated with the port in increments of 0.01 dB."; + } + + container optical-power { + description + "The optical input power of this port in units of + 0.01dBm. Optical input power represents the signal + traversing from an external destination into the module. + The power is measured before any attenuation. If avg/min/max + statistics are not supported, the target is expected to + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + } + + grouping aps-output-port-state { + description + "Grouping for state related to unidirectional automatic + protection switch output ports"; + + leaf attenuation { + type decimal64 { + fraction-digits 2; + } + units dB; + description + "The attenuation of the variable optical attenuator + associated with the port in increments of 0.01 dB"; + } + + container optical-power { + description + "The optical output power of this port in units of + 0.01dBm. Optical output power represents the signal + traversing from the module to an external destination. The + power is measured after any attenuation. If avg/min/max + statistics are not supported, the target is expected to + just supply the instant value"; + + uses oc-types:avg-min-max-instant-stats-precision2-dBm; + } + } + + grouping aps-ports { + description + "Top level grouping for automatic protection switch ports"; + + container line-primary-in { + description + "Container for information related to the line primary + input port"; + + container config { + description + "Configuration data for the line primary input port"; + + uses aps-input-port-config; + } + + container state { + + config false; + + description + "State data for the line primary input port"; + + uses aps-input-port-config; + uses aps-input-port-state; + } + + } + + container line-primary-out { + description + "Container for information related to the line primary + output port"; + + container config { + description + "Configuration data for the line primary output port"; + + uses aps-output-port-config; + } + + container state { + + config false; + + description + "State data for the line primary output port"; + + uses aps-output-port-config; + uses aps-output-port-state; + } + } + + container line-secondary-in { + description + "Container for information related to the line secondary + input port"; + + container config { + description + "Configuration data for the line secondary input port"; + + uses aps-input-port-config; + } + + container state { + + config false; + + description + "State data for the line secondary input port"; + + uses aps-input-port-config; + uses aps-input-port-state; + } + } + + container line-secondary-out { + description + "Container for information related to the line secondary + output port"; + + container config { + description + "Configuration data for the line secondary output port"; + + uses aps-output-port-config; + } + + container state { + + config false; + + description + "State data for the line secondary output port"; + + uses aps-output-port-config; + uses aps-output-port-state; + } + } + + container common-in { + description + "Container for information related to the line common + input port"; + + container config { + description + "Configuration data for the line common input port"; + + uses aps-input-port-config; + } + + container state { + + config false; + + description + "State data for the line common input port"; + + uses aps-input-port-config; + uses aps-input-port-state; + } + } + + container common-output { + description + "Container for information related to the line common + output port"; + + container config { + description + "Configuration data for the line common output port"; + + uses aps-output-port-config; + } + + container state { + + config false; + + description + "State data for the line common output port"; + + uses aps-output-port-config; + uses aps-output-port-state; + } + } + } + + grouping aps-config { + description + "Configuration data for automatic protection switch modules"; + + leaf name { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "Reference to the component name (in the platform model) + corresponding to this automatic protection switch module + in the device"; + } + + leaf revertive { + type boolean; + description + "Revertive behavior of the module. If True, then + automatically revert after protection switch once the + fault is restored. This leaf is not valid when the + relative-switch-threshold is in effect"; + } + + leaf wait-to-restore-time { + type uint32; + units milliseconds; + description + "The time that must elapse before an APS path + that has recovered from an signal failure (SF) or signal + degradation (SD) condition can be used again to transport + the normal traffic signal. During this time period, an SF or + SD condition shall override the wait-to-restore time period. + This leaf can only take effect when the revertive leaf + equals true"; + } + + leaf hold-off-time { + type uint32; + units milliseconds; + description + "The time delay between the declaration of an SF or SD + condition and the initiation of the protection switching + algorithm"; + } + + leaf primary-switch-threshold { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "The threshold at which the primary line port will switch to + the opposite line port in increments of 0.01 dBm. If the + hardware supports only one switch threshold for primary and + and secondary ports then it is recommended to set both + primary-switch-threshold and secondary-switch-threshold to + the same value to be explicit. When the relative switch + threshold is enabled, i.e. set to a non-zero value, the + primary switch threshold will be overridden"; + } + + leaf primary-switch-hysteresis { + type decimal64 { + fraction-digits 2; + } + units dB; + default 0; + description + "The delta in dB between the primary-switch-threshold + and the signal received on the primary APS_PATH before + initiating a switch from the secondary APS_PATH to the + primary APS_PATH, in order to prevent toggling between ports + when an input signal is very close to the threshold. A zero + value means the switch hysteresis is disabled."; + } + + leaf secondary-switch-threshold { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "The threshold at which the secondary line port will switch to + the opposite line port in increments of 0.01 dBm. If the + hardware supports only one switch threshold for primary and + and secondary ports then it is recommended to set both + primary-switch-threshold and secondary-switch-threshold to + the same value to be explicit. When the relative switch + threshold is enabled, i.e. set to a non-zero value, the + secondary switch threshold will be overridden"; + } + + leaf relative-switch-threshold { + type decimal64 { + fraction-digits 2; + } + units dB; + default 0; + description + "The delta threshold in dB at which the current line port + will switch to the opposite line port. It can be set to + the value of 0dB. When set to 0dB, the threshold is ignored + and the system automatically applies the primary and + secondary switch thresholds. When set to a non-zero value, + it overrides the primary and secondary switch thresholds"; + } + + leaf relative-switch-threshold-offset { + type decimal64 { + fraction-digits 2; + } + units dB; + default 0; + description + "The offset of the relative switch threshold that compensates + the normal difference of receiving power between the primary + and secondary line ports. A negative offset corresponds to + the situation where the secondary line port receives a higher + power than the primary line port in normal condition, and a + positive offset means the opposite. The offset will only work + when the relative switch threshold is set to a non-zero + value"; + } + + leaf force-to-port { + type enumeration { + enum NONE { + description + "Do not force the switch to stay on any line port"; + } + enum PRIMARY { + description + "Force the switch to stay on the primary line port"; + } + enum SECONDARY { + description + "Force the switch to stay on the secondary line port"; + } + } + default NONE; + description + "Explicitly set the switch to stay on a port regardless of + its operational condition"; + } + } + + grouping aps-state { + description + "State data for automatic protection switch modules"; + + leaf active-path { + type identityref { + base APS_PATHS; + } + description + "Indicates which line path on the protection switch is + currently the active path connected to the common port"; + } + } + + grouping automatic-protection-switch-top { + description + "Top level grouping for automatic protection switch data"; + + container aps-modules { + description + "Enclosing container for list of automatic protection + switch modules"; + + list aps-module { + key "name"; + description + "List of automatic protection switch modules present + in the device"; + + leaf name { + type leafref { + path "../config/name"; + } + description + "Reference to the config name list key"; + } + + container config { + description + "Configuration data for an automatic protection + switch module"; + + uses aps-config; + } + + container state { + + config false; + + description + "Operational state data for an automatic protection + switch module"; + + uses aps-config; + uses aps-state; + } + + container ports { + description + "Top level grouping for automatic protection switch ports"; + + uses aps-ports; + } + } + } + } + + grouping transport-line-protection-top { + description + "Top level grouping for transport line protection data"; + + container aps { + description + "Top level grouping for automatic protection switch data"; + + uses automatic-protection-switch-top; + } + } + + // data definition statements + + uses transport-line-protection-top; + +} diff --git a/models/yang/openconfig-wavelength-router.yang b/models/yang/openconfig-wavelength-router.yang new file mode 100644 index 000000000..c1fca146d --- /dev/null +++ b/models/yang/openconfig-wavelength-router.yang @@ -0,0 +1,755 @@ +module openconfig-wavelength-router { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/wavelength-router"; + + prefix "oc-wave-router"; + + // import some basic types + import openconfig-extensions { prefix oc-ext; } + import openconfig-platform { prefix oc-platform; } + import openconfig-transport-types { prefix oc-opt-types; } + + + // meta + organization "OpenConfig working group"; + + contact + "OpenConfig working group + www.openconfig.net"; + + description + "This model describes configuration and operational state data + for an optical transport line system node, or ROADM (incl. CDC + ROADMs, WSS, Dynamic Gain Equalizer/DGE). + + Nodes are modeled as a configurable switching element with + ingress and egress ports, as well as a number of add/drop ports + that can be set up to direct portions of the optical spectrum + to the appropriate degrees. + + In relation to configuring target spectrum powers, there + are two, non-overlapping, configuration possibilities that are + supported. + 1. Non-noise loaded wavelength router: + - The target spectrum powers are configured on each media + channel. + 2. Noise-loaded wavelength router: + - The target spectrum power values will be configured as a + target spectrum power profile over the full spectrum instead + of individual media channels."; + + oc-ext:openconfig-version "1.2.0"; + + revision "2024-04-08" { + description + "Add attenuation-control-range to media channel config"; + reference "1.2.0"; + } + + revision "2021-07-26" { + description + "Add dynamic loss damped mode."; + reference "1.1.0"; + } + + revision "2020-08-28" { + description + "Add ase-injection-delta-threshold leaf."; + reference "1.0.0"; + } + + revision "2020-06-03" { + description + "Add attenutation-control-mode to media channel config"; + reference "0.8.0"; + } + + revision "2019-10-24" { + description + "Migrate from using power spectral densisty to using power + target values"; + reference "0.7.0"; + } + + revision "2019-09-20" { + description + "Add ASE related state and config. Also add a super channel + parent leaf"; + reference "0.6.0"; + } + + revision "2019-06-03" { + description + "PSD profile top-level description and + port changed to a leafref."; + reference "0.5.0"; + } + + revision "2019-04-03" { + description + "Add port PSD profile modeling."; + reference "0.4.0"; + } + + revision "2018-11-21" { + description + "Add OpenConfig module metadata extensions."; + reference "0.3.3"; + } + + revision "2018-07-17" { + description + "Correct bug so that source/dest ports are components"; + reference "0.3.2"; + } + + revision "2017-09-08" { + description + "Correct bug with OSC interfaces"; + reference "0.3.1"; + } + + revision "2017-07-08" { + description + "Support multiple OCMs, add monitor port type + and refs to hw ports, "; + reference "0.3.0"; + } + + revision "2017-03-28" { + description + "Added min/max/avg stats, status for media channels, OCM, APS"; + reference "0.2.0"; + } + + revision "2016-03-31" { + description + "Initial public release"; + reference "0.1.0"; + } + + // OpenConfig specific extensions for module metadata. + oc-ext:regexp-posix; + oc-ext:catalog-organization "openconfig"; + oc-ext:origin "openconfig"; + + // identity statements + identity ATTENUATION_CONTROL_MODE { + description + "The definition for different types of attenutation control + modes on a media channel"; + } + + identity ATTENUATION_FIXED_LOSS { + base ATTENUATION_CONTROL_MODE; + description + "The attenuation applied across a media channel will be + calculated based on the target input and output powers as well + as the internal losses of the wavelength router. The target + power levels are configured using port-spectrum-power-profiles + of the two ports"; + } + + identity ATTENUATION_DYNAMIC_LOSS { + base ATTENUATION_CONTROL_MODE; + description + "The attenuation applied across a media channel is dynamically + controlled by the device by attempting to meet the target output + power as defined in the output port's + port-spectrum-power-profile"; + } + + identity ATTENUATION_DYNAMIC_LOSS_DAMPED { + base ATTENUATION_CONTROL_MODE; + description + "The attenuation applied across a media channel is dynamically + controlled by the device by attempting to meet the target output + power as defined in the output port's + port-spectrum-power-profile. In this mode, convergence to the + target output power occurs gradually to minimize any power + oscillations across the line system. These changes will happen + within the order of minutes"; + } + + // identity statements + identity ATTENUATION_CONTROL_RANGE { + description + "The definition for different types of modes to specify + attenuation control range settings on a media channel"; + } + + identity CONTROL_RANGE_FULL { + base ATTENUATION_CONTROL_RANGE; + description + "Media channel power compensation range is not constrained, + and is limited by available WSS dynamic range. Operator does not + explicitly set the undershoot and overshoot compensation range"; + } + + identity CONTROL_RANGE_LIMITED { + base ATTENUATION_CONTROL_RANGE; + description + "Media channel undershoot and overshoot compensation ranges + are defined by max-undershoot-compensation and + max-overshoot-compensation"; + } + + identity ASE_CONTROL_MODE { + description + "The definition for different types of ASE control modes + on a media channel"; + } + + identity ASE_ENABLED { + base ASE_CONTROL_MODE; + description + "The media channel will immediately have ASE noise injected"; + } + + identity ASE_DISABLED { + base ASE_CONTROL_MODE; + description + "Removes any ASE noise injection that may be present on the + media channel"; + } + + identity AUTO_ASE_ON_FAILURE { + base ASE_CONTROL_MODE; + description + "The media channel will automatically be injected with noise + if the media channel target spectrum power drops below the + provided threshdold. In this mode, at time of a failure, the + media channel is removed from the system and would need to be + reconfigured to restore traffic. In addition, unprovisioned + spectrum will be injected with noise"; + } + + identity AUTO_ASE_FAILURE_AND_RESTORE { + base ASE_CONTROL_MODE; + description + "The media channel will automatically be injected with noise + if the media channel target spectrum power drops below the + provided threshold. When the original signal is restored above + the threshold the ASE noise injection will be automatically + removed. In addition, unprovisioned spectrum will be injected + with noise"; + } + + // grouping statements + + grouping port-spectrum-power-profile-state { + description + "Operational state data for a wavelength-router + port spectrum profile"; + } + + grouping port-spectrum-power-profile-config { + description + "Configuration data for a wavelength-router port spectrum + profile"; + + leaf name { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "Reference to system-supplied name of the wavelength-router + port component."; + } + } + + grouping port-spectrum-power-profiles-top { + description + "Top-level grouping for the list of wavelength-router port + spectrum power profiles"; + + container port-spectrum-power-profiles { + description + "Enclosing container for wavelength-router port spectrum + power profiles"; + + list port { + key "name"; + description + "List of ports, keyed by port name"; + + leaf name { + type leafref { + path "../config/name"; + } + description + "References the port name"; + } + + container config { + description + "Configuration data for each port"; + + uses port-spectrum-power-profile-config; + } + + container state { + + config false; + + description + "Operational state data for each port spectrum profile."; + + uses port-spectrum-power-profile-config; + uses port-spectrum-power-profile-state; + } + uses spectrum-target-power-profiles-top; + } + } + } + + grouping media-channel-port-config { + description + "Configuration data for a media channel source/dest port"; + + leaf port-name { + type leafref { + path "/oc-platform:components/oc-platform:component/" + + "oc-platform:name"; + } + description + "Reference to the corresponding node port"; + } + } + + grouping media-channel-port-state { + description + "Operational state data for a media channel source/dest port"; + } + + grouping media-channel-source-port-top { + description + "Top-level grouping for source of the media channel"; + + container source { + description + "Top-level container for media channel source"; + + container config { + description + "Configuration data for the media channel source"; + + uses media-channel-port-config; + } + + container state { + + config false; + + description + "Operational state data for the media channel source"; + + uses media-channel-port-config; + uses media-channel-port-state; + } + } + } + + grouping media-channel-dest-port-top { + description + "Top-level grouping for destination of the media channel"; + + container dest { + description + "Top-level container for media channel destination"; + + container config { + description + "Configuration data for the media channel destination"; + + uses media-channel-port-config; + } + + container state { + + config false; + + description + "Operational state data for the media channel destination"; + + uses media-channel-port-config; + uses media-channel-port-state; + } + } + } + + grouping spectrum-target-power-config { + description + "Configuration data for the media channel target power"; + + leaf lower-frequency { + type oc-opt-types:frequency-type; + description + "Lower frequency of the specified target spectrum power"; + } + + leaf upper-frequency { + type oc-opt-types:frequency-type; + description + "Upper frequency of the specified target spectrum power"; + } + + leaf target-power { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "Target average power to achieve within the specified + spectrum"; + } + } + + grouping spectrum-target-power-state { + description + "Operational state data for the target spectrum power"; + } + + grouping spectrum-target-power-profiles-top { + description + "Top-level grouping for target spectrum profiles"; + + container spectrum-power-profile { + description + "Enclosing container for the list of values describing + the target spectrum powers"; + + list distribution { + key "lower-frequency upper-frequency"; + description + "List of tuples describing the target spectrum power + distribution"; + + leaf lower-frequency { + type leafref { + path "../config/lower-frequency"; + } + description + "Reference to the list key"; + } + + leaf upper-frequency { + type leafref { + path "../config/upper-frequency"; + } + description + "Reference to the list key"; + } + + container config { + description + "Configuration data for target spectrum power"; + + uses spectrum-target-power-config; + } + + container state { + + config false; + + description + "Operational state data for target spectrum power"; + + uses spectrum-target-power-config; + uses spectrum-target-power-state; + } + } + } + } + + grouping media-channel-config { + description + "Configuration data for media channel definitions"; + + leaf index { + type uint32; + description + "Identifier for the defined media channel"; + } + + leaf name { + type string; + description + "The user supplied name of the media channel"; + } + + leaf lower-frequency { + type oc-opt-types:frequency-type; + description + "The lower frequency for the spectrum defined by this media + channel"; + } + + leaf upper-frequency { + type oc-opt-types:frequency-type; + description + "The upper frequency for the spectrum defined by this media + channel"; + } + + leaf admin-status { + type oc-opt-types:admin-state-type; + description + "Sets the admin status of the media channel"; + } + + leaf super-channel { + type boolean; + description + "True if the media channel is a super channel which + contains multiple media channels within it. The contained + media channels should fall within the boundaries of the + super channel. The device should raise an error if a media + channel crosses a super channel boundary. When using super + channels, spectrum power targets should be defined in either + the: + - port-spectrum-power-profiles for the port which matches the + source port of the media channel representing the super + channel + - media channels that are contained within the super + channel, but not on the super channel itself"; + } + + leaf super-channel-parent { + type leafref { + path "../../../channel/config/index"; + } + description + "If the media channel is contained within a super channel this + would specify the index of the super channel parent"; + } + + leaf ase-control-mode { + type identityref { + base ASE_CONTROL_MODE; + } + description + "Sets the ASE control mode for the media channel. + The control mode defines if and when ASE noise is injected + on the media channel"; + } + + leaf ase-injection-mode { + type enumeration { + enum MODE_THRESHOLD { + description + "When set ASE noise will be injected when a defined + threshold is crossed."; + } + enum MODE_DELTA { + description + "When set ASE noise will be injected when a defined + delta in optical power occurs."; + } + } + description + "When specified, defines the mode used to determine whether + ASE noise should be injected on the media channel."; + } + + leaf ase-injection-threshold { + type decimal64 { + fraction-digits 2; + } + when "../ase-injection-mode = 'MODE_THRESHOLD'"; + units dBm; + description + "Defines the optical power threshold value below which ASE + noise should be injected on the media channel. This or + ase-injection-delta is required if an ase-control-mode is + configured"; + } + + leaf ase-injection-delta { + type decimal64 { + fraction-digits 2; + } + when "../ase-injection-mode = 'MODE_DELTA'"; + units dB; + description + "Defines the optical power loss from the configured spectrum + power profile, which would indicate that ASE noise should be + injected on the media channel. This or + ase-injection-threshold is required if an ase-control-mode + is configured"; + } + + leaf media-channel-injection-offset { + type decimal64 { + fraction-digits 2; + } + units dB; + description + "Defines the optical power offset value relative to the + ASE injection threshold at which point ASE should be removed + and the media-channel should be injected. Requires + ase-injection-delta or ase-injection-threshold to be + configured"; + } + + leaf attenuation-control-mode { + type identityref { + base ATTENUATION_CONTROL_MODE; + } + description + "Sets the attenuation control mode for the media channel. + The control mode defines the behavior of how the attenuation + across a media channel is set"; + } + + leaf attenuation-control-range { + type identityref { + base ATTENUATION_CONTROL_RANGE; + } + description + "Sets the attenuation control range for the media channel. + The control range defines the amount of media channel + undershoot and overshoot compensation that will be applied + when performing power targeting to meet the defined output + port spectrum power profile"; + } + + leaf max-undershoot-compensation { + type decimal64 { + fraction-digits 2; + } + when "../attenuation-control-range = 'CONTROL_RANGE_LIMITED'"; + units dB; + description + "Defines the maximum allowable WSS attenuation adjustment + the system will use to compensate a channel with input power + lower than the defined target power at the input. This value + is measured relative to the baseline WSS attenuation + established for an individual media-channel"; + } + + leaf max-overshoot-compensation { + type decimal64 { + fraction-digits 2; + } + when "../attenuation-control-range = 'CONTROL_RANGE_LIMITED'"; + units dB; + description + "Defines the maximum allowable WSS attenuation adjustment + the system will use to compensate a channel with input power + higher than the defined target power at the input. This + value is measured relative to the baseline WSS attenuation + established for an individual media-channel"; + } + } + + grouping media-channel-state { + description + "Operational state data for media channels "; + + leaf oper-status { + type enumeration { + enum UP { + description + "Media channel is operationally up"; + } + enum DOWN { + description + "Media channel is operationally down"; + } + } + description + "Operational state of the media channel"; + } + + leaf ase-status { + type enumeration { + enum PRESENT { + description + "Media channel has injected ASE noise present"; + } + enum NOT_PRESENT { + description + "Media channel does not have injected ASE noise present"; + } + } + description + "Status of injected ASE noise on the media channel"; + } + + } + + grouping media-channel-top { + description + "Top-level grouping for list of defined media channels"; + + container media-channels { + description + "Enclosing container for media channel list"; + + list channel { + key "index"; + description + "List of media channels"; + + leaf index { + type leafref { + path "../config/index"; + } + description + "Reference to index number of the media channel"; + } + + container config { + description + "Configuration data "; + + uses media-channel-config; + } + + container state { + + config false; + + description + "Operational state data "; + + uses media-channel-config; + uses media-channel-state; + } + + uses media-channel-source-port-top; + uses media-channel-dest-port-top; + uses spectrum-target-power-profiles-top; + } + } + } + + grouping wavelength-router-top { + description + "Top level grouping for the wavelength router"; + + container wavelength-router { + description + "Top-level container for wavelength router device"; + + uses media-channel-top; + uses port-spectrum-power-profiles-top; + } + } + + // data definition statements + + uses wavelength-router-top; + + // augment statements + + // rpc statements + + // notification statements + +} \ No newline at end of file diff --git a/models/yang/sonic/sonic-channel-monitor-state.yang b/models/yang/sonic/sonic-channel-monitor-state.yang new file mode 100644 index 000000000..99670d87e --- /dev/null +++ b/models/yang/sonic/sonic-channel-monitor-state.yang @@ -0,0 +1,71 @@ +module sonic-channel-monitor-state { + namespace "http://github.com/Azure/sonic-channel-monitor-state"; + prefix sonic-opt-cha-mon; + + import sonic-extension { prefix sonic-ext; } + + organization + "SONiC"; + contact + "SONiC"; + description + "SONIC CHANNEL MONITOR STATE"; + + revision 2024-03-05 { + description + "Initial revision."; + } + + container sonic-channel-monitor-state { + container OCM { + list OCM_LIST { + key "name"; + leaf name { + type string; + } + + leaf monitor-port { + type string; + } + } + } + container OCM_TABLE { + sonic-ext:db-name "STATE_DB"; + list OCM_TABLE_LIST { + key "name"; + sonic-ext:map-list "true"; //special annotation for map table + + leaf name { + type string; + } + + leaf monitor-port { + type string; + } + } + } + container OCM_CHANNEL_TABLE { + sonic-ext:db-name "STATE_DB"; + list OCM_CHANNEL_TABLE_LIST { //this is list inside list for storing mapping between two fields + key "lower-frequency upper-frequency"; + leaf lower-frequency { + type uint64; + units "MHz"; + description + "Type for optical spectrum frequency values"; + } + leaf upper-frequency { + type uint64; + units "MHz"; + description + "Type for optical spectrum frequency values"; + } + leaf power { + type decimal64 { + fraction-digits 2; + } + } + } + } + } +} diff --git a/models/yang/sonic/sonic-optical-amplifier.yang b/models/yang/sonic/sonic-optical-amplifier.yang index 0ae0082ac..c993ab2fb 100644 --- a/models/yang/sonic/sonic-optical-amplifier.yang +++ b/models/yang/sonic/sonic-optical-amplifier.yang @@ -1,129 +1,156 @@ module sonic-optical-amplifier { - namespace "http://github.com/Azure/sonic-optical-amplifier"; - prefix "sopt-amp"; - - import sonic-extension { - prefix sonic-ext; - } - - organization - "SONiC"; - - contact - "SONiC"; - - description - "SONIC OPTICAL AMPLIFIER"; + namespace "http://github.com/Azure/sonic-optical-amplifier"; + prefix sonic-opt-amp; - revision 2022-06-13 { - description - "Initial revision."; - } - - - container sonic-optical-amplifier { + import sonic-extension { + prefix sonic-ext; + } - container OTN_OA { + organization + "SONiC"; + contact + "SONiC"; + description + "SONIC OPTICAL AMPLIFIER"; - list OTN_OA_LIST { - key "name"; - - leaf name { - type string; - description - "User-defined name assigned to identify a specific amplifier - in the device"; - } - - leaf type { - type string; - description - "Type of the amplifier"; - } - - leaf target-gain { - type decimal64 { - fraction-digits 2; - } - description - "Positive gain applied by the amplifier."; - } - - leaf target-gain-tilt { - type decimal64 { - fraction-digits 2; - } - description - "Gain tilt control"; - } - - leaf gain-range { - type string; - description - "Selected gain range. The gain range is a platform-defined - value indicating the switched gain amplifier setting"; - } - - leaf amp-mode { - type string; - description - "The operating mode of the amplifier"; - } - - leaf target-output-power { - type decimal64 { - fraction-digits 2; - } - description - "Output optical power of the amplifier."; - } - - leaf enabled { - type boolean; - description - "Turns power on / off to the amplifiers gain module."; - } - - leaf fiber-type-profile { - type string; - description - "The fiber type profile specifies details about the - fiber type which are needed to accurately determine - the gain and perform efficient amplification. This is - only needed for Raman type amplifiers."; - } - - leaf autolos { - type boolean; - description - "Determines the behavior of the amplifier on input LOS."; - } + revision 2024-03-19 { + description + "Initial revision."; + } - leaf apr-enabled { - type boolean; - description - "Turns apr on / off to the amplifiers."; - } + container sonic-optical-amplifier { + container AMPLIFIER { + description + "Configuration data for optical amplifiers in CONFIG_DB."; + list AMPLIFIER_LIST { + key "name"; + leaf name { + type string; + description + "User-defined name assigned to identify a specific amplifier + in the device"; + } + leaf type { + type string; + description + "Type of the amplifier"; + } + leaf target-gain { + type decimal64 { + range "0..max"; + fraction-digits 2; + } + units "dB"; + description + "Positive gain applied by the amplifier. This is used + when the amp-mode is in CONSTANT_GAIN or DYNAMIC_GAIN + mode to set the target gain that the amplifier should + achieve."; + } + leaf min-gain { + type decimal64 { + fraction-digits 2; + } + units "dBm"; + description + "The minimum allowed gain of the amplifier. This is used + when the amp-mode is in CONSTANT_POWER or DYNAMIC_GAIN mode + to prevent the gain from dropping below a desired threshold. + If left empty, the platform will apply a minimum gain based + on hardware specifications."; + } + leaf max-gain { + type decimal64 { + fraction-digits 2; + } + units "dBm"; + description + "The maximum allowed gain of the amplifier. This is used + when the amp-mode is in CONSTANT_POWER or DYNAMIC_GAIN mode + to prevent the gain from exceeding a desired threshold. If + left empty, the platform will apply a maximum gain based on + hardware specifications."; + } + leaf target-gain-tilt { + type decimal64 { + fraction-digits 2; + } + units "dB"; + description + "Gain tilt control"; + } + leaf gain-range { + type string; + description + "Selected gain range. The gain range is a platform-defined + value indicating the switched gain amplifier setting"; + } + leaf amp-mode { + type string; + description + "The operating mode of the amplifier"; + } + leaf target-output-power { + type decimal64 { + fraction-digits 2; + } + units "dBm"; + description + "Output optical power of the amplifier."; + } + leaf max-output-power { + type decimal64 { + fraction-digits 2; } + units "dBm"; + description + "The maximum optical output power of the amplifier. This + may be used to prevent the output power from exceeding a + desired threshold."; + } + leaf enabled { + type boolean; + description + "Turns power on / off to the amplifiers gain module."; + } + leaf fiber-type-profile { + type string; + description + "The fiber type profile specifies details about the + fiber type which are needed to accurately determine + the gain and perform efficient amplification. This is + only needed for Raman type amplifiers."; + } + leaf autolos { + type boolean; + description + "Determines the behavior of the amplifier on input LOS."; + } + leaf apr-enabled { + type boolean; + description + "Turns apr on / off to the amplifiers."; + } + } } - container OTN_OSC { - - list OTN_OSC_LIST { + container OSC { + description + "Configuration data for optical amplifiers in CONFIG_DB."; + list OSC_LIST { key "interface"; - leaf interface { type string; description - "Reference to an OSC interface"; + "Reference to an OSC interface"; } - leaf enabled { type boolean; description - "turn on/off sfp"; + "turn on/off sfp"; } } } } } + diff --git a/models/yang/sonic/sonic-optical-attenuator.yang b/models/yang/sonic/sonic-optical-attenuator.yang index f1728a94d..b727fda49 100644 --- a/models/yang/sonic/sonic-optical-attenuator.yang +++ b/models/yang/sonic/sonic-optical-attenuator.yang @@ -1,62 +1,110 @@ module sonic-optical-attenuator { namespace "http://github.com/Azure/sonic-optical-attenuator"; - prefix "sonic-opt-att"; + prefix sonic-opt-att; - import sonic-extension { prefix sonic-ext; } + import sonic-extension { + prefix sonic-ext; + } organization "SONiC"; - contact "SONiC"; - description "SONIC OPTICAL ATTENUATOR"; - revision 2022-06-13 { + revision 2024-03-19 { description "Initial revision."; } - container sonic-optical-attenuator { + container ATTENUATOR { + description + "Configuration data for optical attenuators in CONFIG_DB."; + list ATTENUATOR_LIST { + key "name"; + leaf name { + type string; + description + "User-defined name assigned to identify a specific attenuator + in the device"; + } - container OTN_ATTENUATOR { + leaf attenuation-mode { + type string; + description + "The operating mode of the attenuator"; + } - list OTN_ATTENUATOR_LIST { - key "name"; + leaf target-output-power { + type decimal64 { + fraction-digits 2; + } + units "dB"; + description + "Power level set on the output of attenuator. This leaf is + only relevant when in CONSTANT_POWER mode."; + } + + leaf attenuation { + type decimal64 { + range "0..max"; + fraction-digits 2; + } + units "dB"; + description + "Attenuation applied by the attenuator. This leaf is only + relevant when in CONSTANT_ATTENUATION mode."; + } + + leaf enabled { + type boolean; + description + "When true, attenuator is set to specified attenuation or varies to + maintain constant output power. When false, the attenuator is set + max attenuation or blocked."; + } + } + } + container ATTENUATOR_TABLE { + sonic-ext:db-name "STATE_DB"; + config false; + description + "Operational state data for optical attenuators in STATE_DB."; + list ATTENUATOR_TABLE_LIST { + key "name"; leaf name { type string; - description - "User-defined name assigned to identify a specific attenuator - in the device"; + description + "User-defined name assigned to identify a specific attenuator + in the device"; } - leaf attenuation-mode { type string; description "The operating mode of the attenuator"; } - leaf target-output-power { type decimal64 { fraction-digits 2; } + units "dB"; description "Power level set on the output of attenuator. This leaf is - only relevant when in CONSTANT_POWER mode."; + only relevant when in CONSTANT_POWER mode."; } - leaf attenuation { type decimal64 { + range "0..max"; fraction-digits 2; } + units "dB"; description "Attenuation applied by the attenuator. This leaf is only - relevant when in CONSTANT_ATTENUATION mode."; + relevant when in CONSTANT_ATTENUATION mode."; } - leaf enabled { type boolean; description @@ -64,7 +112,59 @@ module sonic-optical-attenuator { maintain constant output power. When false, the attenuator is set max attenuation or blocked."; } + leaf component { + type string; + description + "Reference to the system-supplied physical component that + the attenuator block is contained within. Multiple + attenuator blocks may be contained within the same + physical component."; + } + leaf ingress-port { + type string; + description + "Reference to system-supplied name of the attenuator ingress + port. This leaf is only valid for ports of type INGRESS."; + } + leaf egress-port { + type string; + description + "Reference to system-supplied name of the attenuator egress + port. This leaf is only valid for ports of type EGRESS."; + } + leaf actual-attenuation { + type decimal64 { + fraction-digits 2; + } + units "dB"; + description + "The actual attenuation applied by the attenuator in units of + 0.01dB. If avg/min/max statistics are not supported, + just supply the instant value"; + } + leaf output-power-total { + type decimal64 { + fraction-digits 2; + } + units "dBm"; + description + "The total output optical power of this port in units + of 0.01dBm. If avg/min/max statistics are not supported, + just supply the instant value"; + } + leaf optical-return-loss { + type decimal64 { + fraction-digits 2; + } + units "dBm"; + description + "The optical return loss (ORL) is the ratio of the light + reflected back into the port to the light launched out of + the port. ORL is in units of 0.01dBm. If avg/min/max + statistics are not supported, just supply the instant value."; + } } } } } + diff --git a/models/yang/sonic/sonic-optical-time-domain-reflectometer.yang b/models/yang/sonic/sonic-optical-time-domain-reflectometer.yang new file mode 100644 index 000000000..6cb18bd50 --- /dev/null +++ b/models/yang/sonic/sonic-optical-time-domain-reflectometer.yang @@ -0,0 +1,117 @@ +module sonic-optical-time-domain-reflectometer { + namespace "http://github.com/Azure/sonic-optical-time-domain-reflectometer"; + prefix sonic-opt-tim-dom-ref; + + import sonic-extension { + prefix sonic-ext; + } + + organization + "SONiC"; + contact + "SONiC"; + description + "SONIC OPTICAL TIME DOMAIN REFLECTOMETER"; + + revision 2024-06-28 { + description + "Initial revision."; + } + + container sonic-optical-time-domain-reflectometer { + container OTDR { + sonic-ext:db-name "CONFIG_DB"; + description + "Enclosing container for OTDR scan list"; + list OTDR_LIST { + key "name"; + leaf start-time { + type string; + description + "The start date and time of the repetition"; + } + leaf period { + type uint32; + units "s"; + description + "The scan period of the repetition, e.g. 60s, 15*60s, 24*60*60s"; + } + leaf enable { + type boolean; + description + "Repetition or not. If True, then + periodic scan the fiber with given frequency"; + } + leaf name { + type string; + description + "OTDR name"; + } + leaf parent-port { + type string; + description + "OTDR scan port"; + } + leaf refractive-index { + type decimal64 { + fraction-digits 4; + } + description + "refractive ratio"; + } + leaf backscatter-index { + type decimal64 { + fraction-digits 2; + } + description + "backscatter ratio"; + } + leaf reflection-threshold { + type decimal64 { + fraction-digits 2; + } + description + "reflection threshold"; + } + leaf splice-loss-threshold { + type decimal64 { + fraction-digits 2; + } + description + "splice loss threshold"; + } + leaf end-of-fiber-threshold { + type decimal64 { + fraction-digits 2; + } + description + "fiber end event threshold"; + } + leaf pulse-width { + type uint32; + units "ns"; + description + "pulse width in ns"; + } + leaf average-time { + type uint32; + units "s"; + description + "Average time of each scanning"; + } + leaf output-frequency { + type uint64; + units "MHz"; + description + "The output frequency in MHz of the OTDR"; + } + leaf distance-range { + type uint32; + units "km"; + description + "distance range in km"; + } + } + } + } +} diff --git a/models/yang/sonic/sonic-platform-oc.yang b/models/yang/sonic/sonic-platform-oc.yang new file mode 100644 index 000000000..3944f74d0 --- /dev/null +++ b/models/yang/sonic/sonic-platform-oc.yang @@ -0,0 +1,102 @@ +module sonic-platform-oc { + namespace "http://github.com/Azure/sonic-platform-oc"; + prefix sonic-opt-amp; + + import sonic-extension { + prefix sonic-ext; + } + + organization + "SONiC"; + contact + "SONiC"; + description + "SONIC OC COMPONENT"; + + revision 2024-03-19 { + description + "Initial revision."; + } + + container sonic-platform-oc { + container OC_COMPONENT { + description + "Configuration data for platform components in CONFIG_DB."; + list OC_COMPONENT_LIST { + key "name"; + leaf name { + type string; + description + "User-defined name assigned to identify a specific component + in the device"; + } + leaf frequency { + type uint64; + units "MHz"; + description + "Frequency of the optical channel, expressed in MHz"; + } + + leaf target-output-power { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "Target output optical power level of the optical channel, + expressed in increments of 0.01 dBm (decibel-milliwats)"; + } + + leaf operational-mode { + type uint16; + description + "Vendor-specific mode identifier"; + } + // TRANSCEIVER + leaf enabled { + type boolean; + description + "Turns power on / off to the transceiver -- provides a means + to power on/off the transceiver (in the case of SFP, SFP+, + QSFP,...) or enable high-power mode (in the case of CFP, + CFP2, CFP4) and is optionally supported (device can choose to + always enable). True = power on / high power, False = + powered off"; + } + leaf fec-mode { + type string; + description + "The FEC mode indicates the mode of operation for the + transceiver's FEC. This defines typical operational modes + and does not aim to specify more granular FEC capabilities."; + } + leaf ethernet-pmd-preconf { + type string; + description + "The Ethernet PMD is a property of the optical transceiver + used on the port, indicating the type of physical connection. + It is included in configuration data to allow pre-configuring + a port/transceiver with the expected PMD. The actual PMD is + indicated by the ethernet-pmd state leaf."; + } + + + } + } + container OC_COMPONENT_TABLE { + sonic-ext:db-name "STATE_DB"; + config false; + description + "Operational state data for optical components in STATE_DB."; + list OC_COMPONENT_TABLE_LIST { + key "name"; + leaf name { + type string; + description + "User-defined name assigned to identify a specific component + in the device"; + } + } + } + } +} diff --git a/models/yang/sonic/sonic-platform-transceiver.yang b/models/yang/sonic/sonic-platform-transceiver.yang new file mode 100644 index 000000000..7d32a1cb9 --- /dev/null +++ b/models/yang/sonic/sonic-platform-transceiver.yang @@ -0,0 +1,60 @@ +module sonic-platform-transceiver { + namespace "http://github.com/Azure/sonic-platform-transceiver"; + prefix sonic-pfm-transceiver; + + import sonic-extension { + prefix sonic-ext; + } + + organization + "SONiC"; + contact + "SONiC"; + description + "SONIC PLATFORM TRANSCEIVER"; + + revision 2024-06-28 { + description + "Initial revision."; + } + + container sonic-platform-transceiver { + container TRANSCEIVER { + description + "Configuration data for transceiver list in CONFIG_DB"; + list TRANSCEIVER_LIST { + key "name"; + leaf name { + type string; + description "Unique identifier for the transceiver."; + } + leaf enabled { + type boolean; + description + "Turns power on / off to the transceiver -- provides a means + to power on/off the transceiver (in the case of SFP, SFP+, + QSFP,...) or enable high-power mode (in the case of CFP, + CFP2, CFP4) and is optionally supported (device can choose to + always enable). True = power on / high power, False = + powered off"; + } + leaf fec-mode { + type string; + description + "The FEC mode indicates the mode of operation for the + transceiver's FEC. This defines typical operational modes + and does not aim to specify more granular FEC capabilities."; + } + leaf ethernet-pmd-preconf { + type string; + description + "The Ethernet PMD is a property of the optical transceiver + used on the port, indicating the type of physical connection. + It is included in configuration data to allow pre-configuring + a port/transceiver with the expected PMD. The actual PMD is + indicated by the ethernet-pmd state leaf."; + } + } + } + } +} diff --git a/models/yang/sonic/sonic-telemetry-client.yang b/models/yang/sonic/sonic-telemetry-client.yang new file mode 100644 index 000000000..03ef0d18b --- /dev/null +++ b/models/yang/sonic/sonic-telemetry-client.yang @@ -0,0 +1,118 @@ +module sonic-telemetry-client { + + yang-version 1.1; + + namespace "http://github.com/sonic-net/sonic-telemetry-client"; + prefix telemetry_client; + + import ietf-inet-types { + prefix inet; + } + + organization + "SONiC"; + + contact + "SONiC"; + + description + "TELEMETRY_CLIENT yang Module for SONiC OS"; + + revision 2023-01-12 { + description + "First revision"; + } + + typedef report-type { + type enumeration { + enum periodic; + enum stream; + enum once; + } + } + typedef path_target { + type enumeration { + enum APPL_DB; + enum CONFIG_DB; + enum COUNTERS_DB; + enum STATE_DB; + enum OTHERS; + } + } + + typedef encoding { + type enumeration { + enum JSON_IETF; + enum ASCII; + enum BYTES; + enum PROTO; + } + } + + typedef ipv4-port { + type string { + pattern + '((([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]):' + + '([0-9]|[1-9]\d{1,3}|[1-5]\d{1,4}|6[0-4]\d{1,3}|65[0-4]\d{1,2}|655[0-2][0-9]|6553[0-5]),?)+'; + } + } + + container sonic-telemetry-client{ + + container TELEMETRY_CLIENT { + + list TELEMETRY_CLIENT_LIST { + ordered-by user; + key "name"; + + leaf name { + type string; + } + leaf report_interval { + type uint64; + description "report_interval unit ms"; + default 5000; + } + leaf path_target { + type string; + } + leaf paths { + type string; + } + leaf heartbeat_interval { + type uint64; + description "heartbeat_interval unit ms"; + } + leaf report_type { + type report-type; + } + leaf dst_group { + type string; + } + leaf retry_interval { + type uint64; + description "retry_interval unit s"; + } + + leaf src_ip { + type inet:ip-address; + } + + leaf encoding { + type encoding; + } + + leaf unidirectional { + type boolean; + default true; + } + leaf dst_addr { + type string; + } + + } + } + } +} + diff --git a/models/yang/sonic/sonic-telemetry-config.yang b/models/yang/sonic/sonic-telemetry-config.yang new file mode 100644 index 000000000..92a8b1f2e --- /dev/null +++ b/models/yang/sonic/sonic-telemetry-config.yang @@ -0,0 +1,183 @@ +module sonic-telemetry-config { + yang-version 1.1; + + namespace "http://github.com/Azure/sonic-telemetry-config"; + prefix sonic-tel; + + import sonic-extension { + prefix sonic-ext; + } + + import ietf-inet-types { + prefix inet; + } + + organization + "SONiC"; + contact + "SONiC"; + description + "SONIC TELEMETRY"; + + revision 2024-06-14 { + description + "Initial revision."; + } + + container sonic-telemetry-config { + container SENSOR_GROUP { + description + "Configuration data for telemetry systems in CONFIG_DB."; + list SENSOR_GROUP_LIST { + key "sensor-group-id"; + leaf sensor-group-id { + type string; + description + "Name or identifier for the sensor group itself. + Will be referenced by other configuration specifying a + sensor group"; + } + leaf sensor-paths { + type string; + description + "Path to a section of operational state of interest + (the sensor)."; + } + } + } + container DESTINATION_GROUP { + description + "Configuration data for telemetry systems in CONFIG_DB."; + list DESTINATION_GROUP_LIST { + key "group-id"; + leaf group-id { + type string; + description + "Unique identifier for the destination group"; + } + } + + } + container DESTINATION { + description + "Configuration data for telemetry systems in CONFIG_DB."; + list DESTINATION_LIST { + key "group-id destination-address destination-port"; + leaf group-id { + type string; + description + "Unique identifier for the destination group"; + } + leaf destination-address { + type inet:ip-address; + description + "IP address of the telemetry stream destination"; + } + leaf destination-port { + type uint16; + description + "Protocol (udp or tcp) port number for the telemetry + stream destination"; + } + + } + } + + container PERSISTENT_SUBSCRIPTION { + description + "Configuration data for telemetry systems in CONFIG_DB."; + list PERSISTENT_SUBSCRIPTION_LIST { + key "name"; + leaf name { + type string; + description + "Reference to the identifier of the subscription + itself. The id will be the handle to refer to the + subscription once created"; + } + + leaf protocol { + type string; + description + "Selection of the transport protocol for the telemetry + stream."; + } + leaf encoding { + type string; + description + "Selection of the specific encoding or RPC framework + for telemetry messages to and from the network element."; + } + } + } + container SENSOR_PROFILE { + description + "Configuration data for telemetry systems in CONFIG_DB."; + list SENSOR_PROFILE_LIST { + key "name sensor-group"; + leaf name { + type string; + description + "Reference to the identifier of the subscription + itself. The id will be the handle to refer to the + subscription once created"; + } + + leaf sensor-group { + type string; + description + "Reference to the sensor group which is used in the profile"; + } + leaf sample-interval { + type uint64; + description + "Time in milliseconds between the device's sample of a + telemetry data source. For example, setting this to 100 + would require the local device to collect the telemetry + data every 100 milliseconds. There can be latency or jitter + in transmitting the data, but the sample must occur at + the specified interval. + + The timestamp must reflect the actual time when the data + was sampled, not simply the previous sample timestamp + + sample-interval. + + If sample-interval is set to 0, the telemetry sensor + becomes event based. The sensor must then emit data upon + every change of the underlying data source."; + } + leaf heartbeat-interval { + type uint64; + description + "Maximum time interval in seconds that may pass + between updates from a device to a telemetry collector. + If this interval expires, but there is no updated data to + send (such as if suppress_updates has been configured), the + device must send a telemetry message to the collector."; + } + } + } + container SUBSCRIPTION_DESTINATION_GROUP { + description + "Configuration data for telemetry systems in CONFIG_DB."; + list SUBSCRIPTION_DESTINATION_GROUP_LIST { + key "name group-id"; + leaf name { + type string; + description + "Reference to the identifier of the subscription + itself. The id will be the handle to refer to the + subscription once created"; + } + + leaf group-id { + type string; + description + "Unique identifier for the destination group"; + } + + } + } + } + +} diff --git a/models/yang/sonic/sonic-terminal-device.yang b/models/yang/sonic/sonic-terminal-device.yang new file mode 100644 index 000000000..3b0714b55 --- /dev/null +++ b/models/yang/sonic/sonic-terminal-device.yang @@ -0,0 +1,182 @@ +module sonic-terminal-device { + namespace "http://github.com/Azure/sonic-terminal-device"; + prefix sonic-ter-dev; + + import sonic-extension { + prefix sonic-ext; + } + + organization + "SONiC"; + contact + "SONiC"; + description + "SONIC TERMINAL DEVICE"; + + revision 2024-07-03 { + description + "Initial revision."; + } + + container sonic-terminal-device { + container OCH { + sonic-ext:db-name "CONFIG_DB"; + description + "Enclosing container the list of optical channels"; + list OCH_LIST { + key "index"; + + leaf index { + type string; + description + "Index of the current logical channel"; + } + + leaf frequency { + type uint64; + units "MHz"; + description + "Frequency of the optical channel, expressed in MHz"; + } + + leaf target-output-power { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "Target output optical power level of the optical channel, + expressed in increments of 0.01 dBm (decibel-milliwats)"; + } + + leaf operational-mode { + type uint16; + description + "Vendor-specific mode identifier"; + } + } + } + container LOGICAL_CHANNEL { + sonic-ext:db-name "CONFIG_DB"; + description + "Enclosing container the list of logical channels"; + list LOGICAL_CHANNEL_LIST { + key "index"; + leaf test-signal { + type boolean; + description + "When enabled the logical channel's DSP will generate a pseudo + randmon bit stream (PRBS) which can be used during testing."; + } + leaf loopback-mode { + type string; + description + "Sets the loopback type on the logical channel. Setting the + mode to something besides NONE activates the loopback in + the specified mode."; + } + leaf admin-state { + type string; + description + "Sets the admin state of the logical channel"; + } + leaf index { + type string; + description + "Index of the current logical channel"; + } + leaf description { + type string; + description + "Description of the logical channel"; + } + } + } + container ETHERNET { + sonic-ext:db-name "CONFIG_DB"; + description + "Enclosing container the list of logical channels"; + list ETHERNET_LIST { + key "index"; + leaf index { + type string; + description + "Index of the current logical channel"; + } + leaf client-als { + type enumeration { + enum NONE { + description + "The client port will do nothing when a failure is + detected on the line port or the remote client port"; + } + enum LASER_SHUTDOWN { + description + "The client port will shut down the laser to notify the + subtending Ethernet equipment of the failure detected on + the line port or the remote client port."; + } + enum ETHERNET { + description + "The client port will propagate the local fault or remote + fault signal to the subtending Ethernet equipment."; + } + } + default ETHERNET; + description + "Sets the client port behavior that defines if the actions + of automatic laser shutdown (als), ethernet fault + propagation, or nothing will be done upon the detection + of a failure on the line port or the upstream remote + client port."; + } + + leaf als-delay { + type uint32; + units milliseconds; + default 0; + description + "The timer to delay the client-als actions on the client + port when a local or remote fault is detected on the line + port. The delay will only be valid when the client-als is + set to LASER_SHUTDOWN"; + } + + } + } + + container OTN { + sonic-ext:db-name "CONFIG_DB"; + description + "Enclosing container the list of logical channels"; + list OTN_LIST { + key "index"; + leaf index { + type string; + description + "Index of the current logical channel"; + } + leaf tti-msg-transmit { + type string; + description + "Trail trace identifier (TTI) message transmitted"; + } + + leaf tti-msg-expected { + type string; + description + "Trail trace identifier (TTI) message expected"; + } + + leaf tti-msg-auto { + type boolean; + description + "Trail trace identifier (TTI) transmit message automatically + created. If true, then setting a custom transmit message + would be invalid."; + } + } + } + + } +} diff --git a/models/yang/sonic/sonic-test-xfmr.yang b/models/yang/sonic/sonic-test-xfmr.yang new file mode 100644 index 000000000..df4751924 --- /dev/null +++ b/models/yang/sonic/sonic-test-xfmr.yang @@ -0,0 +1,344 @@ +module sonic-test-xfmr { + namespace "http://github.com/Azure/sonic-test-xfmr"; + prefix sonic-test-xfmr; + yang-version 1; + + import sonic-extension { prefix sonic-ext; } + + organization + "SONiC"; + + contact + "SONiC"; + + description + "SONIC transformer test yang"; + + revision 2023-04-30 { + description + "Initial revision of Sonic transformer test yang."; + } + + container sonic-test-xfmr { + + container TEST_SENSOR_GROUP { + + list TEST_SENSOR_GROUP_LIST { + key "id"; + + leaf id { + type string; + } + + leaf-list colors { + type string; + } + + leaf color-hold-time { + type uint32; + default 10; + description "Hold time"; + } + } + } + + container TEST_SENSOR_GROUP_COUNTERS { + config false; + + list TEST_SENSOR_GROUP_COUNTERS_LIST { + key "id"; + + leaf id { + type leafref { + path "../../../TEST_SENSOR_GROUP/TEST_SENSOR_GROUP_LIST/id"; + } + } + + leaf frame-in { + type uint32; + } + + leaf frame-out { + type uint32; + } + } + } + + container TEST_SENSOR_A_TABLE { + + list TEST_SENSOR_A_TABLE_LIST { + key "id type"; + + leaf id { + type leafref { + path "../../../TEST_SENSOR_GROUP/TEST_SENSOR_GROUP_LIST/id"; + } + } + + leaf type { + type string { + pattern "sensor_type_a_[a-zA-Z0-9]*"; + } + } + + leaf exclude_filter { + type string; + } + + leaf description_a { + type string; + } + } + } + + container TEST_SENSOR_A_LIGHT_SENSOR_TABLE { + + list TEST_SENSOR_A_LIGHT_SENSOR_TABLE_LIST { + key "id type tag"; + + leaf id { + type leafref { + path "../../../TEST_SENSOR_A_TABLE/TEST_SENSOR_A_TABLE_LIST/id"; + } + } + + leaf type { + type leafref { + path "../../../TEST_SENSOR_A_TABLE/TEST_SENSOR_A_TABLE_LIST/type"; + } + } + + leaf tag { + type string { + pattern "light_sensor_[0-9]*"; + } + } + + leaf light-intensity-measure { + type uint32; + default 5; + } + + } + } + + container TEST_SENSOR_B_TABLE { + + list TEST_SENSOR_B_TABLE_LIST { + key "id type"; + + leaf id { + type leafref { + path "../../../TEST_SENSOR_GROUP/TEST_SENSOR_GROUP_LIST/id"; + } + } + + leaf type { + type string { + pattern "sensor_type_b_[a-zA-Z0-9]*"; + } + } + + leaf exclude_filter { + type string; + } + + leaf description_b { + type string; + } + } + } + + container TEST_SENSOR_COMPONENT_TABLE { + + list TEST_SENSOR_COMPONENT_TABLE_LIST { + key "name type version"; + + leaf name { + type string; + } + + leaf type { + type string; + } + + leaf version { + type string; + } + + leaf description { + type string; + } + } + } + + container TEST_SENSOR_ZONE_TABLE { + list TEST_SENSOR_ZONE_TABLE_LIST { + key "id zone"; + + leaf id { + type string; + } + + leaf zone { + type string; + } + + leaf description { + type string; + } + } + } + + container TEST_SET_TABLE { + + list TEST_SET_TABLE_LIST { + key "name"; + + leaf name { + type string; + } + + leaf type { + type enumeration { + enum IPV4; + enum IPV6; + } + } + + leaf-list ports { + type string; + } + + leaf description { + type string; + } + + } + } + + container TEST_SENSOR_MODE_TABLE { + config false; + sonic-ext:db-name "COUNTERS_DB"; + list TEST_SENSOR_MODE_TABLE_LIST { + key "mode id"; + + leaf mode { + type string; + } + + leaf id { + type uint32; + } + + leaf description { + type string; + } + } + } + + container TEST_SENSOR_GLOBAL { + container global_sensor { + leaf mode { + type string; + } + leaf description { + type string; + } + leaf reset_time { + type uint32; + default 5; + } + } + container global_sensor_timer { + leaf timer_mode { + type string; + } + leaf timer_description { + type string; + } + leaf reset_time { + type uint32; + default 5; + } + } + list TEST_SENSOR_GLOBAL_LIST { + key "device_name device_id"; + leaf device_name { + type string; + } + leaf device_id { + type uint32; + } + leaf device_status { + type enumeration { + enum ON; + enum OFF; + } + } + + } + + } + + container TEST_INTERFACE_MODE_TABLE { + list TEST_INTERFACE_MODE_TABLE_LIST { + key "name"; + + leaf name { + type string; + } + leaf description { + type string; + } + } + list TEST_INTERFACE_MODE_TABLE_IPADDR_LIST { + key "name mode"; + + leaf name { + type string; + } + leaf mode { + type string; + } + leaf description { + type string; + } + } + } + + container TEST_CABLE_LENGTH { + + description "TEST_CABLE_LENGTH to test nested list yang support"; + + list TEST_CABLE_LENGTH_LIST { + key "name"; + + leaf name { + type string { + length 1..32 { + error-message "Invalid length for the cable length list name."; + error-app-tag cable-length-invalid-list-name-length; + } + } + } + list TEST_CABLE_LENGTH { + key "port"; + leaf port { + type leafref { + path "../../../../TEST_INTERFACE_MODE_TABLE/TEST_INTERFACE_MODE_TABLE_LIST/name"; + } + } + leaf length { + type string { + pattern '[0-9]+m' { + error-message "Invalid cable length."; + error-app-tag cable-length-invalid-length; + } + } + } + } + } + } + } +} diff --git a/models/yang/sonic/sonic-transport-line-protection.yang b/models/yang/sonic/sonic-transport-line-protection.yang new file mode 100644 index 000000000..6155f7b99 --- /dev/null +++ b/models/yang/sonic/sonic-transport-line-protection.yang @@ -0,0 +1,44 @@ +module sonic-transport-line-protection { + namespace "http://github.com/Azure/sonic-transport-line-protection"; + prefix sonic-tra-lin-pro; + + import sonic-extension { + prefix sonic-ext; + } + + organization + "SONiC"; + contact + "SONiC"; + description + "SONIC TRANSPORT LINE PROTECTION"; + + revision 2024-06-28 { + description + "Initial revision."; + } + + container sonic-transport-line-protection { + container APS { + description + "Enclosing container for list of automatic protection + switch modules"; + list APS_LIST { + key "name"; + leaf name { + type string; + description + "Reference to the component name (in the platform model) + corresponding to this automatic protection switch module + in the device"; + } + leaf force-to-port { + type string; + description + "Explicitly set the switch to stay on a port regardless of + its operational condition"; + } + } + } + } +} diff --git a/models/yang/sonic/sonic-wavelength-router.yang b/models/yang/sonic/sonic-wavelength-router.yang new file mode 100644 index 000000000..9b71ed4da --- /dev/null +++ b/models/yang/sonic/sonic-wavelength-router.yang @@ -0,0 +1,162 @@ +module sonic-wavelength-router { + namespace "http://github.com/Azure/sonic-wavelength-router"; + prefix sonic-wav-rou; + + import sonic-extension { + prefix sonic-ext; + } + + organization + "SONiC"; + contact + "SONiC"; + description + "SONIC WAVELENGTH ROUTER"; + + revision 2024-06-28 { + description + "Initial revision."; + } + + container sonic-wavelength-router { + container MEDIA_CHANNEL { + sonic-ext:db-name "CONFIG_DB"; + description + "Enclosing container for media channel list"; + list MEDIA_CHANNEL_LIST { + key "index"; + leaf lower-frequency { + type uint64; + units "MHz"; + description + "The lower frequency for the spectrum defined by this media + channel"; + } + leaf admin-status { + type string; + description + "Sets the admin status of the media channel"; + } + leaf super-channel-parent { + type uint32; + description + "If the media channel is contained within a super channel this + would specify the index of the super channel parent"; + } + leaf attenuation-control-mode { + type string; + description + "Sets the attenuation control mode for the media channel. + The control mode defines the behavior of how the attenuation + across a media channel is set"; + } + leaf index { + type uint32; + description + "Identifier for the defined media channel"; + } + leaf super-channel { + type boolean; + description + "True if the media channel is a super channel which + contains multiple media channels within it. The contained + media channels should fall within the boundaries of the + super channel. The device should raise an error if a media + channel crosses a super channel boundary. When using super + channels, spectrum power targets should be defined in either + the: + - port-spectrum-power-profiles for the port which matches the + source port of the media channel representing the super + channel + - media channels that are contained within the super + channel, but not on the super channel itself"; + } + leaf upper-frequency { + type uint64; + units "MHz"; + description + "The upper frequency for the spectrum defined by this media + channel"; + } + leaf attenuation-control-range { + type string; + description + "Sets the attenuation control range for the media channel. + The control range defines the amount of media channel + undershoot and overshoot compensation that will be applied + when performing power targeting to meet the defined output + port spectrum power profile"; + } + leaf name { + type string; + description + "The user supplied name of the media channel"; + } + leaf ase-control-mode { + type string; + description + "Sets the ASE control mode for the media channel. + The control mode defines if and when ASE noise is injected + on the media channel"; + } + + leaf ase-injection-threshold { + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "Defines the optical power threshold value below which ASE + noise should be injected on the media channel. This or + ase-injection-delta is required if an ase-control-mode is + configured"; + } + + leaf source-port-name { + type string; + description + "Reference to the corresponding node port"; + } + leaf dest-port-name { + type string; + description + "Reference to the corresponding node port"; + } + } + } + container MEDIA_CHANNEL_DISTRIBUTION { + description + "Enclosing container for the list of values describing + the target spectrum powers"; + list MEDIA_CHANNEL_DISTRIBUTION_LIST { + key "index lower-frequency upper-frequency"; + leaf index { + type uint32; + description + "Identifier for the defined media channel"; + } + leaf target-power { + type decimal64 { + fraction-digits 2; + } + units "dBm"; + description + "Target average power to achieve within the specified + spectrum"; + } + leaf lower-frequency { + type uint64; + units "MHz"; + description + "Lower frequency of the specified target spectrum power"; + } + leaf upper-frequency { + type uint64; + units "MHz"; + description + "Upper frequency of the specified target spectrum power"; + } + } + } + } +} diff --git a/translib/db/db_config_test.go b/translib/db/db_config_test.go new file mode 100644 index 000000000..8394ae4f7 --- /dev/null +++ b/translib/db/db_config_test.go @@ -0,0 +1,181 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + +package db + +import ( + "testing" +) + +var DatabaseValues = map[string]interface{}{ + "APPL_DB": map[string]interface{}{ + "id": 0, + "separator": ":", + "instance": "redis", + }, + "ASIC_DB": map[string]interface{}{ + "id": 1, + "separator": ":", + "instance": "redis", + }, + "COUNTERS_DB": map[string]interface{}{ + "id": 2, + "separator": ":", + "instance": "redis", + }, + "CONFIG_DB": map[string]interface{}{ + "id": 4, + "separator": "|", + "instance": "redis", + }, + "PFC_WD_DB": map[string]interface{}{ + "id": 5, + "separator": ":", + "instance": "redis", + }, + "FLEX_COUNTER_DB": map[string]interface{}{ + "id": 5, + "separator": ":", + "instance": "redis", + }, + "STATE_DB": map[string]interface{}{ + "id": 6, + "separator": "|", + "instance": "redis", + }, + "SNMP_OVERLAY_DB": map[string]interface{}{ + "id": 7, + "separator": "|", + "instance": "redis", + }, +} + +var requiredDBs = []string{"APPL_DB", "ASIC_DB", "CONFIG_DB", "STATE_DB"} + +func TestDbConfigInit(t *testing.T) { + dbConfigInit("/var/run/redis/sonic-db/database_config.json", hostDBName) + for _, requiredDB := range requiredDBs { + if _, ok := multiDbsConfigMap["host"]["DATABASES"].(map[string]interface{})[requiredDB]; !ok { + //dbinstance check + t.Error("Error in DbConfigInit") + } + } +} + +func TestGetDbList(t *testing.T) { + for _, dbName := range GetMultiDbNames() { + t.Run("GetDbList of "+dbName, func(t *testing.T) { + dbEntries := getDbList(dbName) + for _, requiredDB := range requiredDBs { + if _, ok := dbEntries[requiredDB]; !ok { + //dbinstance check + t.Errorf("Error in GetDBList of %s for database %s", requiredDB, dbName) + } + } + }) + } +} + +func TestGetFunctions(t *testing.T) { + + for _, dbName := range GetMultiDbNames() { + for _, requiredDB := range requiredDBs { + t.Run("GetDbInstance of "+dbName, func(t *testing.T) { + requiredDB = requiredDB + "." + dbName + dbInstance := getDbInst(requiredDB) + if _, ok := dbInstance["hostname"]; !ok { + t.Errorf("Error in GetDbInstance of %s for database %s", requiredDB, dbName) + } + }) + t.Run("GetDbSeperator of "+dbName, func(t *testing.T) { + dbSeperator := getDbSeparator(requiredDB) + dbName, _ := getDBNames(requiredDB) + if dbSeperator != DatabaseValues[dbName].(map[string]interface{})["separator"] { + t.Errorf("Error in dbSeperator in database %s", dbName) + } + + }) + t.Run("GetDbId of "+dbName, func(t *testing.T) { + dbInt := getDbId(requiredDB) + dbName, _ := getDBNames(requiredDB) + if dbInt != DatabaseValues[dbName].(map[string]interface{})["id"] { + t.Errorf("Error in dbInt in database %s", dbName) + } + + }) + t.Run("GetHostName of "+dbName, func(t *testing.T) { + hostName := getDbHostName(requiredDB) + if hostName == "" { + t.Errorf("Error in hostname in database %s", dbName) + } + }) + t.Run("GetDbPort of "+dbName, func(t *testing.T) { + DbPort := getDbPort(requiredDB) + if DbPort <= 0 { + t.Errorf("Error in GetDbPort in database %s", dbName) + } + }) + t.Run("GetTcpAddr of "+dbName, func(t *testing.T) { + tcpAddr := getDbTcpAddr(requiredDB) + if tcpAddr == "" { + t.Errorf("Error in GetTcpAddr in database %s", dbName) + } + }) + t.Run("GetDbSock of "+dbName, func(t *testing.T) { + Dbsock := getDbSock(requiredDB) + switch dbName { + case "host": + t.Run("HostConnection", func(t *testing.T) { + //Redis + if Dbsock != "/var/run/redis/redis.sock" { + t.Error("GetDbSock fails in host connection") + } + }) + case "asic0": + t.Run("Asic0Connection", func(t *testing.T) { + if Dbsock != "/var/run/redis0/redis.sock" { + t.Error("GetDbSock fails in asic0 connection") + } + }) + case "asic1": + t.Run("Asic1Connection", func(t *testing.T) { + if Dbsock != "/var/run/redis1/redis.sock" { + t.Error("GetDbSock fails in asic1 connection") + } + }) + case "asic2": + t.Run("Asic2Connection", func(t *testing.T) { + if Dbsock != "/var/run/redis2/redis.sock" { + t.Error("GetDbSock fails in asic2 connection") + } + }) + case "asic3": + t.Run("Asic3Connection", func(t *testing.T) { + if Dbsock != "/var/run/redis3/redis.sock" { + t.Error("GetDbSock fails in asic3 connection") + } + }) + default: + t.Errorf("Unexpected database name: %s", dbName) + } + + }) + } + } +} diff --git a/translib/db/db_util.go b/translib/db/db_util.go new file mode 100644 index 000000000..aa1043c2a --- /dev/null +++ b/translib/db/db_util.go @@ -0,0 +1,132 @@ +package db + +import ( + "bufio" + "github.com/golang/glog" + "os" + "strconv" + "strings" +) + +const ( + DEFAULT_KEY_SEPERATOR = "-" +) + +func isMultiAsic() bool { + return NumAsic > 0 +} + +func getNumAsic() int { + file, err := os.Open(DefaultAsicConfFilePath) + if err != nil { + glog.Warning("Cannot find the asic.conf file, set num_asic to 1 by default") + return 1 + } + + defer file.Close() + + scanner := bufio.NewScanner(file) + scanner.Split(bufio.ScanLines) + var text []string + for scanner.Scan() { + text = append(text, scanner.Text()) + } + + var numAsics = 1 + for _, line := range text { + tokens := strings.Split(line, "=") + if len(tokens) != 2 { + continue + } + + if strings.ToLower(tokens[0]) == "num_asic" { + num, err := strconv.Atoi(tokens[1]) + if err != nil { + glog.Warning("invalid line in asic.config") + continue + } + numAsics = num + } + } + + return numAsics +} + +// Function to fetch dbName from dbConfigMap +func fetchDbNameFromGlobalJson() string { + var dbName string + for key := range multiDbsConfigMap { + if key != "host" { + dbName = key[:len(key)-1] + break + } + } + return dbName +} + +func GetMultiDbNames() []string { + dbNames := []string{"host"} + cmnDbName := fetchDbNameFromGlobalJson() + if isMultiAsic() { + for num := 0; num < NumAsic; num++ { + dbNames = append(dbNames, cmnDbName+strconv.Itoa(num)) + } + } + return dbNames +} + +func getDbNameBySlotNum(slotNum int) string { + if NumAsic == 1 || slotNum > NumAsic || slotNum < 1 { + return "host" + } + cmnDbName := fetchDbNameFromGlobalJson() + + return cmnDbName + strconv.Itoa(slotNum-1) +} + +func GetKeySeperatorFromGlobalJson() string { + if GlobalKeySeperator == "" { + GlobalKeySeperator = DEFAULT_KEY_SEPERATOR + } + glog.Info("GlobalKeySeperator:", GlobalKeySeperator) + return GlobalKeySeperator +} + +func GetMDBNameFromEntity(entity interface{}) string { + var slotNum int + var slotNumStr string + + keySeperator := GetKeySeperatorFromGlobalJson() + + switch t := entity.(type) { + case uint16: + valUint16, _ := entity.(uint16) + slotNum = int(valUint16 / 100) + case uint32: + // ch115 + valUint32, _ := entity.(uint32) + slotNum = int(valUint32 / 100) + case string: + valString, _ := entity.(string) + elmts := strings.Split(valString, keySeperator) + if len(elmts) == 2 && elmts[0] == "SLOT" { + // used for reboot entity-name + slotNumStr = elmts[1] + } else if len(elmts) >= 3 { + slotNumStr = elmts[2] + } else { + goto error + } + + tmp, err := strconv.ParseInt(slotNumStr, 10, 64) + if err != nil { + goto error + } + slotNum = int(tmp) + default: + glog.Errorf("unexpected type %T", t) + } + +error: + return getDbNameBySlotNum(slotNum) +} diff --git a/translib/transformer/xfmr_aps.go b/translib/transformer/xfmr_aps.go new file mode 100644 index 000000000..682745eaa --- /dev/null +++ b/translib/transformer/xfmr_aps.go @@ -0,0 +1,500 @@ +package transformer + +import ( + "encoding/json" + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "github.com/Azure/sonic-mgmt-common/translib/ocbinds" + log "github.com/golang/glog" + "github.com/openconfig/ygot/ygot" + "reflect" + "strings" +) + +const APS_INTERVAL_CURRENT_VAL = "15_pm_current" + +func init() { + + /* Key transformer for APS table*/ + XlateFuncBind("YangToDb_aps_name_key_xfmr", YangToDb_aps_name_key_xfmr) + XlateFuncBind("DbToYang_aps_name_key_xfmr", DbToYang_aps_name_key_xfmr) + + /* Field transformer for APS table*/ + XlateFuncBind("YangToDb_aps_name_field_xfmr", YangToDb_aps_name_field_xfmr) + XlateFuncBind("DbToYang_aps_name_field_xfmr", DbToYang_aps_name_field_xfmr) + + // Override the existing function with the new implementation + // Uncomment the below line to override the existing GetNamespaceFunc + // aps_name_get_namespace_xfmr = customApsGetNamespaceFunc + + /* Get Namespace transformer for APS table*/ + XlateFuncBind("aps_name_get_namespace_xfmr", aps_name_get_namespace_xfmr) + + /* Key transformer for APS_PORT table*/ + XlateFuncBind("YangToDb_aps_port_commonIn_key_xfmr", YangToDb_aps_port_commonIn_key_xfmr) + XlateFuncBind("DbToYang_aps_port_commonIn_key_xfmr", DbToYang_aps_port_commonIn_key_xfmr) + XlateFuncBind("YangToDb_aps_port_commonOut_key_xfmr", YangToDb_aps_port_commonOut_key_xfmr) + XlateFuncBind("DbToYang_aps_port_commonOut_key_xfmr", DbToYang_aps_port_commonOut_key_xfmr) + XlateFuncBind("YangToDb_aps_port_LinePrimaryIn_key_xfmr", YangToDb_aps_port_LinePrimaryIn_key_xfmr) + XlateFuncBind("DbToYang_aps_port_LinePrimaryIn_key_xfmr", DbToYang_aps_port_LinePrimaryIn_key_xfmr) + XlateFuncBind("YangToDb_aps_port_LinePrimaryOut_key_xfmr", YangToDb_aps_port_LinePrimaryOut_key_xfmr) + XlateFuncBind("DbToYang_aps_port_LinePrimaryOut_key_xfmr", DbToYang_aps_port_LinePrimaryOut_key_xfmr) + XlateFuncBind("YangToDb_aps_port_lineSecondaryIn_key_xfmr", YangToDb_aps_port_lineSecondaryIn_key_xfmr) + XlateFuncBind("DbToYang_aps_port_lineSecondaryIn_key_xfmr", DbToYang_aps_port_lineSecondaryIn_key_xfmr) + XlateFuncBind("YangToDb_aps_port_lineSecondaryOut_key_xfmr", YangToDb_aps_port_lineSecondaryOut_key_xfmr) + XlateFuncBind("DbToYang_aps_port_lineSecondaryOut_key_xfmr", DbToYang_aps_port_lineSecondaryOut_key_xfmr) + + /* Key transformer for APS_PORT Counter table*/ + XlateFuncBind("YangToDb_aps_counter_commonIn_key_xfmr", YangToDb_aps_counter_commonIn_key_xfmr) + XlateFuncBind("DbToYang_aps_counter_commonIn_key_xfmr", DbToYang_aps_counter_commonIn_key_xfmr) + XlateFuncBind("YangToDb_aps_counter_commonOut_key_xfmr", YangToDb_aps_counter_commonOut_key_xfmr) + XlateFuncBind("DbToYang_aps_counter_commonOut_key_xfmr", DbToYang_aps_counter_commonOut_key_xfmr) + XlateFuncBind("YangToDb_aps_counter_linePrimaryIn_key_xfmr", YangToDb_aps_counter_linePrimaryIn_key_xfmr) + XlateFuncBind("DbToYang_aps_counter_linePrimaryIn_key_xfmr", DbToYang_aps_counter_linePrimaryIn_key_xfmr) + XlateFuncBind("YangToDb_aps_counter_linePrimaryOut_key_xfmr", YangToDb_aps_counter_linePrimaryOut_key_xfmr) + XlateFuncBind("DbToYang_aps_counter_linePrimaryOut_key_xfmr", DbToYang_aps_counter_linePrimaryOut_key_xfmr) + XlateFuncBind("YangToDb_aps_counter_lineSecondaryIn_key_xfmr", YangToDb_aps_counter_lineSecondaryIn_key_xfmr) + XlateFuncBind("DbToYang_aps_counter_lineSecondaryIn_key_xfmr", DbToYang_aps_counter_lineSecondaryIn_key_xfmr) + XlateFuncBind("YangToDb_aps_counter_lineSecondaryOut_key_xfmr", YangToDb_aps_counter_lineSecondaryOut_key_xfmr) + XlateFuncBind("DbToYang_aps_counter_lineSecondaryOut__key_xfmr", DbToYang_aps_counter_lineSecondaryOut__key_xfmr) + +} + +var YangToDb_aps_name_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_aps_name_key_xfmr root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("name") + log.V(3).Infof("YangToDb_aps_name_key_xfmr : key", key) + + return key, nil +} + +var DbToYang_aps_name_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_aps_name_key_xfmr: ", inParams.key) + rmap, err := apsNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_aps_name_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_aps_name_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + rmap["name"] = inParams.key + + return rmap, nil +} + +var YangToDb_aps_port_commonIn_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_aps_port_commonIn_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("name") + apsPortKey := key + "_CommonIn" + + return apsPortKey, nil +} + +var DbToYang_aps_port_commonIn_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_aps_port_commonIn_key_xfmr: ", inParams.key) + rmap, err := apsNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_aps_port_commonOut_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_aps_port_commonOut_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("name") + apsPortKey := key + "_CommonOut" + + return apsPortKey, nil +} + +var DbToYang_aps_port_commonOut_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_aps_port_commonOut_key_xfmr: ", inParams.key) + rmap, err := apsNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_aps_port_LinePrimaryIn_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_aps_port_LinePrimaryIn_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("name") + apsPortKey := key + "_LinePrimaryIn" + + return apsPortKey, nil +} + +var DbToYang_aps_port_LinePrimaryIn_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_aps_port_LinePrimaryIn_key_xfmr: ", inParams.key) + rmap, err := apsNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_aps_port_LinePrimaryOut_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_aps_port_LinePrimaryOut_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("name") + apsPortKey := key + "_LinePrimaryOut" + + return apsPortKey, nil +} + +var DbToYang_aps_port_LinePrimaryOut_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_aps_port_LinePrimaryOut_key_xfmr: ", inParams.key) + rmap, err := apsNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_aps_port_lineSecondaryIn_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_aps_port_lineSecondaryIn_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("name") + apsPortKey := key + "_LineSecondaryIn" + + return apsPortKey, nil +} + +var DbToYang_aps_port_lineSecondaryIn_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_aps_port_lineSecondaryIn_key_xfmr: ", inParams.key) + rmap, err := apsNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_aps_port_lineSecondaryOut_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_aps_port_lineSecondaryOut_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("name") + apsPortKey := key + "_LineSecondaryOut" + + return apsPortKey, nil +} + +var DbToYang_aps_port_lineSecondaryOut_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_aps_port_lineSecondaryOut_key_xfmr: ", inParams.key) + rmap, err := apsNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_aps_counter_commonIn_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_aps_counter_commonIn_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + apskey := pathInfo.Var("name") + apsCounterKey := apskey + "_CommonIn_OpticalPower:" + APS_INTERVAL_CURRENT_VAL + + return apsCounterKey, nil +} + +var DbToYang_aps_counter_commonIn_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_aps_counter_commonIn_key_xfmr: ", inParams.key) + rmap, err := apsNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_aps_counter_commonOut_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_aps_counter_commonOut_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + apskey := pathInfo.Var("name") + apsCounterKey := apskey + "_CommonOutput_OpticalPower:" + APS_INTERVAL_CURRENT_VAL + + return apsCounterKey, nil +} + +var DbToYang_aps_counter_commonOut_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_aps_counter_commonOut_key_xfmr: ", inParams.key) + rmap, err := apsNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_aps_counter_linePrimaryIn_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_aps_counter_linePrimaryIn_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + apskey := pathInfo.Var("name") + apsCounterKey := apskey + "_LinePrimaryIn_OpticalPower:" + APS_INTERVAL_CURRENT_VAL + + return apsCounterKey, nil +} + +var DbToYang_aps_counter_linePrimaryIn_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_aps_counter_linePrimaryIn_key_xfmr: ", inParams.key) + rmap, err := apsNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_aps_counter_linePrimaryOut_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_aps_counter_linePrimaryOut_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + apskey := pathInfo.Var("name") + apsCounterKey := apskey + "_LinePrimaryOut_OpticalPower:" + APS_INTERVAL_CURRENT_VAL + + return apsCounterKey, nil +} + +var DbToYang_aps_counter_linePrimaryOut_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_aps_counter_linePrimaryOut_key_xfmr: ", inParams.key) + rmap, err := apsNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_aps_counter_lineSecondaryIn_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_aps_counter_lineSecondaryIn_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + apskey := pathInfo.Var("name") + apsCounterKey := apskey + "_LineSecondaryIn_OpticalPower:" + APS_INTERVAL_CURRENT_VAL + + return apsCounterKey, nil +} + +var DbToYang_aps_counter_lineSecondaryIn_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_aps_counter_lineSecondaryIn_key_xfmr: ", inParams.key) + rmap, err := apsNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_aps_counter_lineSecondaryOut_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_aps_counter_lineSecondaryOut_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + apskey := pathInfo.Var("name") + apsCounterKey := apskey + "_LineSecondaryOut_OpticalPower:" + APS_INTERVAL_CURRENT_VAL + + return apsCounterKey, nil +} + +var DbToYang_aps_counter_lineSecondaryOut__key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_aps_counter_lineSecondaryOut_key_xfmr: ", inParams.key) + rmap, err := apsNameKeyDbToYang(inParams) + + return rmap, err +} + +func getApsRootObj(s *ygot.GoStruct) *ocbinds.OpenconfigTransportLineProtection_Aps { + deviceObj := (*s).(*ocbinds.Device) + return deviceObj.Aps +} + +func apsNameKeyDbToYang(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + log.V(3).Info("apsNameKeyDbToYang : ", inParams.key) + + TableKeys := strings.Split(inParams.key, "_") + rmap["name"] = TableKeys[0] + log.V(3).Info("apsNameKeyDbToYang : rmap", rmap) + + return rmap, nil +} + +// Define a new implementation for GetNamespaceFunc +func customApsGetNamespaceFunc(inParams XfmrParams) ([]NamespacePayload, error) { + + // Your custom implementation here + nameSpaceList, err := aps_name_get_namespace_xfmr(inParams) + + return nameSpaceList, err +} + +var aps_name_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]NamespacePayload, error) { + + // Struct to hold payload and associated key + type payloadWithKey struct { + payload map[string]interface{} + key string + } + var key string + + // Updated map to hold list of payload+key per namespace + var nsPayloadMap = make(map[string][]payloadWithKey) + + log.Infof("aps_name_get_namespace_xfmr: inParams: %v", inParams) + + pathInfo := NewPathInfo(inParams.uri) + key = pathInfo.Var("name") + log.Infof("aps_name_get_namespace_xfmr: key: %v", key) + + if len(key) > 0 { + dbName := db.GetMDBNameFromEntity(key) + log.Infof("aps_name_get_namespace_xfmr: dbName: %v", dbName) + + var raw map[string]interface{} + var payloads []map[string]interface{} + + if inParams.body != nil && len(inParams.body) > 0 { + if err := json.Unmarshal(inParams.body, &raw); err != nil { + log.Warning("Failed during unmarshal the userPayload: %v", err) + return nil, err + } + payloads = append(payloads, raw) + log.Infof("appending raw to the payloads %v", payloads) + } else { + payloads = []map[string]interface{}{} + } + log.Infof("based on the key return %v=dbName %v=key", dbName, key) + return []NamespacePayload{ + { + Namespace: dbName, + Payloads: payloads, + Key: key, + }, + }, nil + } + + var containerPrefix string + if inParams.body != nil { + bodyStr := string(inParams.body) + idx := strings.Index(bodyStr, "[") + if idx != -1 { + containerPrefix = bodyStr[:idx] + containerPrefix = strings.TrimRight(containerPrefix, ": \t\r\n") + } + } + + if inParams.ygRoot != nil { + aps := getApsRootObj(inParams.ygRoot) + + printPayloads := func(entities interface{}) { + val := reflect.ValueOf(entities) + if val.Kind() != reflect.Map { + log.Info("entities is not a map") + return + } + + for _, key := range val.MapKeys() { + entity := val.MapIndex(key).Interface() + dbName := db.GetMDBNameFromEntity(key.String()) + + ygotStruct, ok := entity.(ygot.ValidatedGoStruct) + if !ok { + log.Errorf("Entity does not implement ygot.ValidatedGoStruct") + continue + } + + entityJson, err := ygot.EmitJSON(ygotStruct, &ygot.EmitJSONConfig{ + Format: ygot.RFC7951, + Indent: "", + SkipValidation: true, + }) + if err != nil { + log.Errorf("Failed to marshal entity with ygot.EmitJSON: %v", err) + continue + } + openBraces := strings.Count(containerPrefix, "{") + finalJson := fmt.Sprintf("%s:[%s]%s", containerPrefix, string(entityJson), strings.Repeat("}", openBraces)) + log.Errorf("reconstructed payload: %v", finalJson) + + var finalMap map[string]interface{} + if err := json.Unmarshal([]byte(finalJson), &finalMap); err != nil { + log.Errorf("Failed to unmarshal reconstructed payload: %v", err) + continue + } + + nsPayloadMap[dbName] = append(nsPayloadMap[dbName], payloadWithKey{ + payload: finalMap, + key: key.String(), + }) + + if outStr, err := json.MarshalIndent(finalMap, "", " "); err == nil { + log.Infof("Namespace: %s\nWrapped Output:\n%s", dbName, string(outStr)) + } + } + } + + if aps.ApsModules.ApsModule != nil { + printPayloads(aps.ApsModules.ApsModule) + } + } + // If no payloads found, use wildcard namespace + if len(nsPayloadMap) == 0 { + log.Infof("No specific key found, using '*' to include all DBs.") + return []NamespacePayload{ + { + Namespace: "*", + Payloads: []map[string]interface{}{}, + Key: "*", + }, + }, nil + } + + // Construct final result + var result []NamespacePayload + for ns, pwkList := range nsPayloadMap { + for _, pwk := range pwkList { + result = append(result, NamespacePayload{ + Namespace: ns, //asic0 + Payloads: []map[string]interface{}{pwk.payload}, //payload from payloadWithKey struct + Key: pwk.key, // key from payloadWithkey struct + Commited: false, // commited flag as a false + }) + } + } + + return result, nil +} diff --git a/translib/transformer/xfmr_aps_test.go b/translib/transformer/xfmr_aps_test.go new file mode 100644 index 000000000..aae32c999 --- /dev/null +++ b/translib/transformer/xfmr_aps_test.go @@ -0,0 +1,244 @@ +//go:build xfmrtest +// +build xfmrtest + +package transformer_test + +import ( + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "testing" + "time" +) + +/* APS config,counters, state DB fields and values */ +func Test_aps_config_state_counter_DB_key(t *testing.T) { + var pre_req_map, cleanuptbl, cleanupstatetbl, cleanupcountertbl map[string]interface{} + var expected_get_json, url []string + + for idx, dbName := range getMdbNames() { + /* APS Config DB test */ + t.Log("\n\n+++++++++++++ Performing Get on configDB APS Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "APS": map[string]interface{}{ + fmt.Sprintf("APS-1-%d-2", idx+1): map[string]interface{}{ + "force-to-port": "PRIMARY", + }, + }, + } + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_get_json = []string{fmt.Sprintf("{\"openconfig-transport-line-protection:config\":{\"force-to-port\":\"PRIMARY\",\"name\":\"APS-1-%d-2\"}}", idx+1)} + url = []string{fmt.Sprintf("/openconfig-transport-line-protection:aps/aps-modules/aps-module[name=APS-1-%d-2]/config", idx+1)} + + t.Run("Test get on configDB APS Key", processGetRequest(url[0], nil, expected_get_json[0], false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on configDB APS Key ++++++++++++") + + /* APS and APS_PORT State DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB APS Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "APS_TABLE": map[string]interface{}{ + fmt.Sprintf("APS-1-%d-2", idx+1): map[string]interface{}{ + "revertive": true, + "wait-to-restore-time": 10, + "hold-off-time": 5, + "primary-switch-threshold": 1.5, + "primary-switch-hysteresis": 3.5, + "secondary-switch-threshold": 2.4, + "relative-switch-threshold": 4.5, + "relative-switch-threshold-offset": 6.7, + "force-to-port": "NONE", + "active-path": "PRIMARY", + }, + }, + "APS_PORT_TABLE": map[string]interface{}{ + fmt.Sprintf("APS-1-%d-2_CommonIn", idx+1): map[string]interface{}{ + "enabled": true, + "target-attenuation": 6.1, + "attenuation": 10.5, + }, + }, + } + loadDB(dbName, db.StateDB, pre_req_map) + expected_get_json = []string{ + fmt.Sprintf("{\"openconfig-transport-line-protection:state\":{\"active-path\":\"openconfig-transport-line-protection:PRIMARY\",\"force-to-port\":\"NONE\",\"hold-off-time\":5,\"name\":\"APS-1-%d-2\",\"primary-switch-hysteresis\":\"3.5\",\"primary-switch-threshold\":\"1.5\",\"relative-switch-threshold\":\"4.5\",\"relative-switch-threshold-offset\":\"6.7\",\"revertive\":true,\"secondary-switch-threshold\":\"2.4\",\"wait-to-restore-time\":10}}", idx+1), + "{\"openconfig-transport-line-protection:state\":{\"attenuation\":\"10.5\",\"enabled\":true,\"target-attenuation\":\"6.1\"}}", + } + url = []string{ + fmt.Sprintf("/openconfig-transport-line-protection:aps/aps-modules/aps-module[name=APS-1-%d-2]/state", idx+1), + fmt.Sprintf("/openconfig-transport-line-protection:aps/aps-modules/aps-module[name=APS-1-%d-2]/ports/common-in/state", idx+1), + } + + for idx, url := range url { + t.Run("Test get on state DB Key for "+url, processGetRequest(url, nil, expected_get_json[idx], false)) + time.Sleep(1 * time.Second) + } + t.Log("\n\n+++++++++++++ Done Performing Get on stateDB APS Key ++++++++++++") + + /* APS_PORT Counters DB test */ + t.Log("\n\n+++++++++++++ Performing Get on countersDB APS Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "APS_PORT": map[string]interface{}{ + fmt.Sprintf("APS-1-%d-2_CommonIn_OpticalPower:15_pm_current", idx+1): map[string]interface{}{ + "instant": "0.55", + "min-time": "1680134400477338361", + "min": "0.55", + "max": "0.6", + "interval": "86400000000000", + "validity": "incomplete", + "starttime": "1680134400000000000", + "max-time": "1680136923116487196", + "current_validity": "complete", + "avg": "0.55", + }, + }, + } + loadDB(dbName, db.CountersDB, pre_req_map) + expected_get_json = []string{"{\"openconfig-transport-line-protection:optical-power\":{\"avg\":\"0.55\",\"instant\":\"0.55\",\"interval\":\"86400000000000\",\"max\":\"0.6\",\"max-time\":\"1680136923116487196\",\"min\":\"0.55\",\"min-time\":\"1680134400477338361\"}}"} + url = []string{fmt.Sprintf("/openconfig-transport-line-protection:aps/aps-modules/aps-module[name=APS-1-%d-2]/ports/common-in/state/optical-power", idx+1)} + + t.Run("Test get on countersDB APS Key", processGetRequest(url[0], nil, expected_get_json[0], false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on countersDB APS Key ++++++++++++") + + /* Unload the data */ + cleanuptbl = map[string]interface{}{ + "APS": map[string]interface{}{ + fmt.Sprintf("APS-1-%d-2", idx+1): "", + }, + } + unloadDB(dbName, db.ConfigDB, cleanuptbl) + + cleanupstatetbl = map[string]interface{}{ + "APS_TABLE": map[string]interface{}{fmt.Sprintf("APS-1-%d-2", idx+1): ""}, + "APS_PORT_TABLE": map[string]interface{}{fmt.Sprintf("APS-1-%d-2_CommonIn", idx+1): ""}, + } + unloadDB(dbName, db.StateDB, cleanupstatetbl) + + cleanupcountertbl = map[string]interface{}{ + "APS_PORT": map[string]interface{}{ + fmt.Sprintf("APS-1-%d-2_CommonIn_OpticalPower:15_pm_current", idx+1): "", + }, + } + unloadDB(dbName, db.CountersDB, cleanupcountertbl) + } +} + +func Test_set_aps_config_DB_key_and_field_xfmr(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing Create/Replace/Delete on aps ++++++++++++") + + for idx, dbName := range getMdbNames() { + url := fmt.Sprintf("/openconfig-transport-line-protection:aps/aps-modules/aps-module[name=APS-1-%d-2]/config", idx+1) + url_body_json := "{\"config\": {\"force-to-port\": \"SECONDARY\"}}" + + pre_req_map := map[string]interface{}{ + "APS": map[string]interface{}{ + fmt.Sprintf("APS-1-%d-2", idx+1): map[string]interface{}{ + "force-to-port": "PRIMARY", + }, + }, + } + + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_map := map[string]interface{}{ + "APS": map[string]interface{}{ + fmt.Sprintf("APS-1-%d-2", idx+1): map[string]interface{}{ + "force-to-port": "SECONDARY", + }, + }, + } + + time.Sleep(1 * time.Second) + + //PUT Test + t.Run("Replace Test on APS yang", processSetRequest(url, url_body_json, "PUT", false)) + time.Sleep(1 * time.Second) + + //GET Test + t.Run("Verify replace on APS yang", verifyDbResult(rclient[dbName], fmt.Sprintf("APS|APS-1-%d-2", idx+1), expected_map, false)) + time.Sleep(1 * time.Second) + + //Delete Test + url = fmt.Sprintf("/openconfig-transport-line-protection:aps/aps-modules/aps-module[name=APS-1-%d-2]", idx+1) + t.Run("DELETE Test on APS yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + //POST Test + url = "/openconfig-transport-line-protection:aps/aps-modules" + post_payload := fmt.Sprintf("{\"aps-module\":[{\"name\":\"APS-1-%d-13\",\"config\": {\"force-to-port\": \"SECONDARY\"}}]}", idx+1) + t.Run("Create test on APS yang", processSetRequest(url, post_payload, "POST", false)) + time.Sleep(1 * time.Second) + + expected_map = map[string]interface{}{ + "APS": map[string]interface{}{ + fmt.Sprintf("APS-1-%d-13", idx+1): map[string]interface{}{ + "force-to-port": "SECONDARY", + }, + }, + } + + //Verify After the POST test + t.Run("Verify After the POST test on APS yang", verifyDbResult(rclient[dbName], fmt.Sprintf("APS|APS-1-%d-13", idx+1), expected_map, false)) + + //Delete After the POST test + url = fmt.Sprintf("/openconfig-transport-line-protection:aps/aps-modules/aps-module[name=APS-1-%d-13]", idx+1) + t.Run("DELETE After the POST test on APS yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = "/openconfig-transport-line-protection:aps/aps-modules" + + //Bulk POST Test + Bulk_post_payload := fmt.Sprintf("{\"aps-module\":[{\"name\":\"APS-1-%d-14\",\"config\": {\"force-to-port\": \"PRIMARY\"}},{\"name\":\"APS-1-%d-15\",\"config\": {\"force-to-port\": \"SECONDARY\"}}]}", idx+1, idx+1) + t.Run("Create test on APS yang", processSetRequest(url, Bulk_post_payload, "POST", false)) + + expected_map = map[string]interface{}{ + "APS": map[string]interface{}{ + fmt.Sprintf("APS-1-%d-14", idx+1): map[string]interface{}{ + "force-to-port": "PRIMARY", + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the Bulk test + t.Run("Verify After the Bulk test on APS yang", verifyDbResult(rclient[dbName], fmt.Sprintf("APS|APS-1-%d-14", idx+1), expected_map, false)) + + expected_map = map[string]interface{}{ + "APS": map[string]interface{}{ + fmt.Sprintf("APS-1-%d-15", idx+1): map[string]interface{}{ + "force-to-port": "SECONDARY", + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the POST test + t.Run("Verify After the Bulk test on APS yang", verifyDbResult(rclient[dbName], fmt.Sprintf("APS|APS-1-%d-15", idx+1), expected_map, false)) + + //Delete keys After the Bulk Test + url = fmt.Sprintf("/openconfig-transport-line-protection:aps/aps-modules/aps-module[name=APS-1-%d-14]", idx+1) + t.Run("DELETE After the Bulk Test on APS yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = fmt.Sprintf("/openconfig-transport-line-protection:aps/aps-modules/aps-module[name=APS-1-%d-15]", idx+1) + t.Run("DELETE After the Bulk Test on APS yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + } + t.Log("\n\n+++++++++++++ Done Performing Create/Replace/Delete on APS ++++++++++++") +} + +func Test_aps_allow_write_multiple_namespace(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing aps write for multiple namespace (should be allowed) ++++++++++++") + + url := "/openconfig-transport-line-protection:aps/aps-modules" + url_body_json := `{ + "aps-module": [ + {"name": "APS-1-1-4", "config": {"force-to-port": "PRIMARY"}}, + {"name": "APS-1-2-5", "config": {"force-to-port": "SECONDARY"}} + ] + }` + + // false = no error expected + t.Run("Test allow writing multiple namespace for aps", processSetRequest(url, url_body_json, "POST", false, nil)) + + t.Log("\n\n+++++++++++++ Done Performing aps write for multiple namespace ++++++++++++") +} diff --git a/translib/transformer/xfmr_atten.go b/translib/transformer/xfmr_atten.go new file mode 100644 index 000000000..aed1c1c2d --- /dev/null +++ b/translib/transformer/xfmr_atten.go @@ -0,0 +1,303 @@ +package transformer + +import ( + "encoding/json" + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "github.com/Azure/sonic-mgmt-common/translib/ocbinds" + "github.com/openconfig/ygot/ygot" + "reflect" + "strings" + + log "github.com/golang/glog" +) + +const ATTEN_INTERVAL_CURRENT_VAL = "15_pm_current" + +func init() { + + /* Key transformer for ATTENUATOR table*/ + XlateFuncBind("YangToDb_attn_name_key_xfmr", YangToDb_attn_name_key_xfmr) + XlateFuncBind("DbToYang_attn_name_key_xfmr", DbToYang_attn_name_key_xfmr) + + /* Field transformer for ATTENUATOR table*/ + XlateFuncBind("YangToDb_attn_name_field_xfmr", YangToDb_attn_name_field_xfmr) + XlateFuncBind("DbToYang_attn_name_field_xfmr", DbToYang_attn_name_field_xfmr) + + // Override the existing function with the new implementation + // Uncomment the below line to override the existing GetNamespaceFunc + // attn_name_get_namespace_xfmr = customAttenGetNamespaceFunc + + /* Get Namespace transformer for ATTENUATOR table*/ + XlateFuncBind("attn_name_get_namespace_xfmr", attn_name_get_namespace_xfmr) + + /* Key transformer for ATTENUATOR Counter table*/ + XlateFuncBind("YangToDb_attn_actual_attenuation_key_xfmr", YangToDb_attn_actual_attenuation_key_xfmr) + XlateFuncBind("DbToYang_attn_actual_attenuation_key_xfmr", DbToYang_attn_actual_attenuation_key_xfmr) + XlateFuncBind("YangToDb_attn_optical_return_loss_key_xfmr", YangToDb_attn_optical_return_loss_key_xfmr) + XlateFuncBind("DbToYang_attn_optical_return_loss_key_xfmr", DbToYang_attn_optical_return_loss_key_xfmr) + XlateFuncBind("YangToDb_attn_output_power_total_key_xfmr", YangToDb_attn_output_power_total_key_xfmr) + XlateFuncBind("DbToYang_attn_output_power_total_key_xfmr", DbToYang_attn_output_power_total_key_xfmr) + +} + +var YangToDb_attn_name_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_attn_name_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("name") + log.V(3).Infof("YangToDb_attn_name_key_xfmr : key:", key) + + return key, nil +} + +var DbToYang_attn_name_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_attn_name_key_xfmr: ", inParams.key) + rmap, err := attenNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_attn_name_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_attn_name_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + rmap["name"] = inParams.key + + return rmap, nil +} + +var YangToDb_attn_actual_attenuation_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_attn_actual_attenuation_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + attnkey := pathInfo.Var("name") + log.V(3).Infof("YangToDb_attn_actual_attenuation_key_xfmr : attnkey", attnkey) + key := attnkey + "_ActualAttenuation:" + ATTEN_INTERVAL_CURRENT_VAL + + return key, nil +} + +var DbToYang_attn_actual_attenuation_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Infof("DbToYang_attn_attenuation_return_loss_key_xfmr: ", inParams.key) + rmap, err := attenNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_attn_optical_return_loss_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_attn_optical_return_loss_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + attnkey := pathInfo.Var("name") + log.V(3).Infof("YangToDb_attn_optical_return_loss_key_xfmr : attnkey", attnkey) + key := attnkey + "_OpticalReturnLoss:" + ATTEN_INTERVAL_CURRENT_VAL + + return key, nil +} + +var DbToYang_attn_optical_return_loss_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Infof("DbToYang_attn_optical_return_loss_key_xfmr: ", inParams.key) + rmap, err := attenNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_attn_output_power_total_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_attn_output_power_total_key_xfmr : root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + attnkey := pathInfo.Var("name") + log.V(3).Infof("YangToDb_attn_output_power_total_key_xfmr: attnkey", attnkey) + key := attnkey + "_OutputPowerTotal:" + ATTEN_INTERVAL_CURRENT_VAL + + return key, nil +} + +var DbToYang_attn_output_power_total_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Infof("DbToYang_attn_output_power_total_key_xfmr: ", inParams.key) + rmap, err := attenNameKeyDbToYang(inParams) + + return rmap, err +} + +func getAttenuatorRootObj(s *ygot.GoStruct) *ocbinds.OpenconfigOpticalAttenuator_OpticalAttenuator { + deviceObj := (*s).(*ocbinds.Device) + return deviceObj.OpticalAttenuator +} + +var attn_name_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]NamespacePayload, error) { + + // Struct to hold payload and associated key + type payloadWithKey struct { + payload map[string]interface{} + key string + } + var key string + + // Updated map to hold list of payload+key per namespace + var nsPayloadMap = make(map[string][]payloadWithKey) + + log.Infof("attn_name_get_namespace_xfmr: inParams: %v", inParams) + + pathInfo := NewPathInfo(inParams.uri) + key = pathInfo.Var("name") + log.Infof("attn_name_get_namespace_xfmr: key: %v", key) + + if len(key) > 0 { + dbName := db.GetMDBNameFromEntity(key) + log.Infof("attn_name_get_namespace_xfmr: dbName: %v", dbName) + + var raw map[string]interface{} + var payloads []map[string]interface{} + + if inParams.body != nil && len(inParams.body) > 0 { + if err := json.Unmarshal(inParams.body, &raw); err != nil { + log.Warning("Failed during unmarshal the userPayload: %v", err) + return nil, err + } + payloads = append(payloads, raw) + log.Infof("appending raw to the payloads %v", payloads) + } else { + payloads = []map[string]interface{}{} //delete purpose + } + log.Infof("based on the key return %v=dbName %v=key", dbName, key) + return []NamespacePayload{ + { + Namespace: dbName, + Payloads: payloads, + Key: key, + }, + }, nil + } + + var containerPrefix string + if inParams.body != nil { + bodyStr := string(inParams.body) + idx := strings.Index(bodyStr, "[") + if idx != -1 { + containerPrefix = bodyStr[:idx] + containerPrefix = strings.TrimRight(containerPrefix, ": \t\r\n") + } + } + + if inParams.ygRoot != nil { + attenObj := getAttenuatorRootObj(inParams.ygRoot) + + printPayloads := func(entities interface{}) { + val := reflect.ValueOf(entities) + if val.Kind() != reflect.Map { + log.Info("entities is not a map") + return + } + + for _, key := range val.MapKeys() { + entity := val.MapIndex(key).Interface() + dbName := db.GetMDBNameFromEntity(key.String()) + + ygotStruct, ok := entity.(ygot.ValidatedGoStruct) + if !ok { + log.Errorf("Entity does not implement ygot.ValidatedGoStruct") + continue + } + + entityJson, err := ygot.EmitJSON(ygotStruct, &ygot.EmitJSONConfig{ + Format: ygot.RFC7951, + Indent: "", + SkipValidation: true, + }) + if err != nil { + log.Errorf("Failed to marshal entity with ygot.EmitJSON: %v", err) + continue + } + openBraces := strings.Count(containerPrefix, "{") + finalJson := fmt.Sprintf("%s:[%s]%s", containerPrefix, string(entityJson), strings.Repeat("}", openBraces)) + + log.Errorf("reconstructed payload: %v", finalJson) + + var finalMap map[string]interface{} + if err := json.Unmarshal([]byte(finalJson), &finalMap); err != nil { + log.Errorf("Failed to unmarshal reconstructed payload: %v", err) + continue + } + + nsPayloadMap[dbName] = append(nsPayloadMap[dbName], payloadWithKey{ + payload: finalMap, + key: key.String(), + }) + + if outStr, err := json.MarshalIndent(finalMap, "", " "); err == nil { + log.Infof("Namespace: %s\nWrapped Output:\n%s", dbName, string(outStr)) + } + } + } + + if attenObj.Attenuators.Attenuator != nil { + printPayloads(attenObj.Attenuators.Attenuator) + } + } + + // If no payloads found, use wildcard namespace + if len(nsPayloadMap) == 0 { + log.Infof("No specific key found, using '*' to include all DBs.") + return []NamespacePayload{ + { + Namespace: "*", + Payloads: []map[string]interface{}{}, + Key: "*", + }, + }, nil + } + + // Construct final result + var result []NamespacePayload + for ns, pwkList := range nsPayloadMap { + for _, pwk := range pwkList { + result = append(result, NamespacePayload{ + Namespace: ns, //asic0 + Payloads: []map[string]interface{}{pwk.payload}, //payload from payloadWithKey struct + Key: pwk.key, // key from payloadWithkey struct + Commited: false, // commited flag as a false + }) + } + } + + return result, nil +} + +func attenNameKeyDbToYang(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + log.V(3).Info("attenNameKeyDbToYang : ", inParams.key) + rmap["name"] = inParams.key + + return rmap, nil +} + +// Define a new implementation for GetNamespaceFunc +func customAttenGetNamespaceFunc(inParams XfmrParams) ([]NamespacePayload, error) { + + // Your custom implementation here + nameSpaceList, err := attn_name_get_namespace_xfmr(inParams) + + return nameSpaceList, err +} diff --git a/translib/transformer/xfmr_atten_test.go b/translib/transformer/xfmr_atten_test.go new file mode 100644 index 000000000..0f1a70e37 --- /dev/null +++ b/translib/transformer/xfmr_atten_test.go @@ -0,0 +1,260 @@ +//go:build xfmrtest +// +build xfmrtest + +package transformer_test + +import ( + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "testing" + "time" +) + +/* Attenuator config, state, counters DB fields and values */ +func Test_get_attenuator_config_state_counter_DB_key(t *testing.T) { + var pre_req_map, cleanuptbl, cleanupstatetbl, cleanupcountertbl map[string]interface{} + var url string + + for idx, dbName := range getMdbNames() { + + /* ATTENUATOR Config DB test */ + t.Log("\n\n+++++++++++++ Performing Get on configDB Attenuator Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "ATTENUATOR": map[string]interface{}{ + fmt.Sprintf("ATTENUATOR-1-%d-3", idx+1): map[string]interface{}{ + "attenuation": "1.5", + "attenuation-mode": "CONSTANT_ATTENUATION", + "target-output-power": "2.5", + "enabled": "true", + }, + }, + } + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_get_json := fmt.Sprintf("{\"openconfig-optical-attenuator:config\":{\"attenuation\":\"1.5\",\"attenuation-mode\":\"openconfig-optical-attenuator:CONSTANT_ATTENUATION\",\"enabled\":true,\"name\":\"ATTENUATOR-1-%d-3\",\"target-output-power\":\"2.5\"}}", idx+1) + url = fmt.Sprintf("/openconfig-optical-attenuator:optical-attenuator/attenuators/attenuator[name=ATTENUATOR-1-%d-3]/config", idx+1) + + t.Run("Test get on ConfigDB Attnuator Key", processGetRequest(url, nil, expected_get_json, false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on configDB Attenuator Key ++++++++++++") + + /* ATTENUATOR State DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB Attenuator Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "ATTENUATOR_TABLE": map[string]interface{}{ + fmt.Sprintf("ATTENUATOR-1-%d-3", idx+1): map[string]interface{}{ + "attenuation": "2.5", + "name": fmt.Sprintf("ATTENUATOR-1-%d-3", idx+1), + "target-output-power": "1.5", + "ingress-port": "PORT-1-2-2-VOAIN", + "component": fmt.Sprintf("ATTENUATOR-1-%d-3", idx+1), + "enabled": "true", + "egress-port": "PORT-1-2-2-VOAOUT", + "fix-attenuation": "0.55", + "attenuation-mode": "CONSTANT_ATTENUATION", + }, + }, + } + loadDB(dbName, db.StateDB, pre_req_map) + expected_get_json = fmt.Sprintf("{\"openconfig-optical-attenuator:state\":{\"attenuation\":\"2.5\",\"attenuation-mode\":\"openconfig-optical-attenuator:CONSTANT_ATTENUATION\",\"component\":\"ATTENUATOR-1-%d-3\",\"egress-port\":\"PORT-1-2-2-VOAOUT\",\"enabled\":true,\"ingress-port\":\"PORT-1-2-2-VOAIN\",\"name\":\"ATTENUATOR-1-%d-3\",\"target-output-power\":\"1.5\"}}", idx+1, idx+1) + url = fmt.Sprintf("/openconfig-optical-attenuator:optical-attenuator/attenuators/attenuator[name=ATTENUATOR-1-%d-3]/state", idx+1) + t.Run("Test get on StateDB Attnuator Key ", processGetRequest(url, nil, expected_get_json, false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on stateDB Attnuator Key ++++++++++++") + + /* ATTENUATOR Counter DB test */ + t.Log("\n\n+++++++++++++ Performing Get on CounterDB Attenuator Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "ATTENUATOR": map[string]interface{}{ + fmt.Sprintf("ATTENUATOR-1-%d-3_OutputPowerTotal:15_pm_current", idx+1): map[string]interface{}{ + "instant": "2.5", + "min-time": "1680168600865596372", + "min": "5.1", + "max": "10.2", + "interval": "900000000000", + "validity": "incomplete", + "starttime": "1680168600000000000", + "max-time": "1680168600865596372", + "current_validity": "complete", + "avg": "5.5", + }, + }, + } + loadDB(dbName, db.CountersDB, pre_req_map) + expected_get_json = "{\"openconfig-optical-attenuator:output-power-total\":{\"avg\":\"5.5\",\"instant\":\"2.5\",\"interval\":\"900000000000\",\"max\":\"10.2\",\"max-time\":\"1680168600865596372\",\"min\":\"5.1\",\"min-time\":\"1680168600865596372\"}}" + url = fmt.Sprintf("/openconfig-optical-attenuator:optical-attenuator/attenuators/attenuator[name=ATTENUATOR-1-%d-3]/state/output-power-total", idx+1) + t.Run("Test get on StateDB Attnuator Key-Xfmr and Field-Xfmr.", processGetRequest(url, nil, expected_get_json, false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on CounterDB Attenuator Key ++++++++++++") + + /* Unload the Data */ + cleanuptbl = map[string]interface{}{ + "ATTENUATOR": map[string]interface{}{ + fmt.Sprintf("ATTENUATOR-1-%d-3", idx+1): "", + }, + } + unloadDB(dbName, db.ConfigDB, cleanuptbl) + + cleanupstatetbl = map[string]interface{}{ + "ATTENUATOR_TABLE": map[string]interface{}{ + fmt.Sprintf("ATTENUATOR-1-%d-3", idx+1): "", + }, + } + unloadDB(dbName, db.StateDB, cleanupstatetbl) + + cleanupcountertbl = map[string]interface{}{ + "ATTENUATOR": map[string]interface{}{ + fmt.Sprintf("ATTENUATOR-1-%d-3_OutputPowerTotal:15_pm_current", idx+1): "", + }, + } + unloadDB(dbName, db.CountersDB, cleanupcountertbl) + } +} + +func Test_set_attenuator_config_DB_key_and_field_xfmr(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing Create/Replace/Delete on platform ATTENUATOR ++++++++++++") + + for idx, dbName := range getMdbNames() { + url := fmt.Sprintf("/openconfig-optical-attenuator:optical-attenuator/attenuators/attenuator[name=ATTENUATOR-1-%d-3]/config", idx+1) + url_body_json := "{\"config\":{\"attenuation\":\"1.5\",\"attenuation-mode\":\"CONSTANT_ATTENUATION\",\"enabled\":true,\"target-output-power\":\"2.5\"}}" + pre_req_map := map[string]interface{}{ + "ATTENUATOR": map[string]interface{}{ + fmt.Sprintf("ATTENUATOR-1-%d-3", idx+1): map[string]interface{}{ + "attenuation": "12.5", + "attenuation-mode": "CONSTANT_POWER", + "target-output-power": "12.15", + "enabled": "false", + }, + }, + } + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_map := map[string]interface{}{ + "ATTENUATOR": map[string]interface{}{ + fmt.Sprintf("ATTENUATOR-1-%d-3", idx+1): map[string]interface{}{ + "attenuation": "1.5", + "attenuation-mode": "CONSTANT_ATTENUATION", + "target-output-power": "2.5", + "enabled": "true", + }, + }, + } + time.Sleep(1 * time.Second) + + //PUT Test + t.Run("Replace Test on ATTENUATOR yang", processSetRequest(url, url_body_json, "PUT", false)) + time.Sleep(1 * time.Second) + + //GET Test + t.Run("Verify replace on ATTENUATOR yang", verifyDbResult(rclient[dbName], fmt.Sprintf("ATTENUATOR|ATTENUATOR-1-%d-3", idx+1), expected_map, false)) + time.Sleep(1 * time.Second) + + //Delete Test + url = fmt.Sprintf("/openconfig-optical-attenuator:optical-attenuator/attenuators/attenuator[name=ATTENUATOR-1-%d-3]/config", idx+1) + t.Run("DELETE Test on ATTENUATOR yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + //POST Test + url = "/openconfig-optical-attenuator:optical-attenuator/attenuators" + post_payload := fmt.Sprintf("{\"attenuator\":[{\"name\":\"ATTENUATOR-1-%d-21\",\"config\": {\"attenuation-mode\": \"CONSTANT_POWER\",\"target-output-power\": \"55.55\",\"attenuation\": \"44.44\",\"enabled\":false}}]}", idx+1) + t.Run("Create test on ATTENUATOR yang", processSetRequest(url, post_payload, "POST", false)) + time.Sleep(1 * time.Second) + + expected_map = map[string]interface{}{ + "ATTENUATOR": map[string]interface{}{ + fmt.Sprintf("ATTENUATOR-1-%d-21", idx+1): map[string]interface{}{ + "attenuation": "44.44", + "attenuation-mode": "CONSTANT_POWER", + "target-output-power": "55.55", + "enabled": "false", + }, + }, + } + + //Verify After the POST test + t.Run("Verify After the POST test on ATTENUATOR yang", verifyDbResult(rclient[dbName], fmt.Sprintf("ATTENUATOR|ATTENUATOR-1-%d-21", idx+1), expected_map, false)) + + //Delete After the POST test + url = fmt.Sprintf("/openconfig-optical-attenuator:optical-attenuator/attenuators/attenuator[name=ATTENUATOR-1-%d-21]/config", idx+1) + t.Run("DELETE After the POST test on ATTENUATOR yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = "/openconfig-optical-attenuator:optical-attenuator/attenuators" + //Bulk POST Test + Bulk_post_payload := fmt.Sprintf("{\"attenuator\":[{\"name\":\"ATTENUATOR-1-%d-22\",\"config\": {\"attenuation-mode\": \"CONSTANT_POWER\",\"target-output-power\": \"55.55\",\"attenuation\": \"44.44\",\"enabled\":false}},{\"name\":\"ATTENUATOR-1-%d-23\",\"config\": {\"attenuation-mode\": \"CONSTANT_POWER\",\"target-output-power\": \"5.5\",\"attenuation\": \"4.4\",\"enabled\":true}}]}", idx+1, idx+1) + t.Run("Create test on ATTENUATOR yang", processSetRequest(url, Bulk_post_payload, "POST", false)) + + expected_map = map[string]interface{}{ + "ATTENUATOR": map[string]interface{}{ + fmt.Sprintf("ATTENUATOR-1-%d-23", idx+1): map[string]interface{}{ + "attenuation": "4.4", + "attenuation-mode": "CONSTANT_POWER", + "target-output-power": "5.5", + "enabled": "true", + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the Bulk test + t.Run("Verify After the Bulk test on ATTENUATOR yang", verifyDbResult(rclient[dbName], fmt.Sprintf("ATTENUATOR|ATTENUATOR-1-%d-23", idx+1), expected_map, false)) + + expected_map = map[string]interface{}{ + "ATTENUATOR": map[string]interface{}{ + fmt.Sprintf("ATTENUATOR-1-%d-22", idx+1): map[string]interface{}{ + "attenuation": "44.44", + "attenuation-mode": "CONSTANT_POWER", + "target-output-power": "55.55", + "enabled": "false", + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the POST test + t.Run("Verify After the Bulk test on ATTENUATOR yang", verifyDbResult(rclient[dbName], fmt.Sprintf("ATTENUATOR|ATTENUATOR-1-%d-22", idx+1), expected_map, false)) + + //Delete keys After the Bulk Test + url = fmt.Sprintf("/openconfig-optical-attenuator:optical-attenuator/attenuators/attenuator[name=ATTENUATOR-1-%d-22]/config", idx+1) + t.Run("DELETE After the Bulk Test on ATTENUATOR yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = fmt.Sprintf("/openconfig-optical-attenuator:optical-attenuator/attenuators/attenuator[name=ATTENUATOR-1-%d-23]/config", idx+1) + t.Run("DELETE After the Bulk Test on ATTENUATOR yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + } + + t.Log("\n\n+++++++++++++ Done Performing Create/Replace/Delete on ATTENUATOR ++++++++++++") +} + +func Test_attenuator_allow_write_multiple_namespace(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing attenuator write for multiple namespace (should be allowed) ++++++++++++") + + url := "/openconfig-optical-attenuator:optical-attenuator/attenuators" + + url_body_json := `{ + "attenuator": [ + { + "name": "ATTENUATOR-1-2-22", + "config": { + "attenuation-mode": "CONSTANT_POWER", + "target-output-power": "55.55", + "attenuation": "44.44", + "enabled": false + } + }, + { + "name": "ATTENUATOR-1-1-23", + "config": { + "attenuation-mode": "CONSTANT_POWER", + "target-output-power": "5.5", + "attenuation": "4.4", + "enabled": true + } + } + ] + }` + + // false = no error expected + t.Run("Test allow writing multiple namespace for attenuator", processSetRequest(url, url_body_json, "POST", false, nil)) + + t.Log("\n\n+++++++++++++ Done Performing attenuator write for multiple namespace ++++++++++++") +} diff --git a/translib/transformer/xfmr_channel_monitor.go b/translib/transformer/xfmr_channel_monitor.go new file mode 100644 index 000000000..d2cb088ac --- /dev/null +++ b/translib/transformer/xfmr_channel_monitor.go @@ -0,0 +1,281 @@ +package transformer + +import ( + "encoding/json" + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "github.com/Azure/sonic-mgmt-common/translib/ocbinds" + log "github.com/golang/glog" + "github.com/openconfig/ygot/ygot" + "reflect" + "strings" +) + +func init() { + + // OCM table name key transformers CONFIG_DB + XlateFuncBind("YangToDb_ocm_name_key_xfmr", YangToDb_ocm_name_key_xfmr) + XlateFuncBind("DbToYang_ocm_name_key_xfmr", DbToYang_ocm_name_key_xfmr) + + // OCM table channel key transformers STATE_DB + XlateFuncBind("YangToDb_ocm_channel_key_xfmr", YangToDb_ocm_channel_key_xfmr) + XlateFuncBind("DbToYang_ocm_channel_key_xfmr", DbToYang_ocm_channel_key_xfmr) + + // OCM table channel field transformers STATE_DB + XlateFuncBind("YangToDb_ocm_lower_frequency_field_xfmr", YangToDb_ocm_lower_frequency_field_xfmr) + XlateFuncBind("DbToYang_ocm_lower_frequency_field_xfmr", DbToYang_ocm_lower_frequency_field_xfmr) + XlateFuncBind("YangToDb_ocm_upper_frequency_field_xfmr", YangToDb_ocm_upper_frequency_field_xfmr) + XlateFuncBind("DbToYang_ocm_upper_frequency_field_xfmr", DbToYang_ocm_upper_frequency_field_xfmr) + + // Override the existing function with the new implementation + // Uncomment the below line to override the existing GetNamespaceFunc + // ocm_get_namespace_xfmr = customOcmGetNamespaceFunc + + // OCM table name get-namespace transformers + XlateFuncBind("ocm_get_namespace_xfmr", ocm_get_namespace_xfmr) + +} + +var YangToDb_ocm_name_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Info("YangToDb_ocm_name_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("name") + + return key, nil +} + +var DbToYang_ocm_name_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + key := inParams.key + + TableKeys := strings.Split(key, "|") + rmap["name"] = TableKeys[0] + log.V(3).Info("DbToYang_ocm_name_key_xfmr :", rmap) + + return rmap, nil +} + +var YangToDb_ocm_channel_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Info("YangToDb_ocm_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + name := pathInfo.Var("name") + lower := pathInfo.Var("lower-frequency") + upper := pathInfo.Var("upper-frequency") + key := name + "|" + lower + "|" + upper + + return key, nil +} + +var DbToYang_ocm_channel_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + key := inParams.key + + TableKeys := strings.Split(key, "|") + if len(TableKeys) >= 3 { + rmap["lower-frequency"] = TableKeys[1] + rmap["upper-frequency"] = TableKeys[2] + } + log.V(3).Info("DbToYang_ocm_channel_key_xfmr : rmap ", rmap) + + return rmap, nil +} + +var YangToDb_ocm_lower_frequency_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_ocm_lower_frequency_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + key := inParams.key + + TableKeys := strings.Split(key, "|") + if len(TableKeys) >= 2 { + rmap["lower-frequency"] = TableKeys[1] + } + + return rmap, nil +} + +var YangToDb_ocm_upper_frequency_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_ocm_upper_frequency_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + key := inParams.key + + TableKeys := strings.Split(key, "|") + if len(TableKeys) >= 2 { + rmap["upper-frequency"] = TableKeys[2] + } + + return rmap, nil +} + +func getChannelMonitorObj(s *ygot.GoStruct) *ocbinds.OpenconfigChannelMonitor_ChannelMonitors { + deviceObj := (*s).(*ocbinds.Device) + return deviceObj.ChannelMonitors +} + +var ocm_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]NamespacePayload, error) { + + // Struct to hold payload and associated key + type payloadWithKey struct { + payload map[string]interface{} + key string + } + var key string + + // Updated map to hold list of payload+key per namespace + var nsPayloadMap = make(map[string][]payloadWithKey) + + log.Infof("ocm_get_namespace_xfmr: inParams: %v", inParams) + + pathInfo := NewPathInfo(inParams.uri) + key = pathInfo.Var("name") + log.Infof("ocm_get_namespace_xfmr: key: %v", key) + + if len(key) > 0 { + dbName := db.GetMDBNameFromEntity(key) + log.Infof("ocm_get_namespace_xfmr: dbName: %v", dbName) + + var raw map[string]interface{} + var payloads []map[string]interface{} + + if inParams.body != nil && len(inParams.body) > 0 { + if err := json.Unmarshal(inParams.body, &raw); err != nil { + log.Warning("Failed during unmarshal the userPayload: %v", err) + return nil, err + } + payloads = append(payloads, raw) + log.Infof("appending raw to the payloads %v", payloads) + } else { + payloads = []map[string]interface{}{} + } + log.Infof("based on the key return %v=dbName %v=key", dbName, key) + return []NamespacePayload{ + { + Namespace: dbName, + Payloads: payloads, + Key: key, + }, + }, nil + } + + var containerPrefix string + if inParams.body != nil { + bodyStr := string(inParams.body) + idx := strings.Index(bodyStr, "[") + if idx != -1 { + containerPrefix = bodyStr[:idx] + containerPrefix = strings.TrimRight(containerPrefix, ": \t\r\n") + } + } + + if inParams.ygRoot != nil { + channelMonitor := getChannelMonitorObj(inParams.ygRoot) + + printPayloads := func(entities interface{}) { + val := reflect.ValueOf(entities) + if val.Kind() != reflect.Map { + log.Info("entities is not a map") + return + } + + for _, key := range val.MapKeys() { + entity := val.MapIndex(key).Interface() + dbName := db.GetMDBNameFromEntity(key.String()) + + ygotStruct, ok := entity.(ygot.ValidatedGoStruct) + if !ok { + log.Errorf("Entity does not implement ygot.ValidatedGoStruct") + continue + } + + entityJson, err := ygot.EmitJSON(ygotStruct, &ygot.EmitJSONConfig{ + Format: ygot.RFC7951, + Indent: "", + SkipValidation: true, + }) + if err != nil { + log.Errorf("Failed to marshal entity with ygot.EmitJSON: %v", err) + continue + } + openBraces := strings.Count(containerPrefix, "{") + finalJson := fmt.Sprintf("%s:[%s]%s", containerPrefix, string(entityJson), strings.Repeat("}", openBraces)) + log.Errorf("reconstructed payload: %v", finalJson) + + var finalMap map[string]interface{} + if err := json.Unmarshal([]byte(finalJson), &finalMap); err != nil { + log.Errorf("Failed to unmarshal reconstructed payload: %v", err) + continue + } + + nsPayloadMap[dbName] = append(nsPayloadMap[dbName], payloadWithKey{ + payload: finalMap, + key: key.String(), + }) //"asic0" : payloadWithKey{payload, key} + + if outStr, err := json.MarshalIndent(finalMap, "", " "); err == nil { + log.Infof("Namespace: %s\nWrapped Output:\n%s", dbName, string(outStr)) + } + } + } + + if channelMonitor.ChannelMonitor != nil { + printPayloads(channelMonitor.ChannelMonitor) + } + } + // If no payloads found, use wildcard namespace + if len(nsPayloadMap) == 0 { + log.Infof("No specific key found, using '*' to include all DBs.") + return []NamespacePayload{ + { + Namespace: "*", + Payloads: []map[string]interface{}{}, + Key: "*", + }, + }, nil + } + // Construct final result + var result []NamespacePayload + for ns, pwkList := range nsPayloadMap { + for _, pwk := range pwkList { + result = append(result, NamespacePayload{ + Namespace: ns, //asic0 + Payloads: []map[string]interface{}{pwk.payload}, //payload from payloadWithKey struct + Key: pwk.key, // key from payloadWithkey struct + Commited: false, // commited flag as a false + }) + } + } + + return result, nil +} + +// Define a new implementation for GetNamespaceFunc aps +func customOcmGetNamespaceFunc(inParams XfmrParams) ([]NamespacePayload, error) { + + // Your custom implementation here + nameSpaceList, err := ocm_get_namespace_xfmr(inParams) + + return nameSpaceList, err +} diff --git a/translib/transformer/xfmr_channel_monitor_test.go b/translib/transformer/xfmr_channel_monitor_test.go new file mode 100644 index 000000000..6728d1e96 --- /dev/null +++ b/translib/transformer/xfmr_channel_monitor_test.go @@ -0,0 +1,219 @@ +//go:build xfmrtest +// +build xfmrtest + +package transformer_test + +import ( + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "testing" + "time" +) + +/* channel_monitor config,counters, state DB fields and values */ +func Test_channel_monitor_config_state_DB_key(t *testing.T) { + var pre_req_map, cleanuptbl, cleanupstatetbl map[string]interface{} + var expected_get_json, url []string + + for idx, dbName := range getMdbNames() { + + /* channel_monitor config DB test */ + t.Log("\n\n+++++++++++++ Performing Get on configDB channel monitor Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "OCM": map[string]interface{}{ + fmt.Sprintf("OCM-1-%d-2", idx+1): map[string]interface{}{ + "monitor-port": "test_monitor_port", + }, + }, + } + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_get_json = []string{ + fmt.Sprintf("{\"openconfig-channel-monitor:config\":{\"monitor-port\":\"test_monitor_port\",\"name\":\"OCM-1-%d-2\"}}", idx+1), + } + url = []string{ + fmt.Sprintf("/openconfig-channel-monitor:channel-monitors/channel-monitor[name=OCM-1-%d-2]/config", idx+1), + } + + t.Run("Test get on config DB channel monitor Key", processGetRequest(url[0], nil, expected_get_json[0], false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on configDB channel monitor Key ++++++++++++") + + /* channel monitor State DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB channel monitor Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "OCM_TABLE": map[string]interface{}{ + fmt.Sprintf("OCM-1-%d-2", idx+1): map[string]interface{}{ + "monitor-port": "test_monitor_port", + }, + }, + "OCM_CHANNEL_TABLE": map[string]interface{}{ + fmt.Sprintf("OCM-1-%d-2|25|100", idx+1): map[string]interface{}{ + "power": "5.0", + }, + }, + } + loadDB(dbName, db.StateDB, pre_req_map) + expected_get_json = []string{ + fmt.Sprintf("{\"openconfig-channel-monitor:state\":{\"monitor-port\":\"test_monitor_port\",\"name\":\"OCM-1-%d-2\"}}", idx+1), + fmt.Sprintf("{\"openconfig-channel-monitor:state\":{\"lower-frequency\":\"25\",\"power\":\"5\",\"upper-frequency\":\"100\"}}"), + } + url = []string{ + fmt.Sprintf("/openconfig-channel-monitor:channel-monitors/channel-monitor[name=OCM-1-%d-2]/state", idx+1), + fmt.Sprintf("/openconfig-channel-monitor:channel-monitors/channel-monitor[name=OCM-1-%d-2]/channels/channel[lower-frequency=25][upper-frequency=100]/state", idx+1), + } + + for idx, url := range url { + t.Run("Test get on state DB channel monitor Key for "+url, processGetRequest(url, nil, expected_get_json[idx], false)) + time.Sleep(1 * time.Second) + } + t.Log("\n\n+++++++++++++ Done Performing Get on stateDB channel monitor Key ++++++++++++") + + /* Unload the Data */ + cleanuptbl = map[string]interface{}{ + "OCM": map[string]interface{}{ + fmt.Sprintf("OCM-1-%d-2", idx+1): "", + }, + } + unloadDB(dbName, db.ConfigDB, cleanuptbl) + cleanupstatetbl = map[string]interface{}{ + "OCM_TABLE": map[string]interface{}{ + fmt.Sprintf("OCM-1-%d-2", idx+1): "", + }, + "OCM_CHANNEL_TABLE": map[string]interface{}{ + fmt.Sprintf("OCM-1-%d-2|25|100", idx+1): "", + }, + } + unloadDB(dbName, db.StateDB, cleanupstatetbl) + } +} + +func Test_set_channel_monitor_config_DB_key_and_field_xfmr(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing Create/Replace/Delete on channel monitor ++++++++++++") + for idx, dbName := range getMdbNames() { + url := fmt.Sprintf("/openconfig-channel-monitor:channel-monitors/channel-monitor[name=OCM-1-%d-2]/config", idx+1) + url_body_json := "{\"config\": {\"monitor-port\": \"monitor_data\"}}" + + pre_req_map := map[string]interface{}{ + "OCM": map[string]interface{}{ + fmt.Sprintf("OCM-1-%d-2", idx+1): map[string]interface{}{ + "monitor-port": "test_monitor_port", + }, + }, + } + + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_map := map[string]interface{}{ + "OCM": map[string]interface{}{ + fmt.Sprintf("OCM-1-%d-2", idx+1): map[string]interface{}{ + "monitor-port": "monitor_data", + }, + }, + } + + time.Sleep(1 * time.Second) + + //PUT Test + t.Run("Replace Test on Channel Monitor yang", processSetRequest(url, url_body_json, "PUT", false)) + time.Sleep(1 * time.Second) + + //GET Test + t.Run("Verify replace on Channel Monitor yang", verifyDbResult(rclient[dbName], fmt.Sprintf("OCM|OCM-1-%d-2", idx+1), expected_map, false)) + time.Sleep(1 * time.Second) + + //Delete Test + url = fmt.Sprintf("/openconfig-channel-monitor:channel-monitors/channel-monitor[name=OCM-1-%d-2]/config", idx+1) + t.Run("DELETE Test on Channel Monitor yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + //POST Test + url = "/openconfig-channel-monitor:channel-monitors" + post_payload := fmt.Sprintf("{\"channel-monitor\":[{\"name\":\"OCM-1-%d-13\",\"config\":{\"monitor-port\":\"test_port_data\"}}]}", idx+1) + t.Run("Create test on Channel Monitor yang", processSetRequest(url, post_payload, "POST", false)) + time.Sleep(1 * time.Second) + + expected_map = map[string]interface{}{ + "OCM": map[string]interface{}{ + fmt.Sprintf("OCM-1-%d-13", idx+1): map[string]interface{}{ + "monitor-port": "test_port_data", + }, + }, + } + + //Verify After the POST test + t.Run("Verify After the POST test on Channel Monitor yang", verifyDbResult(rclient[dbName], fmt.Sprintf("OCM|OCM-1-%d-13", idx+1), expected_map, false)) + + //Delete After the POST test + url = fmt.Sprintf("/openconfig-channel-monitor:channel-monitors/channel-monitor[name=OCM-1-%d-13]/config", idx+1) + t.Run("DELETE After the POST test on Channel Monitor yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = "/openconfig-channel-monitor:channel-monitors" + + //Bulk POST Test + Bulk_post_payload := fmt.Sprintf("{\"channel-monitor\":[{\"name\":\"OCM-1-%d-14\",\"config\":{\"monitor-port\":\"Port_data_1\"}},{\"name\":\"OCM-1-%d-15\",\"config\":{\"monitor-port\":\"Port_data_2\"}}]}", idx+1, idx+1) + + t.Run("Create test on Channel monitor yang", processSetRequest(url, Bulk_post_payload, "POST", false)) + + expected_map = map[string]interface{}{ + "OCM": map[string]interface{}{ + fmt.Sprintf("OCM-1-%d-14", idx+1): map[string]interface{}{ + "monitor-port": "Port_data_1", + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the Bulk test + t.Run("Verify After the Bulk test on Channel Monitor yang", verifyDbResult(rclient[dbName], fmt.Sprintf("OCM|OCM-1-%d-14", idx+1), expected_map, false)) + + expected_map = map[string]interface{}{ + "OCM": map[string]interface{}{ + fmt.Sprintf("OCM-1-%d-15", idx+1): map[string]interface{}{ + "monitor-port": "Port_data_2", + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the POST test + t.Run("Verify After the Bulk test on Channel Monitor yang", verifyDbResult(rclient[dbName], fmt.Sprintf("OCM|OCM-1-%d-15", idx+1), expected_map, false)) + + //Delete keys After the Bulk Test + url = fmt.Sprintf("/openconfig-channel-monitor:channel-monitors/channel-monitor[name=OCM-1-%d-14]/config", idx+1) + t.Run("DELETE After the Bulk Test on Channel Monitor yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = fmt.Sprintf("/openconfig-channel-monitor:channel-monitors/channel-monitor[name=OCM-1-%d-15]/config", idx+1) + t.Run("DELETE After the Bulk Test on Channel Monitor yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + } + + t.Log("\n\n+++++++++++++ Done Performing Create/Replace/Delete on Channel Monitor ++++++++++++") +} + +func Test_channel_monitor_allow_write_multiple_namespace(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing channel monitor write for multiple namespace (should be allowed) ++++++++++++") + + url := "/openconfig-channel-monitor:channel-monitors" + url_body_json := `{ + "channel-monitor": [ + { + "name": "OCM-1-2-14", + "config": { + "monitor-port": "Port_data_1" + } + }, + { + "name": "OCM-1-3-15", + "config": { + "monitor-port": "Port_data_2" + } + } + ] + }` + + // false = no error expected + t.Run("Test allow writing multiple namespace for channel monitor", processSetRequest(url, url_body_json, "POST", false, nil)) + + t.Log("\n\n+++++++++++++ Done Performing channel monitor write for multiple namespace ++++++++++++") +} diff --git a/translib/transformer/xfmr_getNamespace.go b/translib/transformer/xfmr_getNamespace.go new file mode 100644 index 000000000..cbaccf215 --- /dev/null +++ b/translib/transformer/xfmr_getNamespace.go @@ -0,0 +1,26 @@ +package transformer + +import ( + log "github.com/golang/glog" +) + +func init() { + + //Get Namespace transformer function + XlateFuncBind("test_get_namespace_xfmr", test_get_namespace_xfmr) +} + +var test_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]NamespacePayload, error) { + + var nameSpaceList []NamespacePayload + + nameSpaceList = append(nameSpaceList, NamespacePayload{ + Namespace: "host", + Payloads: []map[string]interface{}{}, + Key: "", + }) + + log.V(3).Infof("test_get_namespace_xfmr: nameSpaceList:%v ", nameSpaceList) + + return nameSpaceList, nil +} diff --git a/translib/transformer/xfmr_line_common.go b/translib/transformer/xfmr_line_common.go new file mode 100644 index 000000000..b0cb81133 --- /dev/null +++ b/translib/transformer/xfmr_line_common.go @@ -0,0 +1,91 @@ +package transformer + +import ( + log "github.com/golang/glog" +) + +const LINE_COMMON_INTERVAL_CURRENT_VAL = "15_pm_current" + +func init() { + + /* Key transformer for PORT table*/ + XlateFuncBind("YangToDb_optical_port_key_xfmr", YangToDb_optical_port_key_xfmr) + XlateFuncBind("DbToYang_optical_port_key_xfmr", DbToYang_optical_port_key_xfmr) + XlateFuncBind("YangToDb_optical_port_input_power_key_xfmr", YangToDb_optical_port_input_power_key_xfmr) + XlateFuncBind("DbToYang_optical_port_input_power_key_xfmr", DbToYang_optical_port_input_power_key_xfmr) + XlateFuncBind("YangToDb_optical_port_output_power_key_xfmr", YangToDb_optical_port_output_power_key_xfmr) + XlateFuncBind("DbToYang_optical_port_output_power_key_xfmr", DbToYang_optical_port_output_power_key_xfmr) + +} + +var YangToDb_optical_port_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_optical_port_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + ochkey := pathInfo.Var("name") + log.V(3).Infof("YangToDb_optical_port_key_xfmr: :", ochkey) + + return ochkey, nil +} + +var DbToYang_optical_port_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Infof("DbToYang_optical_port_key_xfmr: ", inParams.key) + rmap, err := portNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_optical_port_input_power_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_optical_port_input_power_key_xfmr : root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + name := pathInfo.Var("name") + key := name + "_InputPower:" + LINE_COMMON_INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_optical_port_input_power_key_xfmr : key:", key) + + return key, nil +} + +var DbToYang_optical_port_input_power_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Infof("DbToYang_optical_port_input_power_key_xfmr: ", inParams.key) + rmap, err := portNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_optical_port_output_power_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_optical_port_output_power_key_xfmr : root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + name := pathInfo.Var("name") + key := name + "_OutputPower:" + LINE_COMMON_INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_optical_port_output_power_key_xfmr : key:", key) + + return key, nil +} + +var DbToYang_optical_port_output_power_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Infof("DbToYang_optical_port_output_power_key_xfmr: ", inParams.key) + rmap, err := portNameKeyDbToYang(inParams) + + return rmap, err +} + +func portNameKeyDbToYang(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + log.V(3).Info("portNameKeyDbToYang : ", inParams.key) + rmap["name"] = inParams.key + + return rmap, nil +} diff --git a/translib/transformer/xfmr_line_common_test.go b/translib/transformer/xfmr_line_common_test.go new file mode 100644 index 000000000..c09b4cfa7 --- /dev/null +++ b/translib/transformer/xfmr_line_common_test.go @@ -0,0 +1,94 @@ +//go:build xfmrtest +// +build xfmrtest + +package transformer_test + +import ( + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "testing" + "time" +) + +/* PORT counters, state DB fields and values */ +func Test_port_config_state_counter_DB_key(t *testing.T) { + var pre_req_map, cleanuptbl, cleanupstatetbl, cleanupcountertbl map[string]interface{} + var url string + + for idx, dbName := range getMdbNames() { + + /* PORT config DB data load */ + pre_req_map = map[string]interface{}{ + "OC_COMPONENT": map[string]interface{}{ + fmt.Sprintf("PORT-1-%d-L1IN", idx+1): map[string]interface{}{ + "name": fmt.Sprintf("PORT-1-%d-L1IN", idx+1), + }, + }, + } + loadDB(dbName, db.ConfigDB, pre_req_map) + + /* PORT State DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB PORT Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "PORT_TABLE": map[string]interface{}{ + fmt.Sprintf("PORT-1-%d-L1IN", idx+1): map[string]interface{}{ + "admin-state": "ENABLED", + "optical-port-type": "ADD", + }, + }, + } + loadDB(dbName, db.StateDB, pre_req_map) + expected_get_json := "{\"openconfig-transport-line-common:state\":{\"admin-state\":\"ENABLED\",\"optical-port-type\":\"openconfig-transport-types:ADD\"}}" + url = fmt.Sprintf("/openconfig-platform:components/component[name=PORT-1-%d-L1IN]/port/openconfig-transport-line-common:optical-port/state", idx+1) + + t.Run("Test get on state DB PORT Key", processGetRequest(url, nil, expected_get_json, false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on stateDB PORT Key ++++++++++++") + + /* PORT Counters DB test */ + t.Log("\n\n+++++++++++++ Performing Get on counterDB PORT Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "PORT": map[string]interface{}{ + fmt.Sprintf("PORT-1-%d-L1IN_InputPower:15_pm_current", idx+1): map[string]interface{}{ + "instant": "1.5", + "min-time": "1680168600865596372", + "min": "5.4", + "max": "10.5", + "interval": "900000000000", + "validity": "incomplete", + "starttime": "1680168600000000000", + "max-time": "1680168600865596372", + "current_validity": "complete", + "avg": "11.12", + }, + }, + } + loadDB(dbName, db.CountersDB, pre_req_map) + expected_get_json = "{\"openconfig-transport-line-common:input-power\":{\"avg\":\"11.12\",\"instant\":\"1.5\",\"interval\":\"900000000000\",\"max\":\"10.5\",\"max-time\":\"1680168600865596372\",\"min\":\"5.4\",\"min-time\":\"1680168600865596372\"}}" + url = fmt.Sprintf("/openconfig-platform:components/component[name=PORT-1-%d-L1IN]/port/openconfig-transport-line-common:optical-port/state/input-power", idx+1) + + t.Run("Test get on counter DB PORT Key", processGetRequest(url, nil, expected_get_json, false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on counterDB PORT Key ++++++++++++") + + // Unload the Data + cleanuptbl = map[string]interface{}{ + "OC_COMPONENT": map[string]interface{}{ + fmt.Sprintf("PORT-1-%d-L1IN", idx+1): "", + }, + } + unloadDB(dbName, db.ConfigDB, cleanuptbl) + cleanupstatetbl = map[string]interface{}{ + "PORT_TABLE": map[string]interface{}{ + fmt.Sprintf("PORT-1-%d-L1IN", idx+1): "", + }, + } + unloadDB(dbName, db.StateDB, cleanupstatetbl) + cleanupcountertbl = map[string]interface{}{ + "PORT": map[string]interface{}{ + fmt.Sprintf("PORT-1-%d-L1IN_InputPower:15_pm_current", idx+1): "", + }, + } + unloadDB(dbName, db.CountersDB, cleanupcountertbl) + } +} diff --git a/translib/transformer/xfmr_optical_amplifier.go b/translib/transformer/xfmr_optical_amplifier.go new file mode 100644 index 000000000..318699b7c --- /dev/null +++ b/translib/transformer/xfmr_optical_amplifier.go @@ -0,0 +1,647 @@ +package transformer + +import ( + "encoding/json" + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "github.com/Azure/sonic-mgmt-common/translib/ocbinds" + log "github.com/golang/glog" + "github.com/openconfig/ygot/ygot" + "reflect" + "strings" +) + +const ( + INTERVAL_CURRENT_VAL = "15_pm_current" + + /* COUNTER KEYS */ + ACTUAL_GAIN = "_ActualGain:" + ACTUAL_GAIN_TILT = "_ActualGainTilt:" + INPUT_POWER_TOTAL = "_InputPowerTotal:" + OUTPUT_POWER_TOTAL = "_OutputPowerTotal:" + INPUT_POWER = "_InputPower:" + OUTPUT_POWER = "_OutputPower:" + INPUT_POWER_L_BAND = "_InputPowerLBand:" + INPUT_POWER_C_BAND = "_InputPowerCBand:" + OUTPUT_POWER_L_BAND = "_OutputPowerLBand:" + OUTPUT_POWER_C_BAND = "_OutputPowerCBand:" + LASER_BIAS_CURRENT = "_LaserBiasCurrent:" + OPTICAL_RETURN_LOSS = "_OpticalReturnLoss:" +) + +func init() { + + /* Key transformer for AMPLIFIER table*/ + XlateFuncBind("YangToDb_oa_name_key_xfmr", YangToDb_oa_name_key_xfmr) + XlateFuncBind("DbToYang_oa_name_key_xfmr", DbToYang_oa_name_key_xfmr) + + /* Field transformer for AMPLIFIER table*/ + XlateFuncBind("YangToDb_oa_name_field_xfmr", YangToDb_oa_name_field_xfmr) + XlateFuncBind("DbToYang_oa_name_field_xfmr", DbToYang_oa_name_field_xfmr) + + // Override the existing function with the new implementation + // Uncomment the below line to override the existing GetNamespaceFunc + // oa_name_get_namespace_xfmr = customGetNamespaceFunc + + /* Get Namespace transformer for AMPLIFIER table*/ + XlateFuncBind("oa_name_get_namespace_xfmr", oa_name_get_namespace_xfmr) + + /* Key transformer for AMPLIFIER Output Power L Band Counter table*/ + XlateFuncBind("YangToDb_oa_counter_output_powerL_key_xfmr", YangToDb_oa_counter_output_powerL_key_xfmr) + XlateFuncBind("DbToYang_oa_counter_output_powerL_key_xfmr", DbToYang_oa_counter_output_powerL_key_xfmr) + + /* Key transformer for AMPLIFIER Optical Return loss Counter table*/ + XlateFuncBind("YangToDb_oa_counter_optical_return_loss_key_xfmr", YangToDb_oa_counter_optical_return_loss_key_xfmr) + XlateFuncBind("DbToYang_oa_counter_optical_return_loss_key_xfmr", DbToYang_oa_counter_optical_return_loss_key_xfmr) + + /* Key transformer for AMPLIFIER Output Power CBandCounter table*/ + XlateFuncBind("YangToDb_oa_counter_output_powerC_key_xfmr", YangToDb_oa_counter_output_powerC_key_xfmr) + XlateFuncBind("DbToYang_oa_counter_output_powerC_key_xfmr", DbToYang_oa_counter_output_powerC_key_xfmr) + + /* Key transformer for AMPLIFIER Laser bias Counter table*/ + XlateFuncBind("YangToDb_oa_counter_laser_bias_key_xfmr", YangToDb_oa_counter_laser_bias_key_xfmr) + XlateFuncBind("DbToYang_oa_counter_laser_bias_key_xfmr", DbToYang_oa_counter_laser_bias_key_xfmr) + + /* Key transformer for AMPLIFIER input power c band Counter table*/ + XlateFuncBind("YangToDb_oa_counter_input_powerC_key_xfmr", YangToDb_oa_counter_input_powerC_key_xfmr) + XlateFuncBind("DbToYang_oa_counter_input_powerC_key_xfmr", DbToYang_oa_counter_input_powerC_key_xfmr) + + /* Key transformer for AMPLIFIER output power total Counter table*/ + XlateFuncBind("YangToDb_oa_counter_output_power_total_key_xfmr", YangToDb_oa_counter_output_power_total_key_xfmr) + XlateFuncBind("DbToYang_oa_counter_output_power_total_key_xfmr", DbToYang_oa_counter_output_power_total_key_xfmr) + + /* Key transformer for AMPLIFIER input power total Counter table*/ + XlateFuncBind("YangToDb_oa_counter_input_power_total_key_xfmr", YangToDb_oa_counter_input_power_total_key_xfmr) + XlateFuncBind("DbToYang_oa_counter_input_power_total_key_xfmr", DbToYang_oa_counter_input_power_total_key_xfmr) + + /* Key transformer for AMPLIFIER input power l Counter table*/ + XlateFuncBind("YangToDb_oa_counter_input_powerL_key_xfmr", YangToDb_oa_counter_input_powerL_key_xfmr) + XlateFuncBind("DbToYang_oa_counter_input_powerL_key_xfmr", DbToYang_oa_counter_input_powerL_key_xfmr) + + /* Key transformer for AMPLIFIER actual gain Counter table*/ + XlateFuncBind("YangToDb_oa_counter_actual_gain_key_xfmr", YangToDb_oa_counter_actual_gain_key_xfmr) + XlateFuncBind("DbToYang_oa_counter_actual_gain_key_xfmr", DbToYang_oa_counter_actual_gain_key_xfmr) + + /* Key transformer for AMPLIFIER actual gain tilt Counter table*/ + XlateFuncBind("YangToDb_oa_counter_actual_gain_tilt_key_xfmr", YangToDb_oa_counter_actual_gain_tilt_key_xfmr) + XlateFuncBind("DbToYang_oa_counter_actual_gain_tilt_key_xfmr", DbToYang_oa_counter_actual_gain_tilt_key_xfmr) + + /* Key transformer for OSC table*/ + XlateFuncBind("YangToDb_osc_key_xfmr", YangToDb_osc_key_xfmr) + XlateFuncBind("DbToYang_osc_key_xfmr", DbToYang_osc_key_xfmr) + + /* Field transformer for OSC table*/ + XlateFuncBind("YangToDb_osc_interface_field_xfmr", YangToDb_osc_interface_field_xfmr) + XlateFuncBind("DbToYang_osc_interface_field_xfmr", DbToYang_osc_interface_field_xfmr) + + /* Key transformer for OSC input power Counter table*/ + XlateFuncBind("YangToDb_osc_input_power_counter_key_xfmr", YangToDb_osc_input_power_counter_key_xfmr) + XlateFuncBind("DbToYang_osc_input_power_counter_key_xfmr", DbToYang_osc_input_power_counter_key_xfmr) + + /* Key transformer for OSC output power Counter table*/ + XlateFuncBind("YangToDb_osc_output_power_counter_key_xfmr", YangToDb_osc_output_power_counter_key_xfmr) + XlateFuncBind("DbToYang_osc_output_power_counter_key_xfmr", DbToYang_osc_output_power_counter_key_xfmr) + + /* Key transformer for OSC laser bias current Counter table*/ + XlateFuncBind("YangToDb_osc_laser_bias_current_counter_key_xfmr", YangToDb_osc_laser_bias_current_counter_key_xfmr) + XlateFuncBind("DbToYang_osc_laser_bias_current_counter_key_xfmr", DbToYang_osc_laser_bias_current_counter_key_xfmr) + +} + +var YangToDb_oa_name_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_oa_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + oakey := pathInfo.Var("name") + log.V(3).Infof("YangToDb_oa_key_xfmr: :", oakey) + + return oakey, nil +} + +var DbToYang_oa_name_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + log.V(3).Infof("DbToYang_oa_key_xfmr: ", inParams.key) + rmap["name"] = inParams.key + + return rmap, nil +} + +var YangToDb_oa_name_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_oa_name_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + rmap["name"] = inParams.key + + return rmap, nil +} + +func amplifierNameKeyDbToYang(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + log.V(3).Info("amplifierNameKeyDbToYang: ", inParams.key) + rmap["name"] = inParams.key + + return rmap, nil +} + +var YangToDb_oa_counter_output_powerL_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_oa_counter_output_powerL_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + oakey := pathInfo.Var("name") + oaCounterKey := oakey + OUTPUT_POWER_L_BAND + INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_oa_counter_output-powerL_key_xfmr: key:", oaCounterKey) + + return oaCounterKey, nil +} + +var DbToYang_oa_counter_output_powerL_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_oa_counter_output_powerL_key_xfmr: ", inParams.key) + rmap, err := amplifierNameKeyDbToYang(inParams) + + return rmap, err + +} + +var YangToDb_oa_counter_output_power_total_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_oa_counter_output_power_total_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + oakey := pathInfo.Var("name") + oaCounterKey := oakey + OUTPUT_POWER_TOTAL + INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_oa_counter_output_power_total_key_xfmr: key:", oaCounterKey) + + return oaCounterKey, nil +} + +var DbToYang_oa_counter_output_power_total_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_oa_counter_output_power_total_key_xfmr: ", inParams.key) + rmap, err := amplifierNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_oa_counter_input_power_total_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_oa_counter_input_power_total_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + oakey := pathInfo.Var("name") + oaCounterKey := oakey + INPUT_POWER_TOTAL + INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_oa_counter_input_power_total_key_xfmr: key:", oaCounterKey) + + return oaCounterKey, nil +} + +var DbToYang_oa_counter_input_power_total_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_oa_counter_input_power_total_key_xfmr: ", inParams.key) + rmap, err := amplifierNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_oa_counter_input_powerL_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_oa_counter_input_powerL_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + oakey := pathInfo.Var("name") + oaCounterKey := oakey + INPUT_POWER_L_BAND + INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_oa_counter_input_powerL_key_xfmr: key:", oaCounterKey) + + return oaCounterKey, nil +} + +var DbToYang_oa_counter_input_powerL_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_oa_counter_input_powerL_key_xfmr: ", inParams.key) + rmap, err := amplifierNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_oa_counter_input_powerC_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_oa_counter_input_powerC_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + oakey := pathInfo.Var("name") + oaCounterKey := oakey + INPUT_POWER_C_BAND + INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_oa_counter_input_powerC_key_xfmr: key:", oaCounterKey) + + return oaCounterKey, nil +} + +var DbToYang_oa_counter_input_powerC_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_oa_counter_input_powerC_key_xfmr: ", inParams.key) + rmap, err := amplifierNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_oa_counter_actual_gain_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_oa_counter_actual_gain_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + oakey := pathInfo.Var("name") + oaCounterKey := oakey + ACTUAL_GAIN + INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_oa_counter_actual_gain_key_xfmr: key:", oaCounterKey) + + return oaCounterKey, nil +} + +var DbToYang_oa_counter_actual_gain_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_oa_counter_actual_gain_key_xfmr: ", inParams.key) + rmap, err := amplifierNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_oa_counter_actual_gain_tilt_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_oa_counter_actual_gain_tilt_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + oakey := pathInfo.Var("name") + oaCounterKey := oakey + ACTUAL_GAIN_TILT + INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_oa_counter_actual_gain_tilt_key_xfmr: key:", oaCounterKey) + + return oaCounterKey, nil +} + +var DbToYang_oa_counter_actual_gain_tilt_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_oa_counter_actual_gain_tilt_key_xfmr: ", inParams.key) + rmap, err := amplifierNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_oa_counter_output_powerC_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_oa_counter_output_powerC_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + oakey := pathInfo.Var("name") + oaCounterKey := oakey + OUTPUT_POWER_C_BAND + INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_oa_counter_output_powerC_key_xfmr: key:", oaCounterKey) + + return oaCounterKey, nil +} + +var DbToYang_oa_counter_output_powerC_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_oa_counter_output_powerC_key_xfmr: ", inParams.key) + rmap, err := amplifierNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_oa_counter_optical_return_loss_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_oa_counter_optical_return_loss_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + oakey := pathInfo.Var("name") + oaCounterKey := oakey + OPTICAL_RETURN_LOSS + INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_oa_counter_optical_return_loss_key_xfmr: key:", oaCounterKey) + + return oaCounterKey, nil +} + +var DbToYang_oa_counter_optical_return_loss_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_oa_counter_optical_return_loss_key_xfmr: ", inParams.key) + rmap, err := amplifierNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_oa_counter_laser_bias_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_oa_counter_laser_bias_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + oakey := pathInfo.Var("name") + oaCounterKey := oakey + LASER_BIAS_CURRENT + INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_oa_counter_laser_bias_key_xfmr: key:", oaCounterKey) + + return oaCounterKey, nil +} + +var DbToYang_oa_counter_laser_bias_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_oa_counter_laser_bias_key_xfmr: ", inParams.key) + rmap, err := amplifierNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_osc_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_osc_interface_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + osckey := pathInfo.Var("interface") + log.V(3).Infof("YangToDb_osc_interface_xfmr:osckey:", osckey) + + return osckey, nil +} + +var DbToYang_osc_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + log.V(3).Info("DbToYang_osc_interface_xfmr: ", inParams.key) + rmap["interface"] = inParams.key + + return rmap, nil +} + +var YangToDb_osc_interface_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_osc_interface_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + rmap["interface"] = inParams.key + + return rmap, nil +} + +func oscNameKeyDbToYang(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + log.V(3).Info("oscNameKeyDbToYang: ", inParams.key) + rmap["interface"] = inParams.key + + return rmap, nil +} + +var YangToDb_osc_input_power_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_osc_input_power_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + osckey := pathInfo.Var("interface") + oscCounterKey := osckey + INPUT_POWER + INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_osc_input_power_counter_key_xfmr: key:", osckey) + + return oscCounterKey, nil +} + +var DbToYang_osc_input_power_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_osc_input_power_counter_key_xfmr: ", inParams.key) + rmap, err := oscNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_osc_output_power_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_osc_output_power_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + osckey := pathInfo.Var("interface") + oscCounterKey := osckey + OUTPUT_POWER + INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_osc_output_power_counter_key_xfmr: key:", osckey) + + return oscCounterKey, nil +} + +var DbToYang_osc_output_power_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_osc_output_power_counter_key_xfmr: ", inParams.key) + rmap, err := oscNameKeyDbToYang(inParams) + + return rmap, err +} + +var YangToDb_osc_laser_bias_current_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_osc_laser_bias_current_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + osckey := pathInfo.Var("interface") + oscCounterKey := osckey + LASER_BIAS_CURRENT + INTERVAL_CURRENT_VAL + log.V(3).Infof("YangToDb_osc_laser_bias_current_counter_key_xfmr: key:", osckey) + + return oscCounterKey, nil +} + +var DbToYang_osc_laser_bias_current_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Info("DbToYang_osc_laser_bias_current_counter_key_xfmr: ", inParams.key) + rmap, err := oscNameKeyDbToYang(inParams) + + return rmap, err +} + +func getAmplifierRootObj(s *ygot.GoStruct) *ocbinds.OpenconfigOpticalAmplifier_OpticalAmplifier { + deviceObj := (*s).(*ocbinds.Device) + return deviceObj.OpticalAmplifier +} + +// Define a new implementation for GetNamespaceFunc +func customGetNamespaceFunc(inParams XfmrParams) ([]NamespacePayload, error) { + + // Your custom implementation here + nameSpaceList, err := oa_name_get_namespace_xfmr(inParams) + + return nameSpaceList, err +} + +var oa_name_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]NamespacePayload, error) { + // Struct to hold payload and associated key + type payloadWithKey struct { + payload map[string]interface{} + key string + } + var key string + + // Updated map to hold list of payload+key per namespace + var nsPayloadMap = make(map[string][]payloadWithKey) + + log.Infof("oa_name_get_namespace_xfmr: inParams: %v", inParams) + + pathInfo := NewPathInfo(inParams.uri) + + if strings.Contains(inParams.uri, "/amplifier") { + key = pathInfo.Var("name") + + } else if strings.Contains(inParams.uri, "/supervisory-channel") { + key = pathInfo.Var("interface") + } + log.Infof("oa_name_get_namespace_xfmr: key: %v", key) + + if len(key) > 0 && key != "*" { + dbName := db.GetMDBNameFromEntity(key) + log.Infof("oa_name_get_namespace_xfmr: dbName: %v", dbName) + + var raw interface{} + var payloads []map[string]interface{} + + if inParams.body != nil && len(inParams.body) > 0 { + if err := json.Unmarshal(inParams.body, &raw); err != nil { + return nil, err + } + + switch val := raw.(type) { + case map[string]interface{}: + // JSON object — store directly + payloads = append(payloads, val) + case []interface{}: + // JSON array — convert each element if it's an object + for _, item := range val { + if m, ok := item.(map[string]interface{}); ok { + payloads = append(payloads, m) + } else { + return nil, fmt.Errorf("Invalid json payload!:%v", inParams.body) + } + } + default: + return nil, fmt.Errorf("unsupported JSON structure: must be object or array of objects") + } + } else { + payloads = []map[string]interface{}{} + } + + return []NamespacePayload{ + { + Namespace: dbName, + Payloads: payloads, + Key: key, + }, + }, nil + } + + var containerPrefix string + if inParams.body != nil { + bodyStr := string(inParams.body) + idx := strings.Index(bodyStr, "[") + if idx != -1 { + containerPrefix = bodyStr[:idx] + containerPrefix = strings.TrimRight(containerPrefix, ": \t\r\n") + } + } + + if inParams.ygRoot != nil { + oa := getAmplifierRootObj(inParams.ygRoot) + + formSplitPayloadMap := func(entities interface{}) { + val := reflect.ValueOf(entities) + if val.Kind() != reflect.Map { + log.Info("entities is not a map") + return + } + + for _, key := range val.MapKeys() { + entity := val.MapIndex(key).Interface() + dbName := db.GetMDBNameFromEntity(key.String()) + + ygotStruct, ok := entity.(ygot.ValidatedGoStruct) + if !ok { + log.Errorf("Entity does not implement ygot.ValidatedGoStruct") + continue + } + + entityJson, err := ygot.EmitJSON(ygotStruct, &ygot.EmitJSONConfig{ + Format: ygot.RFC7951, + Indent: "", + SkipValidation: true, + }) + if err != nil { + log.Errorf("Failed to marshal entity with ygot.EmitJSON: %v", err) + continue + } + openBraces := strings.Count(containerPrefix, "{") + finalJson := fmt.Sprintf("%s:[%s]%s", containerPrefix, string(entityJson), strings.Repeat("}", openBraces)) + + log.Errorf("reconstructed payload: %v", finalJson) + + var finalMap map[string]interface{} + if err := json.Unmarshal([]byte(finalJson), &finalMap); err != nil { + log.Errorf("Failed to unmarshal reconstructed payload: %v", err) + continue + } + + nsPayloadMap[dbName] = append(nsPayloadMap[dbName], payloadWithKey{ + payload: finalMap, + key: key.String(), + }) + + if outStr, err := json.MarshalIndent(finalMap, "", " "); err == nil { + log.Infof("Namespace: %s\nWrapped Output:\n%s", dbName, string(outStr)) + } + } + } + + if strings.Contains(inParams.uri, "optical-amplifier") && oa.Amplifiers != nil { + formSplitPayloadMap(oa.Amplifiers.Amplifier) + } else if strings.Contains(inParams.uri, "supervisory-channels") && oa.SupervisoryChannels != nil { + formSplitPayloadMap(oa.SupervisoryChannels.SupervisoryChannel) + } + } + + // If no payloads found, use wildcard namespace + if len(nsPayloadMap) == 0 { + log.Infof("No specific key found, using '*' to include all DBs.") + return []NamespacePayload{ + { + Namespace: "*", + Payloads: []map[string]interface{}{}, + Key: "*", + }, + }, nil + } + + // Construct final result + var result []NamespacePayload + for ns, pwkList := range nsPayloadMap { + for _, pwk := range pwkList { + result = append(result, NamespacePayload{ + Namespace: ns, + Payloads: []map[string]interface{}{pwk.payload}, + Key: pwk.key, + Commited: false, + }) + } + } + + return result, nil +} diff --git a/translib/transformer/xfmr_optical_amplifier_test.go b/translib/transformer/xfmr_optical_amplifier_test.go new file mode 100644 index 000000000..05d8dff99 --- /dev/null +++ b/translib/transformer/xfmr_optical_amplifier_test.go @@ -0,0 +1,349 @@ +//go:build xfmrtest +// +build xfmrtest + +package transformer_test + +import ( + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "testing" + "time" +) + +/* AMPLIFIER config,counters, state DB fields and values */ +func Test_amplifier_config_state_counter_DB_key(t *testing.T) { + var pre_req_map, cleanuptbl, cleanupstatetbl, cleanupcountertbl map[string]interface{} + var expected_get_json, url []string + + for idx, dbName := range getMdbNames() { + /* AMPLIFIER Config DB test */ + t.Log("\n\n+++++++++++++ Performing Get on configDB AMPLIFIER Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "AMPLIFIER": map[string]interface{}{ + fmt.Sprintf("AMPLIFIER-1-%d-2", idx+1): map[string]interface{}{ + "type": "EDFA", + "target-gain": 15.5, + "max-gain": 20.0, + "min-gain": 10.0, + "target-gain-tilt": 2.5, + "gain-range": "MID_GAIN_RANGE", + "amp-mode": "CONSTANT_GAIN", + "target-output-power": 0.0, + "max-output-power": 5.0, + "enabled": true, + "fiber-type-profile": "SSMF", + }, + }, + } + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_get_json = []string{fmt.Sprintf("{\"openconfig-optical-amplifier:config\":{\"amp-mode\":\"openconfig-optical-amplifier:CONSTANT_GAIN\",\"enabled\":true,\"fiber-type-profile\":\"openconfig-optical-amplifier:SSMF\",\"gain-range\":\"openconfig-optical-amplifier:MID_GAIN_RANGE\",\"max-gain\":\"20\",\"max-output-power\":\"5\",\"min-gain\":\"10\",\"name\":\"AMPLIFIER-1-%d-2\",\"target-gain\":\"15.5\",\"target-gain-tilt\":\"2.5\",\"target-output-power\":\"0\",\"type\":\"openconfig-optical-amplifier:EDFA\"}}", idx+1)} + + url = []string{fmt.Sprintf("/openconfig-optical-amplifier:optical-amplifier/amplifiers/amplifier[name=AMPLIFIER-1-%d-2]/config", idx+1)} + t.Run("Test get on configDB AMPLIFIER Key ", processGetRequest(url[0], nil, expected_get_json[0], false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on configDB AMPLIFIER Key ++++++++++++") + + /* AMPLIFIER and OSC State DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB AMPLIFIER , OSC Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "AMPLIFIER_TABLE": map[string]interface{}{ + fmt.Sprintf("AMPLIFIER-1-%d-2", idx+1): map[string]interface{}{ + "component": fmt.Sprintf("AMPLIFIER-1-%d-2", idx+1), + "location": "1-4", + "name": fmt.Sprintf("AMPLIFIER-1-%d-2", idx+1), + "amp-mode": "CONSTANT_POWER", + "egress-port": "test data", + "enabled": "true", + "fiber-type-profile": "DSF", + "gain-range": "LOW_GAIN_RANGE", + "ingress-port": "test data", + "max-gain": "10.5", + "max-output-power": "11.2", + "min-gain": "5.6", + "target-gain": "11.15", + "target-gain-tilt": "16.10", + "target-output-power": "10.30", + "type": "EDFA", + }, + }, + "OSC_TABLE": map[string]interface{}{ + fmt.Sprintf("OSC-1-%d-2", idx+1): map[string]interface{}{ + "output-frequency": "198538051", + }, + }, + } + loadDB(dbName, db.StateDB, pre_req_map) + expected_get_json = []string{fmt.Sprintf("{\"openconfig-optical-amplifier:state\":{\"amp-mode\":\"openconfig-optical-amplifier:CONSTANT_POWER\",\"component\":\"AMPLIFIER-1-%d-2\",\"egress-port\":\"test data\",\"enabled\":true,\"fiber-type-profile\":\"openconfig-optical-amplifier:DSF\",\"gain-range\":\"openconfig-optical-amplifier:LOW_GAIN_RANGE\",\"ingress-port\":\"test data\",\"max-gain\":\"10.5\",\"max-output-power\":\"11.2\",\"min-gain\":\"5.6\",\"name\":\"AMPLIFIER-1-%d-2\",\"target-gain\":\"11.15\",\"target-gain-tilt\":\"16.1\",\"target-output-power\":\"10.3\",\"type\":\"openconfig-optical-amplifier:EDFA\"}}", idx+1, idx+1), fmt.Sprintf("{\"openconfig-optical-amplifier:state\":{\"interface\":\"OSC-1-%d-2\",\"output-frequency\":\"198538051\"}}", idx+1)} + url = []string{ + fmt.Sprintf("/openconfig-optical-amplifier:optical-amplifier/amplifiers/amplifier[name=AMPLIFIER-1-%d-2]/state", idx+1), + fmt.Sprintf("/openconfig-optical-amplifier:optical-amplifier/supervisory-channels/supervisory-channel[interface=OSC-1-%d-2]/state", idx+1), + } + + for idx, url := range url { + t.Run("Test get on state DB Key for "+url, processGetRequest(url, nil, expected_get_json[idx], false)) + time.Sleep(1 * time.Second) + } + time.Sleep(1 * time.Second) + + t.Log("\n\n+++++++++++++ Done Performing Get on stateDB AMPLIFIER, OSC Key ++++++++++++") + + /* AMPLIFIER and OSC counters DB test */ + t.Log("\n\n+++++++++++++ Performing Get on counters AMPLIFIER , OSC Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "AMPLIFIER": map[string]interface{}{ + fmt.Sprintf("AMPLIFIER-1-%d-2_ActualGain:15_pm_current", idx+1): map[string]interface{}{ + "interval": "86400000000000", + "starttime": "1709251200000000000", + "max": "1.0", + "max-time": "1909276854829015912", + "min": "1.0", + "min-time": "1909276854829015912", + "instant": "1.0", + "avg": "1.0", + "current_validity": "complete", + "validity": "incomplete", + }, + }, + "OSC": map[string]interface{}{ + fmt.Sprintf("OSC-1-%d-2_OutputPower:15_pm_current", idx+1): map[string]interface{}{ + "interval": "900000000000", + "starttime": "1709251200000000000", + "max": "2.5", + "max-time": "1680168786273045375", + "min": "2.12", + "min-time": "1680168676158235913", + "instant": "2.29", + "avg": "2.32", + "current_validity": "complete", + "validity": "incomplete", + }, + }, + } + loadDB(dbName, db.CountersDB, pre_req_map) + expected_get_json = []string{"{\"openconfig-optical-amplifier:actual-gain\":{\"avg\":\"1\",\"instant\":\"1\",\"interval\":\"86400000000000\",\"max\":\"1\",\"max-time\":\"1909276854829015912\",\"min\":\"1\",\"min-time\":\"1909276854829015912\"}}", "{\"openconfig-optical-amplifier:output-power\":{\"avg\":\"2.32\",\"instant\":\"2.29\",\"interval\":\"900000000000\",\"max\":\"2.5\",\"max-time\":\"1680168786273045375\",\"min\":\"2.12\",\"min-time\":\"1680168676158235913\"}}"} + + url = []string{ + fmt.Sprintf("/openconfig-optical-amplifier:optical-amplifier/amplifiers/amplifier[name=AMPLIFIER-1-%d-2]/state/actual-gain", idx+1), + fmt.Sprintf("/openconfig-optical-amplifier:optical-amplifier/supervisory-channels/supervisory-channel[interface=OSC-1-%d-2]/state/output-power", idx+1), + } + for idx, url := range url { + t.Run("Test get on counters DB Key "+url, processGetRequest(url, nil, expected_get_json[idx], false)) + time.Sleep(1 * time.Second) + } + t.Log("\n\n+++++++++++++ Performing Get on counters AMPLIFIER, OSC Key ++++++++++++") + + //Unload the Data + cleanuptbl = map[string]interface{}{ + "AMPLIFIER": map[string]interface{}{fmt.Sprintf("AMPLIFIER-1-%d-2", idx+1): ""}, + } + unloadDB(dbName, db.ConfigDB, cleanuptbl) + + cleanupstatetbl = map[string]interface{}{ + "AMPLIFIER_TABLE": map[string]interface{}{fmt.Sprintf("AMPLIFIER-1-%d-2", idx+1): ""}, + "OSC_TABLE": map[string]interface{}{fmt.Sprintf("OSC-1-%d-2", idx+1): ""}, + } + unloadDB(dbName, db.StateDB, cleanupstatetbl) + + cleanupcountertbl = map[string]interface{}{ + "AMPLIFIER": map[string]interface{}{fmt.Sprintf("AMPLIFIER-1-%d-2_ActualGain:15_pm_current", idx+1): ""}, + "OSC": map[string]interface{}{fmt.Sprintf("OSC-1-%d-2_OutputPower:15_pm_current", idx+1): ""}, + } + unloadDB(dbName, db.CountersDB, cleanupcountertbl) + } +} + +func Test_set_amplifier_config_DB_key_and_field_xfmr(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing Create/Replace/Delete on amplifier ++++++++++++") + + for idx, dbName := range getMdbNames() { + url := fmt.Sprintf("/openconfig-optical-amplifier:optical-amplifier/amplifiers/amplifier[name=AMPLIFIER-1-%d-3]/config", idx+1) + url_body_json := fmt.Sprintf("{\"config\":{\"amp-mode\":\"openconfig-optical-amplifier:CONSTANT_GAIN\",\"enabled\":false,\"fiber-type-profile\":\"openconfig-optical-amplifier:SSMF\",\"gain-range\":\"openconfig-optical-amplifier:MID_GAIN_RANGE\",\"max-gain\":\"30\",\"max-output-power\":\"5\",\"min-gain\":\"15\",\"name\":\"AMPLIFIER-1-%d-3\",\"target-gain\":\"10.5\",\"target-gain-tilt\":\"12.5\",\"target-output-power\":\"0\",\"type\":\"openconfig-optical-amplifier:EDFA\"}}", idx+1) + + pre_req_map := map[string]interface{}{ + "AMPLIFIER": map[string]interface{}{ + fmt.Sprintf("AMPLIFIER-1-%d-3", idx+1): map[string]interface{}{ + "type": "EDFA", + "target-gain": 15.5, + "max-gain": 20.0, + "min-gain": 10.0, + "target-gain-tilt": 2.5, + "gain-range": "MID_GAIN_RANGE", + "amp-mode": "CONSTANT_GAIN", + "target-output-power": 0.0, + "max-output-power": 5.0, + "enabled": true, + "fiber-type-profile": "SSMF", + }, + }, + } + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_map := map[string]interface{}{ + "AMPLIFIER": map[string]interface{}{ + fmt.Sprintf("AMPLIFIER-1-%d-3", idx+1): map[string]interface{}{ + "type": "EDFA", + "target-gain": 10.5, + "max-gain": 30.0, + "min-gain": 15.0, + "target-gain-tilt": 12.5, + "gain-range": "MID_GAIN_RANGE", + "amp-mode": "CONSTANT_GAIN", + "target-output-power": 0.0, + "max-output-power": 5.0, + "enabled": false, + "fiber-type-profile": "SSMF", + }, + }, + } + + time.Sleep(1 * time.Second) + + //PUT Test + t.Run("Replace Test on Amplifier yang", processSetRequest(url, url_body_json, "PUT", false)) + time.Sleep(1 * time.Second) + + //GET Test + t.Run("Verify replace on Amplifier yang", verifyDbResult(rclient[dbName], fmt.Sprintf("AMPLIFIER|AMPLIFIER-1-%d-3", idx+1), expected_map, false)) + time.Sleep(1 * time.Second) + + //Delete Test + url = fmt.Sprintf("/openconfig-optical-amplifier:optical-amplifier/amplifiers/amplifier[name=AMPLIFIER-1-%d-3]/config", idx+1) + t.Run("DELETE Test on Amplifier yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + //POST Test + url = "/openconfig-optical-amplifier:optical-amplifier/amplifiers" + post_payload := fmt.Sprintf("{\"amplifier\":[{\"name\":\"AMPLIFIER-1-%d-4\",\"config\":{\"target-gain\":\"30.22\",\"max-gain\":\"41.42\",\"min-gain\":\"20.92\",\"target-gain-tilt\":\"59.22\",\"gain-range\":\"LOW_GAIN_RANGE\",\"amp-mode\":\"CONSTANT_POWER\",\"target-output-power\":\"82.33\",\"max-output-power\":\"199.99\",\"enabled\":false,\"fiber-type-profile\":\"DSF\",\"type\":\"openconfig-optical-amplifier:EDFA\"}}]}", idx+1) + t.Run("Create test on Amplifier yang", processSetRequest(url, post_payload, "POST", false)) + time.Sleep(1 * time.Second) + + expected_map = map[string]interface{}{ + "AMPLIFIER": map[string]interface{}{ + fmt.Sprintf("AMPLIFIER-1-%d-4", idx+1): map[string]interface{}{ + "type": "EDFA", + "target-gain": 30.22, + "max-gain": 41.42, + "min-gain": 20.92, + "target-gain-tilt": 59.22, + "gain-range": "LOW_GAIN_RANGE", + "amp-mode": "CONSTANT_POWER", + "target-output-power": 82.33, + "max-output-power": 199.99, + "enabled": false, + "fiber-type-profile": "DSF", + }, + }, + } + + //Verify After the POST test + t.Run("Verify After the POST test on Amplifier yang", verifyDbResult(rclient[dbName], fmt.Sprintf("AMPLIFIER|AMPLIFIER-1-%d-4", idx+1), expected_map, false)) + + //Delete After the POST test + url = fmt.Sprintf("/openconfig-optical-amplifier:optical-amplifier/amplifiers/amplifier[name=AMPLIFIER-1-%d-4]/config", idx+1) + t.Run("DELETE After the POST test on Amplifier yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = "/openconfig-optical-amplifier:optical-amplifier/amplifiers" + + //Bulk POST Test + Bulk_post_payload := fmt.Sprintf("{\"amplifier\":[{\"name\":\"AMPLIFIER-1-%d-5\",\"config\":{\"target-gain\":\"30.22\",\"max-gain\":\"41.42\",\"min-gain\":\"20.92\",\"target-gain-tilt\":\"59.22\",\"gain-range\":\"LOW_GAIN_RANGE\",\"amp-mode\":\"CONSTANT_POWER\",\"target-output-power\":\"82.33\",\"max-output-power\":\"199.99\",\"enabled\":false,\"fiber-type-profile\":\"DSF\",\"type\":\"openconfig-optical-amplifier:EDFA\"}},{\"name\":\"AMPLIFIER-1-%d-6\",\"config\":{\"target-gain\":\"20.22\",\"max-gain\":\"31.42\",\"min-gain\":\"15.92\",\"target-gain-tilt\":\"50.22\",\"gain-range\":\"MID_GAIN_RANGE\",\"amp-mode\":\"CONSTANT_POWER\",\"target-output-power\":\"12.33\",\"max-output-power\":\"100.99\",\"enabled\":true,\"fiber-type-profile\":\"DSF\",\"type\":\"openconfig-optical-amplifier:EDFA\"}}]}", idx+1, idx+1) + t.Run("Create test on Amplifier yang", processSetRequest(url, Bulk_post_payload, "POST", false)) + + expected_map = map[string]interface{}{ + "AMPLIFIER": map[string]interface{}{ + fmt.Sprintf("AMPLIFIER-1-%d-5", idx+1): map[string]interface{}{ + "type": "EDFA", + "target-gain": 30.22, + "max-gain": 41.42, + "min-gain": 20.92, + "target-gain-tilt": 59.22, + "gain-range": "LOW_GAIN_RANGE", + "amp-mode": "CONSTANT_POWER", + "target-output-power": 82.33, + "max-output-power": 199.99, + "enabled": false, + "fiber-type-profile": "DSF", + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the Bulk test + t.Run("Verify After the Bulk test on Amplifier yang", verifyDbResult(rclient[dbName], fmt.Sprintf("AMPLIFIER|AMPLIFIER-1-%d-5", idx+1), expected_map, false)) + + expected_map = map[string]interface{}{ + "AMPLIFIER": map[string]interface{}{ + fmt.Sprintf("AMPLIFIER-1-%d-6", idx+1): map[string]interface{}{ + "type": "EDFA", + "target-gain": 20.22, + "max-gain": 31.42, + "min-gain": 15.92, + "target-gain-tilt": 50.22, + "gain-range": "MID_GAIN_RANGE", + "amp-mode": "CONSTANT_POWER", + "target-output-power": 12.33, + "max-output-power": 100.99, + "enabled": true, + "fiber-type-profile": "DSF", + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the POST test + t.Run("Verify After the Bulk test on Amplifier yang", verifyDbResult(rclient[dbName], fmt.Sprintf("AMPLIFIER|AMPLIFIER-1-%d-6", idx+1), expected_map, false)) + + //Delete keys After the Bulk Test + url = fmt.Sprintf("/openconfig-optical-amplifier:optical-amplifier/amplifiers/amplifier[name=AMPLIFIER-1-%d-5]/config", idx+1) + t.Run("DELETE After the Bulk Test on Amplifier yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = fmt.Sprintf("/openconfig-optical-amplifier:optical-amplifier/amplifiers/amplifier[name=AMPLIFIER-1-%d-6]/config", idx+1) + t.Run("DELETE After the Bulk Test on Amplifier yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + } + t.Log("\n\n+++++++++++++ Done Performing Create/Replace/Delete on Amplifier ++++++++++++") +} + +func Test_Amplifier_allow_write_multiple_namespace(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing Amplifier write for multiple namespace (should be allowed) ++++++++++++") + + url := "/openconfig-optical-amplifier:optical-amplifier/amplifiers" + url_body_json := `{ + "amplifier": [ + { + "name": "AMPLIFIER-1-1-5", + "config": { + "target-gain": "30.22", + "max-gain": "41.42", + "min-gain": "20.92", + "target-gain-tilt": "59.22", + "gain-range": "LOW_GAIN_RANGE", + "amp-mode": "CONSTANT_POWER", + "target-output-power": "82.33", + "max-output-power": "199.99", + "enabled": false, + "fiber-type-profile": "DSF" + } + }, + { + "name": "AMPLIFIER-1-2-6", + "config": { + "target-gain": "20.22", + "max-gain": "31.42", + "min-gain": "15.92", + "target-gain-tilt": "50.22", + "gain-range": "MID_GAIN_RANGE", + "amp-mode": "CONSTANT_POWER", + "target-output-power": "12.33", + "max-output-power": "100.99", + "enabled": true, + "fiber-type-profile": "DSF" + } + } + ] + }` + + // false = no error expected + t.Run("Test allow writing multiple namespace for Amplifier", processSetRequest(url, url_body_json, "POST", false, nil)) + t.Log("\n\n+++++++++++++ Done Performing Amplifier write for multiple namespace ++++++++++++") +} diff --git a/translib/transformer/xfmr_otdr.go b/translib/transformer/xfmr_otdr.go new file mode 100644 index 000000000..272e2fdfa --- /dev/null +++ b/translib/transformer/xfmr_otdr.go @@ -0,0 +1,515 @@ +package transformer + +import ( + "encoding/json" + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "github.com/Azure/sonic-mgmt-common/translib/ocbinds" + log "github.com/golang/glog" + "github.com/openconfig/ygot/ygot" + "reflect" + "strconv" + "strings" +) + +func init() { + /* Key transformer for OTDR table*/ + XlateFuncBind("YangToDb_otdr_key_xfmr", YangToDb_otdr_key_xfmr) + XlateFuncBind("DbToYang_otdr_key_xfmr", DbToYang_otdr_key_xfmr) + + /* Field transformer for OTDR table*/ + XlateFuncBind("YangToDb_otdr_name_field_xfmr", YangToDb_otdr_name_field_xfmr) + XlateFuncBind("DbToYang_otdr_name_field_xfmr", DbToYang_otdr_name_field_xfmr) + + // Override the existing function with the new implementation + // Uncomment the below line to override the existing GetNamespaceFunc + // otdr_get_namespace_xfmr = customOtdrGetNamespaceFunc + + /* Get Namespace transformer for OTDR table*/ + XlateFuncBind("otdr_get_namespace_xfmr", otdr_get_namespace_xfmr) + + /* Key transformer for OTDR baseline STATE-DB tables*/ + XlateFuncBind("YangToDb_otdr_baseline_state_key_xfmr", YangToDb_otdr_baseline_state_key_xfmr) + XlateFuncBind("DbToYang_otdr_baseline_state_key_xfmr", DbToYang_otdr_baseline_state_key_xfmr) + + /* Key transformer for OTDR baseline events STATE-DB tables*/ + XlateFuncBind("YangToDb_otdr_baseline_events_state_key_xfmr", YangToDb_otdr_baseline_events_state_key_xfmr) + XlateFuncBind("DbToYang_otdr_baseline_events_state_key_xfmr", DbToYang_otdr_baseline_events_state_key_xfmr) + + /* Key transformer for OTDR current STATE-DB tables*/ + XlateFuncBind("YangToDb_otdr_current_state_key_xfmr", YangToDb_otdr_current_state_key_xfmr) + XlateFuncBind("DbToYang_otdr_current_state_key_xfmr", DbToYang_otdr_current_state_key_xfmr) + + /* Key transformer for OTDR current events STATE-DB tables*/ + XlateFuncBind("YangToDb_otdr_current_events_state_key_xfmr", YangToDb_otdr_current_events_state_key_xfmr) + XlateFuncBind("DbToYang_otdr_current_events_state_key_xfmr", DbToYang_otdr_current_events_state_key_xfmr) + + /* Key transformer for OTDR history STATE-DB tables*/ + XlateFuncBind("YangToDb_otdr_history_state_key_xfmr", YangToDb_otdr_history_state_key_xfmr) + XlateFuncBind("DbToYang_otdr_history_state_key_xfmr", DbToYang_otdr_history_state_key_xfmr) + + /* Key transformer for OTDR_EVENT history STATE-DB tables*/ + XlateFuncBind("YangToDb_otdr_history_events_state_key_xfmr", YangToDb_otdr_history_events_state_key_xfmr) + XlateFuncBind("DbToYang_otdr_history_events_state_key_xfmr", DbToYang_otdr_history_events_state_key_xfmr) + + /* Field transformer for OTDR table*/ + XlateFuncBind("YangToDb_otdr_history_scan_time_field_xfmr", YangToDb_otdr_history_scan_time_field_xfmr) + XlateFuncBind("DbToYang_otdr_history_scan_time_field_xfmr", DbToYang_otdr_history_scan_time_field_xfmr) +} + +var YangToDb_otdr_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_otdr_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + otdrkey := pathInfo.Var("name") + log.V(3).Infof("YangToDb_otdr_key_xfmr: :", otdrkey) + + return otdrkey, nil +} + +var DbToYang_otdr_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + log.V(3).Infof("DbToYang_otdr_key_xfmr: ", inParams.key) + rmap["name"] = inParams.key + + return rmap, nil +} + +var YangToDb_otdr_name_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_otdr_name_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + rmap["name"] = inParams.key + + return rmap, nil +} + +var YangToDb_otdr_baseline_state_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_otdr_baseline_state_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + otdrkey := pathInfo.Var("name") + otdrStateKey := otdrkey + "|BASELINE" + log.V(3).Infof("YangToDb_otdr_baseline_state_key_xfmr: key:", otdrStateKey) + + return otdrStateKey, nil +} + +var DbToYang_otdr_baseline_state_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + log.V(3).Info("DbToYang_otdr_baseline_state_key_xfmr: ", inParams.key) + key := inParams.key + TableKeys := strings.Split(key, "|") + + if len(TableKeys) == 2 { + rmap["name"] = TableKeys[0] + } + log.V(3).Info("DbToYang_otdr_baseline_state_key_xfmr: Name:", TableKeys[0]) + + return rmap, nil +} + +var YangToDb_otdr_baseline_events_state_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_otdr_baseline_events_state_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + otdrkey := pathInfo.Var("name") + otdrIndex := pathInfo.Var("index") + otdrStateKey := otdrkey + "|BASELINE|" + otdrIndex + + log.V(3).Infof("YangToDb_otdr_baseline_events_state_key_xfmr: key:", otdrStateKey) + + return otdrStateKey, nil +} + +var DbToYang_otdr_baseline_events_state_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + log.V(3).Info("DbToYang_otdr_baseline_events_state_key_xfmr: ", inParams.key) + key := inParams.key + TableKeys := strings.Split(key, "|") + + if len(TableKeys) == 3 { + rmap["name"] = TableKeys[0] + log.V(3).Infof("DbToYang_otdr_state_key_xfmr: TableKeys[0]:%v", TableKeys[0]) + index, err := strconv.ParseUint(TableKeys[2], 10, 32) + if err != nil { + log.Errorf("Error in parsing key %s: %v", TableKeys[2], err) + return rmap, err + } + log.V(3).Infof("DbToYang_otdr_state_key_xfmr: TableKeys[2]:%v", TableKeys[2]) + rmap["index"] = uint32(index) + } + log.V(3).Info("DbToYang_otdr_baseline_events_state_key_xfmr: Name:", TableKeys[0]) + + return rmap, nil +} + +var YangToDb_otdr_current_state_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_otdr_current_state_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + otdrkey := pathInfo.Var("name") + otdrStateKey := otdrkey + "|CURRENT" + log.V(3).Infof("YangToDb_otdr_current_state_key_xfmr: key:", otdrStateKey) + + return otdrStateKey, nil +} + +var DbToYang_otdr_current_state_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + log.V(3).Info("DbToYang_otdr_current_state_key_xfmr: ", inParams.key) + key := inParams.key + TableKeys := strings.Split(key, "|") + + if len(TableKeys) == 2 { + rmap["name"] = TableKeys[0] + } + log.V(3).Info("DbToYang_otdr_current_state_key_xfmr: Name:", TableKeys[0]) + + return rmap, nil +} + +var YangToDb_otdr_current_events_state_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_otdr_current_events_state_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + otdrkey := pathInfo.Var("name") + otdrIndex := pathInfo.Var("index") + otdrStateKey := otdrkey + "|CURRENT|" + otdrIndex + log.V(3).Infof("YangToDb_otdr_current_events_state_key_xfmr: key:", otdrStateKey) + + return otdrStateKey, nil +} + +var DbToYang_otdr_current_events_state_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + log.V(3).Info("DbToYang_otdr_current_events_state_key_xfmr: ", inParams.key) + key := inParams.key + TableKeys := strings.Split(key, "|") + + if len(TableKeys) == 3 { + rmap["name"] = TableKeys[0] + log.V(3).Infof("DbToYang_otdr_state_key_xfmr: TableKeys[0]:%v", TableKeys[0]) + index, err := strconv.ParseUint(TableKeys[2], 10, 32) + if err != nil { + log.Errorf("Error in parsing key %s: %v", TableKeys[2], err) + return rmap, err + } + log.V(3).Infof("DbToYang_otdr_state_key_xfmr: TableKeys[2]:%v", TableKeys[2]) + rmap["index"] = uint32(index) + + } + log.V(3).Info("DbToYang_otdr_current_events_state_key_xfmr: Name:", TableKeys[0]) + + return rmap, nil +} + +var YangToDb_otdr_history_state_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + var otdrStateKey string + log.V(3).Info("YangToDb_otdr_history_state_key_xfmr:uri:", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + if !strings.Contains(inParams.uri, "baseline") && + !strings.Contains(inParams.uri, "current") { + + log.V(3).Infof("YangToDb_otdr_history_state_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + otdrkey := pathInfo.Var("name") + + otdrScanTime := pathInfo.Var("scan-time") + if otdrScanTime != "" { + otdrStateKey = otdrkey + "|" + otdrScanTime + } + + log.V(3).Infof("YangToDb_otdr_history_state_key_xfmr: key:", otdrStateKey) + } + + return otdrStateKey, nil +} + +var DbToYang_otdr_history_state_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + key := inParams.key + log.V(3).Info("DbToYang_otdr_history_state_key_xfmr: key:", key) + + if !strings.Contains(key, "BASELINE") && + !strings.Contains(key, "CURRENT") { + + log.V(3).Info("DbToYang_otdr_history_state_key_xfmr: ", inParams.key) + TableKeys := strings.Split(key, "|") + + if len(TableKeys) >= 2 { + log.V(3).Infof("DbToYang_otdr_state_key_xfmr: Scan time:TableKeys[1]:%v", TableKeys[1]) + rmap["scan-time"] = TableKeys[1] + } + } + + return rmap, nil +} + +var YangToDb_otdr_history_scan_time_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_otdr_history_scan_time_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + key := inParams.key + if !strings.Contains(key, "BASELINE") && + !strings.Contains(key, "CURRENT") { + + TableKeys := strings.Split(key, "|") + + if len(TableKeys) >= 2 { + + log.V(3).Infof("DbToYang_otdr_history_scan_time_field_xfmr: Scan time:TableKeys[1]:%v", TableKeys[1]) + rmap["scan-time"] = TableKeys[1] + } + + log.V(3).Info("DbToYang_otdr_history_scan_time_field_xfmr: Name:", TableKeys[0]) + } + + return rmap, nil +} + +var YangToDb_otdr_history_events_state_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + var otdrStateKey string + log.V(3).Infof("YangToDb_otdr_history_events_state_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + if !strings.Contains(inParams.uri, "baseline") && + !strings.Contains(inParams.uri, "current") { + + otdrkey := pathInfo.Var("name") + otdrIndex := pathInfo.Var("index") + otdrScanTime := pathInfo.Var("scan-time") + otdrStateKey = otdrkey + "|" + otdrScanTime + "|" + otdrIndex + + log.V(3).Infof("YangToDb_otdr_history_events_state_key_xfmr: key:", otdrStateKey) + } + + return otdrStateKey, nil +} + +var DbToYang_otdr_history_events_state_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + key := inParams.key + if !strings.Contains(key, "BASELINE") && + !strings.Contains(key, "CURRENT") { + + log.V(3).Info("DbToYang_otdr_history_events_state_key_xfmr: ", inParams.key) + TableKeys := strings.Split(key, "|") + + if len(TableKeys) == 3 { + index, err := strconv.ParseUint(TableKeys[2], 10, 32) + if err != nil { + log.Errorf("Error in parsing key %s: %v", TableKeys[2], err) + return rmap, err + } + rmap["index"] = uint32(index) + rmap["scan-time"] = TableKeys[1] + } + + log.V(3).Infof("DbToYang_otdr_history_events_state_key_xfmr: rmap:%v", rmap) + } + return rmap, nil +} + +func getOtdrRootObj(s *ygot.GoStruct) *ocbinds.OpenconfigOpticalTimeDomainReflectometer_Otdrs { + deviceObj := (*s).(*ocbinds.Device) + return deviceObj.Otdrs +} + +var otdr_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]NamespacePayload, error) { + type payloadWithKey struct { + payload map[string]interface{} + key string + } + + var ( + key string + nsPayloadMap = make(map[string][]payloadWithKey) + ) + + log.Infof("otdr_get_namespace_xfmr: inParams: %v", inParams) + pathInfo := NewPathInfo(inParams.uri) + + // --- If Key is present in xpath payload split is not required --- + if strings.Contains(inParams.uri, "/otdr") { + key = pathInfo.Var("name") + } + + if key != "" && key != "*" { + dbName := db.GetMDBNameFromEntity(key) + log.Infof("otdr_get_namespace_xfmr: key: %s, dbName: %s", key, dbName) + + var raw interface{} + var payloads []map[string]interface{} + + if inParams.body != nil && len(inParams.body) > 0 { + if err := json.Unmarshal(inParams.body, &raw); err != nil { + return nil, fmt.Errorf("failed to unmarshal input body: %v", err) + } + + switch val := raw.(type) { + case map[string]interface{}: + payloads = append(payloads, val) + case []interface{}: + for _, item := range val { + if m, ok := item.(map[string]interface{}); ok { + payloads = append(payloads, m) + } else { + return nil, fmt.Errorf("invalid JSON payload: %v", inParams.body) + } + } + default: + return nil, fmt.Errorf("unsupported JSON structure") + } + } else { + payloads = []map[string]interface{}{} + } + + return []NamespacePayload{ + { + Namespace: dbName, + Payloads: payloads, + Key: key, + }, + }, nil + } + + var containerPrefix string + if inParams.body != nil { + bodyStr := string(inParams.body) + if idx := strings.Index(bodyStr, "["); idx != -1 { + containerPrefix = strings.TrimRight(bodyStr[:idx], ": \t\r\n") + } + } + + if inParams.ygRoot != nil { + obj := getOtdrRootObj(inParams.ygRoot) + + parseEntities := func(entities interface{}) { + val := reflect.ValueOf(entities) + if val.Kind() != reflect.Map { + log.Info("otdr_get_namespace_xfmr: entities is not a map") + return + } + + for _, key := range val.MapKeys() { + entity := val.MapIndex(key).Interface() + dbName := db.GetMDBNameFromEntity(key.String()) + + ygotStruct, ok := entity.(ygot.ValidatedGoStruct) + if !ok { + log.Errorf("Entity does not implement ygot.ValidatedGoStruct") + continue + } + + entityJson, err := ygot.EmitJSON(ygotStruct, &ygot.EmitJSONConfig{ + Format: ygot.RFC7951, + Indent: "", + SkipValidation: true, + }) + if err != nil { + log.Errorf("Failed to marshal entity: %v", err) + continue + } + + openBraces := strings.Count(containerPrefix, "{") + finalJson := fmt.Sprintf("%s:[%s]%s", containerPrefix, string(entityJson), strings.Repeat("}", openBraces)) + + var finalMap map[string]interface{} + if err := json.Unmarshal([]byte(finalJson), &finalMap); err != nil { + log.Errorf("Failed to unmarshal reconstructed payload: %v", err) + continue + } + + nsPayloadMap[dbName] = append(nsPayloadMap[dbName], payloadWithKey{ + payload: finalMap, + key: key.String(), + }) + + if outStr, err := json.MarshalIndent(finalMap, "", " "); err == nil { + log.Infof("Namespace: %s\nWrapped Output:\n%s", dbName, string(outStr)) + } + } + } + + if obj.Otdr != nil { + parseEntities(obj.Otdr) + } + } + + // --- If no payloads were found, default to wildcard (*) + if len(nsPayloadMap) == 0 { + log.Infof("otdr_get_namespace_xfmr: No specific key found, using '*' to include all DBs.") + return []NamespacePayload{ + { + Namespace: "*", + Payloads: []map[string]interface{}{}, + Key: "*", + }, + }, nil + } + + // --- Construct final NamespacePayload result --- + var result []NamespacePayload + for ns, pwkList := range nsPayloadMap { + for _, pwk := range pwkList { + result = append(result, NamespacePayload{ + Namespace: ns, + Payloads: []map[string]interface{}{pwk.payload}, + Key: pwk.key, + Commited: false, + }) + } + } + + return result, nil +} + +// Define a new implementation for GetNamespaceFunc +func customOtdrGetNamespaceFunc(inParams XfmrParams) ([]NamespacePayload, error) { + + // Your custom implementation here + nameSpaceList, err := otdr_get_namespace_xfmr(inParams) + + return nameSpaceList, err +} diff --git a/translib/transformer/xfmr_otdr_test.go b/translib/transformer/xfmr_otdr_test.go new file mode 100644 index 000000000..bcfc4c0ec --- /dev/null +++ b/translib/transformer/xfmr_otdr_test.go @@ -0,0 +1,420 @@ +//go:build xfmrtest +// +build xfmrtest + +package transformer_test + +import ( + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "testing" + "time" +) + +/* otdr config,counters, state DB fields and values */ +func Test_otdr_config_state_DB_key(t *testing.T) { + var pre_req_map, cleanuptbl, cleanupstatetbl map[string]interface{} + var expected_get_json, url []string + + for idx, dbName := range getMdbNames() { + /* OTDR config DB test */ + t.Log("\n\n+++++++++++++ Performing Get on configDB OTDR Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "OTDR": map[string]interface{}{ + fmt.Sprintf("OTDR-1-%d-2", idx+1): map[string]interface{}{ + "average-time": "2", + "backscatter-index": "2.0", + "distance-range": "2", + "enable": "true", + "end-of-fiber-threshold": "0.0", + "name": fmt.Sprintf("OTDR-1-%d-2", idx+1), + "output-frequency": "88", + "parent-port": "test_parent_port", + "period": "1", + "pulse-width": "2", + "refractive-index": "0.0", + "reflection-threshold": "0.0", + "splice-loss-threshold": "0.0", + "start-time": "0:10", + }, + }, + } + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_get_json = []string{fmt.Sprintf("{\"openconfig-optical-time-domain-reflectometer:config\":{\"fiber-profile\":{\"backscatter-index\":\"2\",\"end-of-fiber-threshold\":\"0\",\"reflection-threshold\":\"0\",\"refractive-index\":\"0\",\"splice-loss-threshold\":\"0\"},\"name\":\"OTDR-1-%d-2\",\"parent-port\":\"test_parent_port\",\"repetition\":{\"enable\":true,\"period\":1,\"start-time\":\"0:10\"},\"scanning-profile\":{\"average-time\":2,\"distance-range\":2,\"output-frequency\":\"88\",\"pulse-width\":2}}}", idx+1)} + + url = []string{fmt.Sprintf("/openconfig-optical-time-domain-reflectometer:otdrs/otdr[name=OTDR-1-%d-2]/config", idx+1)} + t.Run("Test get on config DB otdr Key.", processGetRequest(url[0], nil, expected_get_json[0], false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on configDB otdr Key ++++++++++++") + + /* OTDR State DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB otdr Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "OTDR_TABLE": map[string]interface{}{ + fmt.Sprintf("OTDR-1-%d-2", idx+1): map[string]interface{}{ + "average-time": "2", + "backscatter-index": "2.0", + "distance-accuracy": "0.0", + "distance-range": "2", + "dynamic-range": "1", + "enable": "true", + "end-of-fiber-threshold": "0.0", + "firmware-version": "test_f_version", + "hardware-version": "test_version", + "loss-dead-zone": "2.0", + "mfg-date": "test-mfg-date", + "mfg-name": "test-mfg-name", + "name": "OTDR-1-1-2", + "oper-status": "test_oper", + "output-frequency": "88", + "parent": "test_parent", + "parent-port": "test_parent_port", + "part-no": "test_part-no", + "period": "1", + "pulse-width": "2", + "reflection-dead-zone": "2.0", + "reflection-threshold": "0.0", + "refractive-index": "0.0", + "removable": "false", + "sampling-resolution": "2.0", + "scanning-status": "ACTIVE", + "serial-no": "test_serial_no", + "software-version": "test_soft", + "splice-loss-threshold": "0.0", + "start-time": "0:10", + }, + fmt.Sprintf("OTDR-1-%d-2|BASELINE", idx+1): map[string]interface{}{ + "scan-time": "2024-06-14T15:30:45.123Z+05:30", + "span-distance": "0.0", + "span-loss": "0.0", + "distance-range": "12", + "pulse-width": "12", + "average-time": "0", + "output-frequency": "2", + "update-time": "0:0:1", + "data": "test_data", + }, + fmt.Sprintf("OTDR-1-%d-2|CURRENT", idx+1): map[string]interface{}{ + "scan-time": "2024-06-14T15:30:45.123Z+05:30", + "span-distance": "0.0", + "span-loss": "0.0", + "distance-range": "12", + "pulse-width": "12", + "average-time": "0", + "output-frequency": "2", + "update-time": "0:0:1", + "data": "test_data", + }, + fmt.Sprintf("OTDR-1-%d-2|2024-06-14T15:30:45.123Z+05:30", idx+1): map[string]interface{}{ + "scan-time": "2024-06-14T15:30:45.123Z+05:30", + "span-distance": "0.0", + "span-loss": "0.0", + "distance-range": "12", + "pulse-width": "12", + "average-time": "0", + "output-frequency": "2", + "update-time": "0:0:1", + "data": "test_data", + }, + }, + "OTDR_EVENT_TABLE": map[string]interface{}{ + fmt.Sprintf("OTDR-1-%d-2|BASELINE|101", idx+1): map[string]interface{}{ + "index": "101", + "length": "0.0", + "loss": "0.0", + "accumulate-loss": "0.0", + "type": "REFLECTION", + "reflection": "0.0", + }, + fmt.Sprintf("OTDR-1-%d-2|CURRENT|101", idx+1): map[string]interface{}{ + "index": "101", + "length": "0.0", + "loss": "0.0", + "accumulate-loss": "0.0", + "type": "REFLECTION", + "reflection": "0.0", + }, + fmt.Sprintf("OTDR-1-%d-2|2024-06-14T15:30:45.123Z+05:30|101", idx+1): map[string]interface{}{ + "index": "101", + "length": "0.0", + "loss": "0.0", + "accumulate-loss": "0.0", + "type": "REFLECTION", + "reflection": "0.0", + }, + }, + } + loadDB(dbName, db.StateDB, pre_req_map) + expected_get_json = []string{ + fmt.Sprintf("{\"openconfig-optical-time-domain-reflectometer:state\":{\"fiber-profile\":{\"backscatter-index\":\"2\",\"end-of-fiber-threshold\":\"0\",\"reflection-threshold\":\"0\",\"refractive-index\":\"0\",\"splice-loss-threshold\":\"0\"},\"name\":\"OTDR-1-%d-2\",\"parent-port\":\"test_parent_port\",\"repetition\":{\"enable\":true,\"period\":1,\"start-time\":\"0:10\"},\"scanning-profile\":{\"average-time\":2,\"distance-range\":2,\"output-frequency\":\"88\",\"pulse-width\":2},\"scanning-status\":\"openconfig-platform-types:ACTIVE\",\"specification\":{\"distance-accuracy\":\"0\",\"dynamic-range\":1,\"loss-dead-zone\":\"2\",\"reflection-dead-zone\":\"2\",\"sampling-resolution\":\"2\"}}}", idx+1), + + "{\"openconfig-optical-time-domain-reflectometer:baseline-result\":{\"events\":{\"event\":[{\"accumulate-loss\":\"0\",\"index\":101,\"length\":\"0\",\"loss\":\"0\",\"reflection\":\"0\",\"type\":\"REFLECTION\"}],\"scan-time\":\"2024-06-14T15:30:45.123Z+05:30\",\"span-distance\":\"0\",\"span-loss\":\"0\"},\"scanning-profile\":{\"average-time\":0,\"distance-range\":12,\"output-frequency\":\"2\",\"pulse-width\":12},\"trace\":{\"data\":\"test_data\",\"update-time\":\"0:0:1\"}}}", + + "{\"openconfig-optical-time-domain-reflectometer:event\":[{\"accumulate-loss\":\"0\",\"index\":101,\"length\":\"0\",\"loss\":\"0\",\"reflection\":\"0\",\"type\":\"REFLECTION\"}]}", + + "{\"openconfig-optical-time-domain-reflectometer:events\":{\"event\":[{\"accumulate-loss\":\"0\",\"index\":101,\"length\":\"0\",\"loss\":\"0\",\"reflection\":\"0\",\"type\":\"REFLECTION\"}],\"scan-time\":\"2024-06-14T15:30:45.123Z+05:30\",\"span-distance\":\"0\",\"span-loss\":\"0\"}}", + + "{\"openconfig-optical-time-domain-reflectometer:current-result\":{\"events\":{\"event\":[{\"accumulate-loss\":\"0\",\"index\":101,\"length\":\"0\",\"loss\":\"0\",\"reflection\":\"0\",\"type\":\"REFLECTION\"}],\"scan-time\":\"2024-06-14T15:30:45.123Z+05:30\",\"span-distance\":\"0\",\"span-loss\":\"0\"},\"scanning-profile\":{\"average-time\":0,\"distance-range\":12,\"output-frequency\":\"2\",\"pulse-width\":12},\"trace\":{\"data\":\"test_data\",\"update-time\":\"0:0:1\"}}}", + + "{\"openconfig-optical-time-domain-reflectometer:event\":[{\"accumulate-loss\":\"0\",\"index\":101,\"length\":\"0\",\"loss\":\"0\",\"reflection\":\"0\",\"type\":\"REFLECTION\"}]}", + + "{\"openconfig-optical-time-domain-reflectometer:events\":{\"event\":[{\"accumulate-loss\":\"0\",\"index\":101,\"length\":\"0\",\"loss\":\"0\",\"reflection\":\"0\",\"type\":\"REFLECTION\"}],\"scan-time\":\"2024-06-14T15:30:45.123Z+05:30\",\"span-distance\":\"0\",\"span-loss\":\"0\"}}", + } + + url = []string{ + fmt.Sprintf("/openconfig-optical-time-domain-reflectometer:otdrs/otdr[name=OTDR-1-%d-2]/state", idx+1), + fmt.Sprintf("/openconfig-optical-time-domain-reflectometer:otdrs/otdr[name=OTDR-1-%d-2]/baseline-result", idx+1), + fmt.Sprintf("/openconfig-optical-time-domain-reflectometer:otdrs/otdr[name=OTDR-1-%d-2]/baseline-result/events/event[index=101]", idx+1), + fmt.Sprintf("/openconfig-optical-time-domain-reflectometer:otdrs/otdr[name=OTDR-1-%d-2]/baseline-result/events", idx+1), + fmt.Sprintf("/openconfig-optical-time-domain-reflectometer:otdrs/otdr[name=OTDR-1-%d-2]/current-result", idx+1), + fmt.Sprintf("/openconfig-optical-time-domain-reflectometer:otdrs/otdr[name=OTDR-1-%d-2]/current-result/events/event[index=101]", idx+1), + fmt.Sprintf("/openconfig-optical-time-domain-reflectometer:otdrs/otdr[name=OTDR-1-%d-2]/current-result/events", idx+1), + } + for idx, url := range url { + t.Run("Test get on state DB otdr Key for "+url, processGetRequest(url, nil, expected_get_json[idx], false)) + time.Sleep(1 * time.Second) + } + + t.Log("\n\n+++++++++++++ Done Performing Get on stateDB otdr Key ++++++++++++") + //Unload the Data + cleanuptbl = map[string]interface{}{ + "OTDR": map[string]interface{}{ + fmt.Sprintf("OTDR-1-%d-2", idx+1): "", + }, + } + unloadDB(dbName, db.ConfigDB, cleanuptbl) + + cleanupstatetbl = map[string]interface{}{ + "OTDR_TABLE": map[string]interface{}{ + fmt.Sprintf("OTDR-1-%d-2", idx+1): "", + fmt.Sprintf("OTDR-1-%d-2|BASELINE", idx+1): "", + fmt.Sprintf("OTDR-1-%d-2|2024-06-14T15:30:45.123Z+05:30", idx+1): "", + fmt.Sprintf("OTDR-1-%d-2|CURRENT", idx+1): "", + }, + "OTDR_EVENT_TABLE": map[string]interface{}{ + fmt.Sprintf("OTDR-1-%d-2|CURRENT|101", idx+1): "", + fmt.Sprintf("OTDR-1-%d-2|BASELINE|101", idx+1): "", + fmt.Sprintf("OTDR-1-%d-2|2024-06-14T15:30:45.123Z+05:30|101", idx+1): "", + }, + } + unloadDB(dbName, db.StateDB, cleanupstatetbl) + } +} + +func Test_set_OTDR_config_DB_key_and_field_xfmr(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing Create/Replace/Delete on OTDR ++++++++++++") + + for idx, dbName := range getMdbNames() { + url := fmt.Sprintf("/openconfig-optical-time-domain-reflectometer:otdrs/otdr[name=OTDR-1-%d-2]/config", idx+1) + url_body_json := "{\"config\":{\"fiber-profile\":{\"backscatter-index\":\"28.78\",\"refractive-index\":\"11.11\",\"reflection-threshold\":\"22.22\",\"splice-loss-threshold\":\"33.33\",\"end-of-fiber-threshold\":\"44.44\"},\"scanning-profile\":{\"distance-range\":8,\"pulse-width\":7,\"average-time\":9,\"output-frequency\":\"20\"},\"repetition\":{\"period\":10,\"start-time\":\"2024-07-03T14:30:00.123Z+03:00\",\"enable\":false}}}" + + pre_req_map := map[string]interface{}{ + "OTDR": map[string]interface{}{ + fmt.Sprintf("OTDR-1-%d-2", idx+1): map[string]interface{}{ + "average-time": "2", + "backscatter-index": "2.0", + "distance-range": "2", + "enable": "true", + "end-of-fiber-threshold": "0.0", + "output-frequency": "88", + "period": "1", + "pulse-width": "2", + "refractive-index": "0.0", + "reflection-threshold": "0.0", + "splice-loss-threshold": "0.0", + "start-time": "0:10", + }, + }, + } + + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_map := map[string]interface{}{ + "OTDR": map[string]interface{}{ + fmt.Sprintf("OTDR-1-%d-2", idx+1): map[string]interface{}{ + "average-time": "9", + "backscatter-index": "28.78", + "distance-range": "8", + "enable": "false", + "end-of-fiber-threshold": "44.44", + "output-frequency": "20", + "period": "10", + "pulse-width": "7", + "refractive-index": "11.11", + "reflection-threshold": "22.22", + "splice-loss-threshold": "33.33", + "start-time": "2024-07-03T14:30:00.123Z+03:00", + }, + }, + } + time.Sleep(1 * time.Second) + + //PUT Test + t.Run("Replace Test on OTDR yang", processSetRequest(url, url_body_json, "PUT", false)) + time.Sleep(1 * time.Second) + + //GET Test + t.Run("Verify replace on OTDR yang", verifyDbResult(rclient[dbName], fmt.Sprintf("OTDR|OTDR-1-%d-2", idx+1), expected_map, false)) + time.Sleep(1 * time.Second) + + //Delete Test + url = fmt.Sprintf("/openconfig-optical-time-domain-reflectometer:otdrs/otdr[name=OTDR-1-%d-2]/config", idx+1) + t.Run("DELETE Test on OTDR yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + //POST Test + url = "/openconfig-optical-time-domain-reflectometer:otdrs" + post_payload := fmt.Sprintf("{\"otdr\":[{\"name\":\"OTDR-1-%d-3\",\"config\":{\"fiber-profile\":{\"backscatter-index\":\"18.18\",\"refractive-index\":\"11.11\",\"reflection-threshold\":\"22.22\",\"splice-loss-threshold\":\"33.33\",\"end-of-fiber-threshold\":\"44.44\"},\"scanning-profile\":{\"distance-range\":15,\"pulse-width\":7,\"average-time\":10,\"output-frequency\":\"31\"},\"repetition\":{\"period\":10,\"start-time\":\"2024-07-03T14:30:00.123Z+03:00\",\"enable\":true}}}]}", idx+1) + t.Run("Create test on OTDR yang", processSetRequest(url, post_payload, "POST", false)) + time.Sleep(1 * time.Second) + + expected_map = map[string]interface{}{ + "OTDR": map[string]interface{}{ + fmt.Sprintf("OTDR-1-%d-3", idx+1): map[string]interface{}{ + "average-time": "10", + "backscatter-index": "18.18", + "distance-range": "15", + "enable": "true", + "end-of-fiber-threshold": "44.44", + "output-frequency": "31", + "period": "10", + "pulse-width": "7", + "refractive-index": "11.11", + "reflection-threshold": "22.22", + "splice-loss-threshold": "33.33", + "start-time": "2024-07-03T14:30:00.123Z+03:00", + }, + }, + } + + //Verify After the POST test + t.Run("Verify After the POST test on OTDR yang", verifyDbResult(rclient[dbName], fmt.Sprintf("OTDR|OTDR-1-%d-3", idx+1), expected_map, false)) + + //Delete After the POST test + url = fmt.Sprintf("/openconfig-optical-time-domain-reflectometer:otdrs/otdr[name=OTDR-1-%d-3]/config", idx+1) + t.Run("DELETE After the POST test on OTDR yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = "/openconfig-optical-time-domain-reflectometer:otdrs" + + //Bulk POST Test + Bulk_post_payload := fmt.Sprintf("{\"otdr\":[{\"name\":\"OTDR-1-%d-4\",\"config\":{\"fiber-profile\":{\"backscatter-index\":\"18.18\",\"refractive-index\":\"11.11\",\"reflection-threshold\":\"22.22\",\"splice-loss-threshold\":\"33.33\",\"end-of-fiber-threshold\":\"44.44\"},\"scanning-profile\":{\"distance-range\":15,\"pulse-width\":7,\"average-time\":10,\"output-frequency\":\"31\"},\"repetition\":{\"period\":10,\"start-time\":\"2024-07-03T14:30:00.123Z+03:00\",\"enable\":true}}},{\"name\":\"OTDR-1-%d-5\",\"config\":{\"fiber-profile\":{\"backscatter-index\":\"28.78\",\"refractive-index\":\"11.11\",\"reflection-threshold\":\"22.22\",\"splice-loss-threshold\":\"33.33\",\"end-of-fiber-threshold\":\"44.44\"},\"scanning-profile\":{\"distance-range\":8,\"pulse-width\":7,\"average-time\":9,\"output-frequency\":\"20\"},\"repetition\":{\"period\":10,\"start-time\":\"2024-07-03T14:30:00.123Z+03:00\",\"enable\":false}}}]}", idx+1, idx+1) + t.Run("Create test on terminal_device yang", processSetRequest(url, Bulk_post_payload, "POST", false)) + + expected_map = map[string]interface{}{ + "OTDR": map[string]interface{}{ + fmt.Sprintf("OTDR-1-%d-4", idx+1): map[string]interface{}{ + "average-time": "10", + "backscatter-index": "18.18", + "distance-range": "15", + "enable": "true", + "end-of-fiber-threshold": "44.44", + "output-frequency": "31", + "period": "10", + "pulse-width": "7", + "refractive-index": "11.11", + "reflection-threshold": "22.22", + "splice-loss-threshold": "33.33", + "start-time": "2024-07-03T14:30:00.123Z+03:00", + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the Bulk test + t.Run("Verify After the Bulk test on OTDR yang", verifyDbResult(rclient[dbName], fmt.Sprintf("OTDR|OTDR-1-%d-4", idx+1), expected_map, false)) + + expected_map = map[string]interface{}{ + "OTDR": map[string]interface{}{ + fmt.Sprintf("OTDR-1-%d-5", idx+1): map[string]interface{}{ + "average-time": "9", + "backscatter-index": "28.78", + "distance-range": "8", + "enable": "false", + "end-of-fiber-threshold": "44.44", + "output-frequency": "20", + "period": "10", + "pulse-width": "7", + "refractive-index": "11.11", + "reflection-threshold": "22.22", + "splice-loss-threshold": "33.33", + "start-time": "2024-07-03T14:30:00.123Z+03:00", + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the POST test + t.Run("Verify After the Bulk test on OTDR yang", verifyDbResult(rclient[dbName], fmt.Sprintf("OTDR|OTDR-1-%d-5", idx+1), expected_map, false)) + + //Delete keys After the Bulk Test + url = fmt.Sprintf("/openconfig-optical-time-domain-reflectometer:otdrs/otdr[name=OTDR-1-%d-4]/config", idx+1) + t.Run("DELETE After the Bulk Test on OTDR yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = fmt.Sprintf("/openconfig-optical-time-domain-reflectometer:otdrs/otdr[name=OTDR-1-%d-5]/config", idx+1) + t.Run("DELETE After the Bulk Test on OTDR yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + } + + t.Log("\n\n+++++++++++++ Done Performing Create/Replace/Delete on OTDR ++++++++++++") +} + +func Test_OTDR_allow_write_multiple_namespace(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing OTDR write for multiple namespace (should be allowed) ++++++++++++") + + url := "/openconfig-optical-time-domain-reflectometer:otdrs" + url_body_json := `{ + "otdr": [ + { + "name": "OTDR-1-1-4", + "config": { + "fiber-profile": { + "backscatter-index": "18.18", + "refractive-index": "11.11", + "reflection-threshold": "22.22", + "splice-loss-threshold": "33.33", + "end-of-fiber-threshold": "44.44" + }, + "scanning-profile": { + "distance-range": 15, + "pulse-width": 7, + "average-time": 10, + "output-frequency": "31" + }, + "repetition": { + "period": 10, + "start-time": "2024-07-03T14:30:00.123Z+03:00", + "enable": true + } + } + }, + { + "name": "OTDR-1-3-5", + "config": { + "fiber-profile": { + "backscatter-index": "28.78", + "refractive-index": "11.11", + "reflection-threshold": "22.22", + "splice-loss-threshold": "33.33", + "end-of-fiber-threshold": "44.44" + }, + "scanning-profile": { + "distance-range": 8, + "pulse-width": 7, + "average-time": 9, + "output-frequency": "20" + }, + "repetition": { + "period": 10, + "start-time": "2024-07-03T14:30:00.123Z+03:00", + "enable": false + } + } + } + ] + }` + + // false = no error expected + t.Run("Test allow writing multiple namespace for OTDR", processSetRequest(url, url_body_json, "POST", false, nil)) + + t.Log("\n\n+++++++++++++ Done Performing OTDR write for multiple namespace ++++++++++++") +} diff --git a/translib/transformer/xfmr_pfm.go b/translib/transformer/xfmr_pfm.go new file mode 100644 index 000000000..c45e76d52 --- /dev/null +++ b/translib/transformer/xfmr_pfm.go @@ -0,0 +1,247 @@ +package transformer + +import ( + "errors" + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + log "github.com/golang/glog" + "strconv" + "strings" +) + +const ( + OC_COMPONENT_TBL = "OC_COMPONENT" + OCH_TBL = "OCH" + TRANSCEIVER_TBL = "TRANSCEIVER" +) + +func init() { + /* Table transformer for tables in component container*/ + XlateFuncBind("pfm_table_xfmr", pfm_table_xfmr) + + /* Key transformer for OC_COMPONENT_TABLE table*/ + XlateFuncBind("YangToDb_component_key_xfmr", YangToDb_component_key_xfmr) + XlateFuncBind("DbToYang_component_key_xfmr", DbToYang_component_key_xfmr) + + /* Field transformer for OC_COMPONENT_TABLE table*/ + XlateFuncBind("YangToDb_component_field_xfmr", YangToDb_component_field_xfmr) + XlateFuncBind("DbToYang_component_field_xfmr", DbToYang_component_field_xfmr) + + /* Key transformer for transceiver table*/ + XlateFuncBind("YangToDb_pfm_transceiver_key_xfmr", YangToDb_pfm_transceiver_key_xfmr) + XlateFuncBind("DbToYang_pfm_transceiver_key_xfmr", DbToYang_pfm_transceiver_key_xfmr) + + XlateFuncBind("pfm_post_xfmr", pfm_post_xfmr) + +} + +var YangToDb_component_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.Infof("YangToDb_component_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + ochkey := pathInfo.Var("name") + log.Infof("YangToDb_component_key_xfmr: :", ochkey) + + return ochkey, nil +} + +var DbToYang_component_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + log.Infof("DbToYang_component_key_xfmr: ", inParams.key) + rmap["name"] = inParams.key + + return rmap, nil +} + +var YangToDb_component_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_component_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + rmap["name"] = inParams.key + + return rmap, nil +} + +var pfm_table_xfmr TableXfmrFunc = func(inParams XfmrParams) ([]string, error) { + var tblList []string + pathInfo := NewPathInfo(inParams.uri) + name := pathInfo.Var("name") + + log.Infof("Pfm_table_xfmr inParams.d:%v ", inParams.d) + + // Determine the suffix based on DBNo + suffix := "" + if inParams.d.Opts.DBNo == db.StateDB { + suffix = "_TABLE" + } + + // Base entries for the case when name is empty + baseEntries := []string{"FAN", "PSU", "CU", "CHASSIS", "OC_COMPONENT"} + + if len(name) == 0 { + // Append the suffix + tblName := "OC_COMPONENT" + suffix + tblList = append(tblList, tblName) + log.Info("Pfm_table_xfmr NO KEY tblList= ", tblList) + return tblList, nil + } + + // Check the prefix and append the corresponding entry + for _, entry := range baseEntries { + if strings.HasPrefix(name, entry) { + tblList = append(tblList, entry) + break + } + } + + // If no prefix matched, default to OC_COMPONENT + if len(tblList) == 0 { + tblList = append(tblList, "OC_COMPONENT") + } + + // Append "_TABLE" if its STATE_DB + if len(tblList) > 0 && suffix != "" { + tblList[len(tblList)-1] += suffix + } + + log.Info("Pfm_table_xfmr tblList= ", tblList) + return tblList, nil +} + +var YangToDb_pfm_transceiver_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.Infof("YangToDb_pfm_transceiver_key_xfmr : root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("name") + index := pathInfo.Var("index") + + if strings.Contains(inParams.uri, "/channel") { + if index != "" { + if strings.Contains(index, "CH") { + key += "|" + index + } else { + key += "|CH-" + index + } + } + } + + log.Infof("YangToDb_pfm_transceiver_key_xfmr : key:", key) + + return key, nil +} + +var DbToYang_pfm_transceiver_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_pfm_transceiver_key_xfmr: ", inParams.key) + rmap := make(map[string]interface{}, 1) + if strings.Contains(inParams.uri, "/channel") { + TableKeys := strings.Split(inParams.key, "|") + if len(TableKeys) < 2 { + log.Errorf("length of Table Key is less than 2: %v", TableKeys) + return nil, errors.New("length of Table Key is less than 2") + } + + indexKey := strings.Split(TableKeys[1], "-") + if len(indexKey) < 2 { + log.Errorf("length of Index Key is less than 2: %v", indexKey) + return nil, errors.New("length of Index Key is less than 2") + } + + index, err := strconv.ParseUint(indexKey[1], 10, 16) + if err != nil { + log.Errorf("Error parsing index: %v", err) + return nil, err + } + rmap["index"] = index + } else { + rmap["name"] = inParams.key + } + + log.Info("DbToYang_pfm_transceiver_key_xfmr: rmap", rmap) + return rmap, nil +} + +var pfm_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[string]map[string]db.Value, error) { + + if inParams.dbDataMap == nil || *inParams.dbDataMap == nil { + return nil, fmt.Errorf("dbDataMap is nil") + } + + retDbDataMap := (*inParams.dbDataMap)[inParams.curDb] + if retDbDataMap == nil { + retDbDataMap = make(map[string]map[string]db.Value) + (*inParams.dbDataMap)[inParams.curDb] = retDbDataMap + } + + log.Infof("pfm_post_xfmr: Entering Request URI path = %v", inParams.requestUri) + + // ---------- CREATE ---------- + if inParams.oper == CREATE { + if strings.Contains(inParams.requestUri, "components") { + for _, table := range []string{OCH_TBL, TRANSCEIVER_TBL} { + if retDbDataMap[table] == nil { + continue + } + + if retDbDataMap[OC_COMPONENT_TBL] == nil { + retDbDataMap[OC_COMPONENT_TBL] = make(map[string]db.Value) + } + + for keyName := range retDbDataMap[table] { + // Only add if not already present in dbDataMap + if _, exists := retDbDataMap[OC_COMPONENT_TBL][keyName]; !exists { + log.Infof("pfm_post_xfmr: Adding key %v to OC_COMPONENT_TBL", keyName) + retDbDataMap[OC_COMPONENT_TBL][keyName] = db.Value{} // empty value marks new entry + } + } + } + } + } + + // ---------- DELETE ---------- + if inParams.oper == DELETE { + pathInfo := NewPathInfo(inParams.requestUri) + keyName := pathInfo.Var("name") + + // Determine table based on URI (similar to original logic) + var tableTsName string + switch { + case strings.Contains(inParams.requestUri, "OCH") && !strings.Contains(inParams.requestUri, "optical-channel"): + tableTsName = OCH_TBL + case strings.Contains(inParams.requestUri, "OCH") && strings.Contains(inParams.requestUri, "optical-channel"): + tableTsName = OC_COMPONENT_TBL + case strings.Contains(inParams.requestUri, "TRANSCEIVER") && strings.Contains(inParams.requestUri, "transceiver"): + tableTsName = OC_COMPONENT_TBL + case strings.Contains(inParams.requestUri, "TRANSCEIVER") && !strings.Contains(inParams.requestUri, "transceiver"): + tableTsName = TRANSCEIVER_TBL + } + + if tableTsName != "" { + if retDbDataMap[tableTsName] == nil { + retDbDataMap[tableTsName] = make(map[string]db.Value) + } + + if keyName != "" { + log.Infof("pfm_post_xfmr: Marking key %v in %v for deletion", keyName, tableTsName) + retDbDataMap[tableTsName][keyName] = db.Value{} // marks deletion + } else { + log.Infof("pfm_post_xfmr: Clearing all entries in table %v", tableTsName) + retDbDataMap[tableTsName] = make(map[string]db.Value) // clears table + } + } + } + + log.Infof("pfm_post_xfmr: Updated dbDataMap: %+v", retDbDataMap) + return retDbDataMap, nil +} diff --git a/translib/transformer/xfmr_pfm_test.go b/translib/transformer/xfmr_pfm_test.go new file mode 100644 index 000000000..06a78ea1f --- /dev/null +++ b/translib/transformer/xfmr_pfm_test.go @@ -0,0 +1,412 @@ +//go:build xfmrtest +// +build xfmrtest + +package transformer_test + +import ( + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "testing" + "time" +) + +/* TRANSCEIVER config, state DB fields and values */ +func Test_pfm_transceiver_config_state_DB_key(t *testing.T) { + var pre_req_map, cleanuptbl, cleanupstatetbl map[string]interface{} + var expected_get_json, url []string + + for idx, dbName := range getMdbNames() { + /* TRANSCEIVER config DB test */ + t.Log("\n\n+++++++++++++ Performing Get on configDB TRANSCEIVER Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "OC_COMPONENT": map[string]interface{}{ + fmt.Sprintf("TRANSCEIVER-1-%d-C2", idx+1): map[string]interface{}{ + "name": fmt.Sprintf("TRANSCEIVER-1-%d-C2", idx+1), + }, + }, + "TRANSCEIVER": map[string]interface{}{ + fmt.Sprintf("TRANSCEIVER-1-%d-C2", idx+1): map[string]interface{}{ + "enabled": "true", + "fec-mode": "FEC_AUTO", + "ethernet-pmd-preconf": "ETH_100GBASE_SR10", + }, + }, + } + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_get_json = []string{"{\"openconfig-platform-transceiver:config\":{\"enabled\":true,\"ethernet-pmd-preconf\":\"openconfig-transport-types:ETH_100GBASE_SR10\",\"fec-mode\":\"openconfig-platform-types:FEC_AUTO\"}}"} + + url = []string{fmt.Sprintf("/openconfig-platform:components/component[name=TRANSCEIVER-1-%d-C2]/openconfig-platform-transceiver:transceiver/config", idx+1)} + t.Run("Test get on configDB TRANSCEIVER Key", processGetRequest(url[0], nil, expected_get_json[0], false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on configDB TRANSCEIVER Key ++++++++++++") + + /* TRANSCEIVER State DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB TRANSCEIVER Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "TRANSCEIVER_TABLE": map[string]interface{}{ + fmt.Sprintf("TRANSCEIVER-1-%d-C2", idx+1): map[string]interface{}{ + "vendor": "VendorX", + "vendor-rev": "1.0", + "date-code": "2024-10-03", + "vendor-part": "VX-1234", + "fec-mode": "FEC_ENABLED", + "form-factor": "QSFP28", + "present": "PRESENT", + "enabled": "true", + "fault-condition": "false", + "connector-type": "LC_CONNECTOR", + "ethernet-pmd": "ETH_100GBASE_CWDM4", + }, + }, + "PHYSICAL_CHANNEL_TABLE": map[string]interface{}{ + fmt.Sprintf("TRANSCEIVER-1-%d-C2|CH-1", idx+1): map[string]interface{}{ + "index": 1, + "output-frequency": "193000000", + "tx-laser": "true", + }, + }, + } + loadDB(dbName, db.StateDB, pre_req_map) + expected_get_json = []string{ + "{\"openconfig-platform-transceiver:state\":{\"connector-type\":\"openconfig-transport-types:LC_CONNECTOR\",\"date-code\":\"2024-10-03\",\"enabled\":true,\"ethernet-pmd\":\"openconfig-transport-types:ETH_100GBASE_CWDM4\",\"fault-condition\":false,\"fec-mode\":\"openconfig-platform-types:FEC_ENABLED\",\"form-factor\":\"openconfig-transport-types:QSFP28\",\"present\":\"PRESENT\",\"vendor\":\"VendorX\",\"vendor-part\":\"VX-1234\",\"vendor-rev\":\"1.0\"}}", + "{\"openconfig-platform-transceiver:state\":{\"index\":1,\"output-frequency\":\"193000000\",\"tx-laser\":true}}", + } + url = []string{ + fmt.Sprintf("/openconfig-platform:components/component[name=TRANSCEIVER-1-%d-C2]/openconfig-platform-transceiver:transceiver/state", idx+1), + fmt.Sprintf("/openconfig-platform:components/component[name=TRANSCEIVER-1-%d-C2]/openconfig-platform-transceiver:transceiver/physical-channels/channel[index=1]/state", idx+1), + } + for idx, url := range url { + t.Run("Test get on state DB TRANSCEIVER Key for "+url, processGetRequest(url, nil, expected_get_json[idx], false)) + time.Sleep(1 * time.Second) + } + + t.Log("\n\n+++++++++++++ Done Performing Get on stateDB TRANSCEIVER Key ++++++++++++") + + //Unload the Data + cleanuptbl = map[string]interface{}{ + "OC_COMPONENT": map[string]interface{}{ + fmt.Sprintf("TRANSCEIVER-1-%d-C2", idx+1): "", + }, + "TRANSCEIVER": map[string]interface{}{ + fmt.Sprintf("TRANSCEIVER-1-%d-C2", idx+1): "", + }, + } + unloadDB(dbName, db.ConfigDB, cleanuptbl) + + cleanupstatetbl = map[string]interface{}{ + "TRANSCEIVER_TABLE": map[string]interface{}{ + fmt.Sprintf("TRANSCEIVER-1-%d-C2", idx+1): "", + }, + "PHYSICAL_CHANNEL_TABLE": map[string]interface{}{ + fmt.Sprintf("TRANSCEIVER-1-%d-C2|CH-1", idx+1): "", + }, + } + unloadDB(dbName, db.StateDB, cleanupstatetbl) + } +} + +func pfmMapDetails() map[string]interface{} { + return map[string]interface{}{ + "serial-no": "test_serial_no", + "part-no": "10", + "mfg-name": "test_mfg_name", + "mfg-date": "09-10-24", + "hardware-version": "test_hw_version", + "oper-status": "ACTIVE", + "empty": "false", + "removable": "true", + "parent": "ACTIVE", + "software-version": "test_software_version", + "memory-available": "100", + "memory-utilized": "200", + } +} + +/* FAN state DB fields and values */ +func Test_fan_state_DB_key(t *testing.T) { + var pre_req_map, cleanuptbl, cleanupstatetbl map[string]interface{} + var expected_get_json, url string + + pfmValues := pfmMapDetails() + + /* FAN State DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB FAN Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "FAN": map[string]interface{}{ + "FAN-1-7": pfmValues, + }, + } + loadDB(hostDBName, db.ConfigDB, pre_req_map) + + pre_req_map = map[string]interface{}{ + "FAN_TABLE": map[string]interface{}{ + "FAN-1-7": pfmValues, + }, + } + time.Sleep(1 * time.Second) + loadDB(hostDBName, db.StateDB, pre_req_map) + expected_get_json = "{\"openconfig-platform:state\":{\"empty\":false,\"hardware-version\":\"test_hw_version\",\"memory\":{\"available\":\"100\",\"utilized\":\"200\"},\"mfg-date\":\"09-10-24\",\"mfg-name\":\"test_mfg_name\",\"name\":\"FAN-1-7\",\"oper-status\":\"openconfig-platform-types:ACTIVE\",\"parent\":\"ACTIVE\",\"part-no\":\"10\",\"removable\":true,\"serial-no\":\"test_serial_no\",\"software-version\":\"test_software_version\"}}" + url = "/openconfig-platform:components/component[name=FAN-1-7]/state" + t.Run("Test get on state DB FAN Key for "+url, processGetRequest(url, nil, expected_get_json, false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on stateDB FAN Key ++++++++++++") + + //Unload the data + cleanuptbl = map[string]interface{}{ + "FAN": map[string]interface{}{ + "FAN-1-7": "", + }, + } + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + cleanupstatetbl = map[string]interface{}{ + "FAN_TABLE": map[string]interface{}{ + "FAN-1-7": "", + }, + } + unloadDB(hostDBName, db.StateDB, cleanupstatetbl) +} + +/* PSU state DB fields and values */ +func Test_psu_state_DB_key(t *testing.T) { + var pre_req_map, cleanuptbl, cleanupstatetbl map[string]interface{} + var expected_get_json, url string + + pfmValues := pfmMapDetails() + + /* PSU State DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB PSU Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "PSU": map[string]interface{}{ + "PSU-1-5": pfmValues, + }, + } + loadDB(hostDBName, db.ConfigDB, pre_req_map) + + pre_req_map = map[string]interface{}{ + "PSU_TABLE": map[string]interface{}{ + "PSU-1-5": pfmValues, + }, + } + time.Sleep(1 * time.Second) + loadDB(hostDBName, db.StateDB, pre_req_map) + expected_get_json = "{\"openconfig-platform:state\":{\"empty\":false,\"hardware-version\":\"test_hw_version\",\"memory\":{\"available\":\"100\",\"utilized\":\"200\"},\"mfg-date\":\"09-10-24\",\"mfg-name\":\"test_mfg_name\",\"name\":\"PSU-1-5\",\"oper-status\":\"openconfig-platform-types:ACTIVE\",\"parent\":\"ACTIVE\",\"part-no\":\"10\",\"removable\":true,\"serial-no\":\"test_serial_no\",\"software-version\":\"test_software_version\"}}" + url = "/openconfig-platform:components/component[name=PSU-1-5]/state" + t.Run("Test get on state DB PSU Key for "+url, processGetRequest(url, nil, expected_get_json, false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on stateDB PSU Key ++++++++++++") + + //Unload the data + cleanuptbl = map[string]interface{}{ + "PSU": map[string]interface{}{ + "PSU-1-5": "", + }, + } + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + cleanupstatetbl = map[string]interface{}{ + "PSU_TABLE": map[string]interface{}{ + "PSU-1-5": "", + }, + } + unloadDB(hostDBName, db.StateDB, cleanupstatetbl) +} + +/* CU state DB fields and values */ +func Test_CU_state_DB_key(t *testing.T) { + var pre_req_map, cleanuptbl, cleanupstatetbl map[string]interface{} + var expected_get_json, url string + + pfmValues := pfmMapDetails() + + /* CU State DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB CU Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "CU": map[string]interface{}{ + "CU-1": pfmValues, + }, + } + loadDB(hostDBName, db.ConfigDB, pre_req_map) + + pre_req_map = map[string]interface{}{ + "CU_TABLE": map[string]interface{}{ + "CU-1": pfmValues, + }, + } + time.Sleep(1 * time.Second) + loadDB(hostDBName, db.StateDB, pre_req_map) + expected_get_json = "{\"openconfig-platform:state\":{\"empty\":false,\"hardware-version\":\"test_hw_version\",\"memory\":{\"available\":\"100\",\"utilized\":\"200\"},\"mfg-date\":\"09-10-24\",\"mfg-name\":\"test_mfg_name\",\"name\":\"CU-1\",\"oper-status\":\"openconfig-platform-types:ACTIVE\",\"parent\":\"ACTIVE\",\"part-no\":\"10\",\"removable\":true,\"serial-no\":\"test_serial_no\",\"software-version\":\"test_software_version\"}}" + url = "/openconfig-platform:components/component[name=CU-1]/state" + t.Run("Test get on state DB CU Key for "+url, processGetRequest(url, nil, expected_get_json, false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on stateDB CU Key ++++++++++++") + + //Unload the data + cleanuptbl = map[string]interface{}{ + "CU": map[string]interface{}{ + "CU-1": "", + }, + } + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + cleanupstatetbl = map[string]interface{}{ + "CU_TABLE": map[string]interface{}{ + "CU-1": "", + }, + } + unloadDB(hostDBName, db.StateDB, cleanupstatetbl) +} + +/* chassis state DB fields and values */ +func Test_chassis_state_DB_key(t *testing.T) { + var pre_req_map, cleanuptbl, cleanupstatetbl map[string]interface{} + var expected_get_json, url string + + /* chassis State DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB chassis Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "CHASSIS": map[string]interface{}{ + "CHASSIS-1": map[string]interface{}{ + "oper-status": "ACTIVE", + }, + }, + } + loadDB(hostDBName, db.ConfigDB, pre_req_map) + + pre_req_map = map[string]interface{}{ + "CHASSIS_TABLE": map[string]interface{}{ + "CHASSIS-1": map[string]interface{}{ + "oper-status": "ACTIVE", + }, + }, + } + time.Sleep(1 * time.Second) + loadDB(hostDBName, db.StateDB, pre_req_map) + expected_get_json = "{\"openconfig-platform:state\":{\"name\":\"CHASSIS-1\",\"oper-status\":\"openconfig-platform-types:ACTIVE\"}}" + url = "/openconfig-platform:components/component[name=CHASSIS-1]/state" + t.Run("Test get on state DB chassis Key for "+url, processGetRequest(url, nil, expected_get_json, false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on stateDB chassis Key ++++++++++++") + + //Unload the data + cleanuptbl = map[string]interface{}{ + "CHASSIS": map[string]interface{}{ + "CHASSIS-1": "", + }, + } + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + cleanupstatetbl = map[string]interface{}{ + "CHASSIS_TABLE": map[string]interface{}{ + "CHASSIS-1": "", + }, + } + unloadDB(hostDBName, db.StateDB, cleanupstatetbl) +} + +func Test_set_pfm_transcevier_config_DB_key_and_field_xfmr(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing Create/Replace/Delete on pfm_transcevier ++++++++++++") + + for idx, dbName := range getMdbNames() { + url := fmt.Sprintf("/openconfig-platform:components/component[name=TRANSCEIVER-1-%d-C2]/openconfig-platform-transceiver:transceiver/config", idx+1) + url_body_json := "{\"config\":{\"enabled\":false,\"ethernet-pmd-preconf\":\"openconfig-transport-types:ETH_100GBASE_SR4\",\"fec-mode\":\"openconfig-platform-types:FEC_AUTO\"}}" + + pre_req_map := map[string]interface{}{ + "OC_COMPONENT": map[string]interface{}{ + fmt.Sprintf("TRANSCEIVER-1-%d-C2", idx+1): map[string]interface{}{ + "enabled": "true", + "fec-mode": "FEC_AUTO", + "ethernet-pmd-preconf": "ETH_100GBASE_SR10", + }, + }, + "TRANSCEIVER": map[string]interface{}{ + fmt.Sprintf("TRANSCEIVER-1-%d-C2", idx+1): map[string]interface{}{ + "enabled": "true", + "fec-mode": "FEC_AUTO", + "ethernet-pmd-preconf": "ETH_100GBASE_SR10", + }, + }, + } + + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_map := map[string]interface{}{ + "TRANSCEIVER": map[string]interface{}{ + fmt.Sprintf("TRANSCEIVER-1-%d-C2", idx+1): map[string]interface{}{ + "enabled": "false", + "fec-mode": "FEC_AUTO", + "ethernet-pmd-preconf": "ETH_100GBASE_SR4", + }, + }, + } + time.Sleep(1 * time.Second) + + //PUT Test + t.Run("Replace Test on pfm_transcevier yang", processSetRequest(url, url_body_json, "PUT", false)) + time.Sleep(1 * time.Second) + + //GET Test + t.Run("Verify replace on pfm_transcevier yang", verifyDbResult(rclient[dbName], fmt.Sprintf("TRANSCEIVER|TRANSCEIVER-1-%d-C2", idx+1), expected_map, false)) + time.Sleep(1 * time.Second) + + //Delete Test + url = fmt.Sprintf("/openconfig-platform:components/component[name=TRANSCEIVER-1-%d-C2]/openconfig-platform-transceiver:transceiver", idx+1) + t.Run("DELETE Test on pfm_transcevier yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + //POST Test + url = "/openconfig-platform:components" + post_payload := fmt.Sprintf("{\"component\":[{\"name\": \"TRANSCEIVER-1-%d-C3\", \"openconfig-platform-transceiver:transceiver\": {\"config\":{\"enabled\":false,\"ethernet-pmd-preconf\":\"openconfig-transport-types:ETH_100GBASE_SR4\",\"fec-mode\":\"openconfig-platform-types:FEC_AUTO\"}}}]}", idx+1) + + t.Run("Create test on Transceiver yang", processSetRequest(url, post_payload, "POST", false)) + time.Sleep(1 * time.Second) + + expected_map = map[string]interface{}{ + "TRANSCEIVER": map[string]interface{}{ + fmt.Sprintf("TRANSCEIVER-1-%d-C3", idx+1): map[string]interface{}{ + "enabled": false, + "ethernet-pmd-preconf": "ETH_100GBASE_SR4", + "fec-mode": "FEC_AUTO", + }, + }, + } + + //Verify After the POST test + t.Run("Verify After the POST test on Transceiver yang", verifyDbResult(rclient[dbName], fmt.Sprintf("TRANSCEIVER|TRANSCEIVER-1-%d-C3", idx+1), expected_map, false)) + + //Delete After the POST test + url = fmt.Sprintf("/openconfig-platform:components/component[name=TRANSCEIVER-1-%d-C3]/openconfig-platform-transceiver:transceiver", idx+1) + t.Run("DELETE After the POST test on Transceiver yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + } +} + +func Test_transceiver_allow_write_multiple_namespace(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing transceiver write for multiple namespace (should be allowed) ++++++++++++") + + url := "/openconfig-platform:components" + url_body_json := `{ + "component": [ + { + "name": "TRANSCEIVER-1-1-C1", + "openconfig-platform-transceiver:transceiver": { + "config": { + "enabled": false, + "ethernet-pmd-preconf": "openconfig-transport-types:ETH_100GBASE_SR4", + "fec-mode": "openconfig-platform-types:FEC_AUTO" + } + } + }, + { + "name": "TRANSCEIVER-1-2-C1", + "openconfig-platform-transceiver:transceiver": { + "config": { + "enabled": false, + "ethernet-pmd-preconf": "openconfig-transport-types:ETH_100GBASE_SR4", + "fec-mode": "openconfig-platform-types:FEC_AUTO" + } + } + } + ] + }` + + // false = no error expected + t.Run("Test allow writing multiple namespace for transceiver", processSetRequest(url, url_body_json, "POST", false, nil)) + + t.Log("\n\n+++++++++++++ Done Performing transceiver write for multiple namespace ++++++++++++") +} diff --git a/translib/transformer/xfmr_system.go b/translib/transformer/xfmr_system.go index fad71552e..d8858a4ad 100644 --- a/translib/transformer/xfmr_system.go +++ b/translib/transformer/xfmr_system.go @@ -120,6 +120,11 @@ func init() { XlateFuncBind("DbToYang_pathz_policies_key_xfmr", DbToYang_pathz_policies_key_xfmr) XlateFuncBind("DbToYang_console_counters_xfmr", DbToYang_console_counters_xfmr) XlateFuncBind("Subscribe_console_counters_xfmr", Subscribe_console_counters_xfmr) + /* Key transformer for CURALARM_TABLE table*/ + XlateFuncBind("YangToDb_oc_system_alarm_key_xfmr", YangToDb_oc_system_alarm_key_xfmr) + XlateFuncBind("DbToYang_oc_system_alarm_key_xfmr", DbToYang_oc_system_alarm_key_xfmr) + /* Get Namespace transformer for platform table*/ + XlateFuncBind("oc_sys_get_namespace_xfmr", oc_sys_get_namespace_xfmr) } type grpcState struct { @@ -934,3 +939,43 @@ var Subscribe_console_counters_xfmr SubTreeXfmrSubscribe = func(inParams XfmrSub nOpts: ¬ificationOpts{mInterval: 0, pType: OnChange}, }, nil } + +var YangToDb_oc_system_alarm_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_oc_system_alarm_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + key := pathInfo.Var("id") + log.V(3).Infof("YangToDb_oc_system_alarm_key_xfmr: :", key) + + return key, nil +} + +var DbToYang_oc_system_alarm_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + log.V(3).Infof("DbToYang_oc_system_alarm_key_xfmr: ", inParams.key) + rmap["id"] = inParams.key + + return rmap, nil +} + +var oc_sys_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]NamespacePayload, error) { + return []NamespacePayload{ + { + Namespace: "*", + Payloads: []map[string]interface{}{}, + Key: "*", + }, + }, nil + +} + +// Define a new implementation for GetNamespaceFunc +func customSysGetNamespaceFunc(inParams XfmrParams) ([]NamespacePayload, error) { + + // Your custom implementation here + nameSpaceList, err := oc_sys_get_namespace_xfmr(inParams) + + return nameSpaceList, err +} diff --git a/translib/transformer/xfmr_system_test.go b/translib/transformer/xfmr_system_test.go new file mode 100644 index 000000000..4f1a9f0ed --- /dev/null +++ b/translib/transformer/xfmr_system_test.go @@ -0,0 +1,45 @@ +//go:build xfmrtest +// +build xfmrtest + +package transformer_test + +import ( + "testing" + "time" + + "github.com/Azure/sonic-mgmt-common/translib/db" +) + +/* ALARM counters, state DB fields and values */ +func Test_alarm_state_DB_key(t *testing.T) { + var pre_req_map, cleanupstatetbl map[string]interface{} + var url string + + /* PORT State DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB ALARM Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "CURALARM_TABLE": map[string]interface{}{ + "ALARM1": map[string]interface{}{ + "time-created": "12", + "resource": "test_res", + "text": "test_text", + "severity": "CRITICAL", + "type-id": "EQPT", + }, + }, + } + loadDB(hostDBName, db.StateDB, pre_req_map) + expected_get_json := "{\"openconfig-system:alarm\":[{\"id\":\"ALARM1\",\"state\":{\"id\":\"ALARM1\",\"resource\":\"test_res\",\"severity\":\"openconfig-alarm-types:CRITICAL\",\"text\":\"test_text\",\"time-created\":\"12\",\"type-id\":\"openconfig-alarm-types:EQPT\"}}]}" + url = "/openconfig-system:system/alarms/alarm[id=ALARM1]" + t.Run("Test get on state DB ALARM Key", processGetRequest(url, nil, expected_get_json, false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on stateDB ALARM Key ++++++++++++") + + // Unload the Data + cleanupstatetbl = map[string]interface{}{ + "CURALARM_TABLE": map[string]interface{}{ + "ALARM1": "", + }, + } + unloadDB(hostDBName, db.StateDB, cleanupstatetbl) +} diff --git a/translib/transformer/xfmr_terminal_device.go b/translib/transformer/xfmr_terminal_device.go new file mode 100644 index 000000000..ecdf90730 --- /dev/null +++ b/translib/transformer/xfmr_terminal_device.go @@ -0,0 +1,1366 @@ +package transformer + +import ( + "encoding/json" + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "github.com/Azure/sonic-mgmt-common/translib/ocbinds" + log "github.com/golang/glog" + "github.com/openconfig/ygot/ygot" + "reflect" + "regexp" + "strconv" + "strings" +) + +const ( + TD_INTERVAL_CURRENT_VAL = "15_pm_current" + + /* COUNTER KEYS */ + CHROMATIC_DISPERSION = "_ChromaticDispersion:" + POLARIZATION_MODE_DISPERSION = "_PolarizationModeDispersion:" + SECOND_ORDER_POLARIZATION_MODE_DISPERSION = "_SecondOrderPolarizationModeDispersion:" + POLARIZATION_DEPENDENT_LOSS = "_PolarizationDependentLoss:" + OSNR = "_Osnr:" + CARRIER_FREQUENCY_OFFSET = "_CarrierFrequencyOffset:" + OCH_OUTPUT_POWER = "_OutputPower:" + OCH_INPUT_POWER = "_InputPower:" + OCH_LASER_BIAS_CURRENT = "_LaserBiasCurrent:" + + OTN_PRE_FEC_BER = "_PreFecBer:" + OTN_POST_FEC_BER = "_PostFecBer:" + OTN_ESNR = "_Esnr:" + OTN_QVALUE = "_QValue:" + + ETHERNET_TBL = "ETHERNET" + OTN_TBL = "OTN" +) + +func init() { + + /* Key transformer for LOGICAL_CHANNEL table*/ + XlateFuncBind("YangToDb_logical_channel_key_xfmr", YangToDb_logical_channel_key_xfmr) + XlateFuncBind("DbToYang_logical_channel_key_xfmr", DbToYang_logical_channel_key_xfmr) + + /* Field transformer for LOGICAL_CHANNEL table*/ + XlateFuncBind("YangToDb_logical_channel_field_xfmr", YangToDb_logical_channel_field_xfmr) + XlateFuncBind("DbToYang_logical_channel_field_xfmr", DbToYang_logical_channel_field_xfmr) + + /* Key transformer for ETHERNET COUNTERS_DB table*/ + XlateFuncBind("YangToDb_ethernet_counters_key_xfmr", YangToDb_ethernet_counters_key_xfmr) + XlateFuncBind("DbToYang_ethernet_counters_key_xfmr", DbToYang_ethernet_counters_key_xfmr) + + /* Key transformer for NEIGHBOR table*/ + XlateFuncBind("YangToDb_neighbor_key_xfmr", YangToDb_neighbor_key_xfmr) + XlateFuncBind("DbToYang_neighbor_key_xfmr", DbToYang_neighbor_key_xfmr) + + /* Field transformer for NEIGHBOR table*/ + XlateFuncBind("YangToDb_neighbor_field_xfmr", YangToDb_neighbor_field_xfmr) + XlateFuncBind("DbToYang_neighbor_field_xfmr", DbToYang_neighbor_field_xfmr) + + /* Key transformer for ASSIGNMENT table*/ + XlateFuncBind("YangToDb_assignment_key_xfmr", YangToDb_assignment_key_xfmr) + XlateFuncBind("DbToYang_assignment_key_xfmr", DbToYang_assignment_key_xfmr) + + /* Field transformer for ASSIGNMENT table*/ + XlateFuncBind("YangToDb_assignment_field_xfmr", YangToDb_assignment_field_xfmr) + XlateFuncBind("DbToYang_assignment_field_xfmr", DbToYang_assignment_field_xfmr) + + /* Field transformer logical-channel field in ASSIGNMENT table*/ + XlateFuncBind("YangToDb_ass_logical_field_xfmr", YangToDb_ass_logical_field_xfmr) + XlateFuncBind("DbToYang_ass_logical_field_xfmr", DbToYang_ass_logical_field_xfmr) + + /* Key transformer for MODE table*/ + XlateFuncBind("YangToDb_mode_key_xfmr", YangToDb_mode_key_xfmr) + XlateFuncBind("DbToYang_mode_key_xfmr", DbToYang_mode_key_xfmr) + + /* Field transformer for MODE table*/ + XlateFuncBind("YangToDb_mode_field_xfmr", YangToDb_mode_field_xfmr) + XlateFuncBind("DbToYang_mode_field_xfmr", DbToYang_mode_field_xfmr) + + /* Key transformer for OCH hromatic dispersion Counter table*/ + XlateFuncBind("YangToDb_och_chromatic_dispersion_counter_key_xfmr", YangToDb_och_chromatic_dispersion_counter_key_xfmr) + XlateFuncBind("DbToYang_och_chromatic_dispersion_counter_key_xfmr", DbToYang_och_chromatic_dispersion_counter_key_xfmr) + + /* Key transformer for OCH polarization mode dispersion Counter table*/ + XlateFuncBind("YangToDb_och_pmd_counter_key_xfmr", YangToDb_och_pmd_counter_key_xfmr) + XlateFuncBind("DbToYang_och_pmd_counter_key_xfmr", DbToYang_och_pmd_counter_key_xfmr) + + /* Key transformer for OCH second order polarization mode dispersion Counter table*/ + XlateFuncBind("YangToDb_och_second_pmd_counter_key_xfmr", YangToDb_och_second_pmd_counter_key_xfmr) + XlateFuncBind("DbToYang_och_second_pmd_counter_key_xfmr", DbToYang_och_second_pmd_counter_key_xfmr) + + /* Key transformer for OCH polarization dependent loss Counter table*/ + XlateFuncBind("YangToDb_och_pd_loss_counter_key_xfmr", YangToDb_och_pd_loss_counter_key_xfmr) + XlateFuncBind("DbToYang_och_pd_loss_counter_key_xfmr", DbToYang_och_pd_loss_counter_key_xfmr) + + /* Key transformer for OCH osnr Counter table*/ + XlateFuncBind("YangToDb_och_osnr_counter_key_xfmr", YangToDb_och_osnr_counter_key_xfmr) + XlateFuncBind("DbToYang_och_osnr_counter_key_xfmr", DbToYang_och_osnr_counter_key_xfmr) + + /* Key transformer for OCH carrier frequency offset Counter table*/ + XlateFuncBind("YangToDb_och_cfo_counter_key_xfmr", YangToDb_och_cfo_counter_key_xfmr) + XlateFuncBind("DbToYang_och_cfo_counter_key_xfmr", DbToYang_och_cfo_counter_key_xfmr) + + /* Key transformer for OCH output power Counter table*/ + XlateFuncBind("YangToDb_och_output_power_counter_key_xfmr", YangToDb_och_output_power_counter_key_xfmr) + XlateFuncBind("DbToYang_och_output_power_counter_key_xfmr", DbToYang_och_output_power_counter_key_xfmr) + + /* Key transformer for OCH input power Counter table*/ + XlateFuncBind("YangToDb_och_input_power_counter_key_xfmr", YangToDb_och_input_power_counter_key_xfmr) + XlateFuncBind("DbToYang_och_input_power_counter_key_xfmr", DbToYang_och_input_power_counter_key_xfmr) + + /* Key transformer for OCH laser bias current Counter table*/ + XlateFuncBind("YangToDb_och_laser_bias_counter_key_xfmr", YangToDb_och_laser_bias_counter_key_xfmr) + XlateFuncBind("DbToYang_och_laser_bias_counter_key_xfmr", DbToYang_och_laser_bias_counter_key_xfmr) + + /* Key transformer for LOGICAL CHANNEL table*/ + XlateFuncBind("YangToDb_otn_counter_key_xfmr", YangToDb_otn_counter_key_xfmr) + XlateFuncBind("DbToYang_otn_counter_key_xfmr", DbToYang_otn_counter_key_xfmr) + + /* Key transformer for otn pre-fec-ber table*/ + XlateFuncBind("YangToDb_otn_pre_fec_ber_counter_key_xfmr", YangToDb_otn_pre_fec_ber_counter_key_xfmr) + XlateFuncBind("DbToYang_otn_pre_fec_ber_counter_key_xfmr", DbToYang_otn_pre_fec_ber_counter_key_xfmr) + + /* Key transformer for otn post-fec-ber table*/ + XlateFuncBind("YangToDb_otn_post_fec_ber_counter_key_xfmr", YangToDb_otn_post_fec_ber_counter_key_xfmr) + XlateFuncBind("DbToYang_otn_post_fec_ber_counter_key_xfmr", DbToYang_otn_post_fec_ber_counter_key_xfmr) + + /* Key transformer for otn esnr table*/ + XlateFuncBind("YangToDb_otn_esnr_counter_key_xfmr", YangToDb_otn_esnr_counter_key_xfmr) + XlateFuncBind("DbToYang_otn_esnr_counter_key_xfmr", DbToYang_otn_esnr_counter_key_xfmr) + + /* Key transformer for q-value table*/ + XlateFuncBind("YangToDb_otn_qvalue_counter_key_xfmr", YangToDb_otn_qvalue_counter_key_xfmr) + XlateFuncBind("DbToYang_otn_qvalue_counter_key_xfmr", DbToYang_otn_qvalue_counter_key_xfmr) + + // Override the existing function with the new implementation + // Uncomment the below line to override the existing GetNamespaceFunc + // td_get_namespace_xfmr = customOcGetNamespaceFunc + + /* Get Namespace transformer for platform table*/ + XlateFuncBind("td_get_namespace_xfmr", td_get_namespace_xfmr) + + XlateFuncBind("terminal_device_post_xfmr", terminal_device_post_xfmr) + + XlateFuncBind("DbToYang_ethernet_subtree_xfmr", DbToYang_ethernet_subtree_xfmr) + XlateFuncBind("Subscribe_ethernet_subtree_xfmr", Subscribe_ethernet_subtree_xfmr) + +} + +/* LOGICAL_CHANNEL TABLE */ + +var YangToDb_logical_channel_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + var lchkey string + log.Infof("YangToDb_logical_channel_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + index := pathInfo.Var("index") + if index != "" { + lchkey = "CH" + pathInfo.Var("index") + } + log.Infof("YangToDb_logical_channel_key_xfmr: :", lchkey) + + return lchkey, nil +} + +var DbToYang_logical_channel_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + log.Infof("DbToYang_logical_channel_key_xfmr: ", inParams.key) + + // Removing the CH from the key since in yang, + // only index value is key + // EG: CH103(redis table key) - 103(yang list key) + index := strings.Replace(inParams.key, "CH", "", -1) + nKey, err := strconv.ParseUint(index, 10, 32) + if err != nil { + log.Errorf("Error in parsing key %s: %v", index, err) + return rmap, err + } + rmap["index"] = uint32(nKey) + + log.Infof("DbToYang_logical_channel_key_xfmr: key :%v", uint32(nKey)) + + return rmap, nil +} + +var YangToDb_logical_channel_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + log.Infof("YangToDb_logical_channel_field_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_logical_channel_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + var index string + log.Infof("DbToYang_logical_channel_field_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + + rmap := make(map[string]interface{}) + // Removing the CH from the key since in yang, + // only index value is key + // EG: CH103(redis table key) - 103(yang list key) + if strings.Contains(inParams.uri, "assignment") { + indexValues := fetchIndexValuesFromAssignmentXpath(inParams.uri) + if len(indexValues) == 2 { + index = indexValues[0] + } + } else { + index = strings.Replace(inParams.key, "CH", "", -1) + } + + nKey, err := strconv.ParseUint(index, 10, 32) + if err != nil { + log.Errorf("Error in parsing key %s: %v", index, err) + return rmap, err + } + + rmap["index"] = uint32(nKey) + log.Infof("DbToYang_logical_channel_field_xfmr value for index is:%v", nKey) + + return rmap, nil +} + +/* ETHERNET COUNTERS_DB TABLE */ + +var YangToDb_ethernet_counters_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + var key string + log.Infof("YangToDb_ethernet_counters_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + index := pathInfo.Var("index") + if index != "" { + key = "CH" + pathInfo.Var("index") + ":" + TD_INTERVAL_CURRENT_VAL + } + log.Infof("YangToDb_ethernet_counters_key_xfmr: :", key) + + return key, nil +} + +var DbToYang_ethernet_counters_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + log.Infof("DbToYang_ethernet_counters_key_xfmr: ", inParams.key) + key := strings.Replace(inParams.key, "CH", "", -1) + TableKeys := strings.Split(key, ":") + + if len(TableKeys) >= 2 { + index, err := strconv.ParseUint(TableKeys[0], 10, 32) + if err != nil { + log.Errorf("Error in parsing key %s: %v", TableKeys[0], err) + return rmap, err + } + + log.Infof("DbToYang_ethernet_counters_key_xfmr: index:%v", index) + rmap["index"] = uint32(index) + } + + return rmap, nil +} + +/* NEIGHBOR TABLE */ + +var YangToDb_neighbor_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + var key string + log.Infof("YangToDb_neighbor_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + index := pathInfo.Var("index") + if index != "" { + key = "CH" + pathInfo.Var("index") + "|" + pathInfo.Var("id") + } + log.Infof("YangToDb_neighbor_key_xfmr: :", key) + + return key, nil +} + +var DbToYang_neighbor_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + log.Infof("DbToYang_neighbor_key_xfmr: ", inParams.key) + key := inParams.key + TableKeys := strings.Split(key, "|") + + if len(TableKeys) >= 2 { + log.Infof("DbToYang_neighbor_key_xfmr: TableKeys[1]:%v", TableKeys[1]) + rmap["id"] = TableKeys[1] + } + + return rmap, nil +} + +var YangToDb_neighbor_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_neighbor_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + key := inParams.key + TableKeys := strings.Split(key, "|") + + if len(TableKeys) >= 2 { + log.Infof("DbToYang_neighbor_key_xfmr: TableKeys[1]:%v", TableKeys[1]) + rmap["id"] = TableKeys[1] + } + + return rmap, nil +} + +/* ASSIGNMENT TABLE */ + +func fetchIndexValuesFromAssignmentXpath(str string) []string { + + re := regexp.MustCompile(`\[index=(\d+)\]`) + matches := re.FindAllStringSubmatch(str, -1) + + // Extract index values + indexValues := make([]string, len(matches)) + for i, match := range matches { + indexValues[i] = match[1] + } + + return indexValues +} + +var YangToDb_assignment_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + var key string + log.Infof("YangToDb_assignment_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + + indexValues := fetchIndexValuesFromAssignmentXpath(inParams.uri) + if len(indexValues) == 2 { + key = "CH" + indexValues[0] + "|" + "ASS" + indexValues[1] + } + log.Infof("YangToDb_assignment_key_xfmr: :", key) + + return key, nil +} + +var DbToYang_assignment_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + log.Infof("DbToYang_assignment_key_xfmr: ", inParams.key) + key := inParams.key + TableKeys := strings.Split(key, "|") + + if len(TableKeys) >= 2 { + index := strings.Replace(TableKeys[1], "ASS", "", -1) + aKey, err := strconv.ParseUint(index, 10, 32) + if err != nil { + log.Errorf("Error in parsing key %s: %v", index, err) + return rmap, err + } + + log.Infof("DbToYang_assignment_key_xfmr: TableKeys[1]:%v", aKey) + rmap["index"] = uint32(aKey) + log.Infof("DbToYang_assignment_key_xfmr: rmap:%v", rmap) + } + + return rmap, nil +} + +var YangToDb_assignment_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_assignment_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + key := inParams.key + TableKeys := strings.Split(key, "|") + + if len(TableKeys) >= 2 { + aindex := strings.Replace(TableKeys[1], "ASS", "", -1) + aKey, err := strconv.ParseUint(aindex, 10, 32) + if err != nil { + log.Errorf("Error in parsing key %s: %v", aindex, err) + return rmap, err + } + log.Infof("DbToYang_assignment_field_xfmr: TableKey[1]:%v", aKey) + rmap["index"] = uint32(aKey) + log.Infof("DbToYang_assignment_field_xfmr: rmap:%v", rmap) + } + + return rmap, nil +} + +var YangToDb_ass_logical_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_ass_logical_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + key := inParams.key + TableKeys := strings.Split(key, "|") + + if len(TableKeys) >= 2 { + lindex := strings.Replace(TableKeys[0], "CH", "", -1) + lKey, err := strconv.ParseUint(lindex, 10, 32) + if err != nil { + log.Errorf("Error in parsing key %s: %v", lindex, err) + return rmap, err + } + + log.Infof("DbToYang_ass_logical_field_xfmr: TableKeys[0]:%v", lKey) + rmap["logical-channel"] = uint32(lKey) + log.Infof("DbToYang_ass_logical_field_xfmr: rmap:%v", rmap) + } + + return rmap, nil +} + +/* MODE TABLE */ + +var YangToDb_mode_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.Infof("YangToDb_mode_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("mode-id") + log.Infof("YangToDb_mode_key_xfmr: :", key) + + return key, nil +} + +var DbToYang_mode_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + log.Infof("DbToYang_mode_key_xfmr: ", inParams.key) + + key, err := strconv.ParseUint(inParams.key, 10, 16) + if err != nil { + log.Errorf("Error in parsing key %s: %v", inParams.key, err) + return rmap, err + } + + log.Infof("DbToYang_mode_key_xfmr: key:%v", key) + rmap["mode-id"] = uint16(key) + + return rmap, nil +} + +var YangToDb_mode_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_mode_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + key, err := strconv.ParseUint(inParams.key, 10, 16) + if err != nil { + log.Errorf("Error in parsing key %s: %v", inParams.key, err) + return rmap, err + } + + log.Infof("DbToYang_mode_key_xfmr: key:%v", key) + rmap["mode-id"] = uint16(key) + + return rmap, nil +} + +func otnKeyDbtoYang(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + log.Info("ochNameKeyDbtoYang: ", inParams.key) + // Removing the CH from the key since in yang, + // only index value is key + // EG: CH103(redis table key) - 103(yang list key) + index := strings.Replace(inParams.key, "CH", "", -1) + nKey, err := strconv.ParseUint(index, 10, 32) + if err != nil { + log.Errorf("Error in parsing key %s: %v", index, err) + return rmap, err + } + rmap["index"] = uint32(nKey) + + log.Infof("ochNameKeyDbtoYang: key :%v", uint32(nKey)) + + return rmap, nil +} + +var YangToDb_otn_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + var tdCounterKey string + log.Infof("YangToDb_otn_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + index := pathInfo.Var("index") + if index != "" { + ochkey := "CH" + index + log.Infof("YangToDb_otn_counter_key_xfmr:ochkey:%v", ochkey) + tdCounterKey = ochkey + ":" + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_otn_counter_key_xfmr: key:", tdCounterKey) + } + + return tdCounterKey, nil +} + +var DbToYang_otn_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_otn_counter_key_xfmr: ", inParams.key) + rmap, err := otnKeyDbtoYang(inParams) + + return rmap, err +} + +var YangToDb_otn_pre_fec_ber_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + var tdCounterKey string + log.Infof("YangToDb_otn_pre_fec_ber_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + index := pathInfo.Var("index") + if index != "" { + ochkey := "CH" + index + log.Infof("YangToDb_otn_pre_fec_ber_counter_key_xfmr:ochkey:%v", ochkey) + tdCounterKey = ochkey + OTN_PRE_FEC_BER + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_otn_pre_fec_ber_counter_key_xfmr: key:", tdCounterKey) + } + + return tdCounterKey, nil +} + +var DbToYang_otn_pre_fec_ber_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_otn_pre_fec_ber_counter_key_xfmr: ", inParams.key) + rmap, err := otnKeyDbtoYang(inParams) + + return rmap, err +} + +var YangToDb_otn_post_fec_ber_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + var tdCounterKey string + log.Infof("YangToDb_otn_post_fec_ber_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + index := pathInfo.Var("index") + if index != "" { + ochkey := "CH" + index + log.Infof("YangToDb_otn_post_fec_ber_counter_key_xfmr:ochkey:%v", ochkey) + tdCounterKey = ochkey + OTN_POST_FEC_BER + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_otn_post_fec_ber_counter_key_xfmr: key:", tdCounterKey) + } + + return tdCounterKey, nil +} + +var DbToYang_otn_post_fec_ber_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_otn_post_fec_ber_counter_key_xfmr: ", inParams.key) + rmap, err := otnKeyDbtoYang(inParams) + + return rmap, err +} + +var YangToDb_otn_esnr_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + var tdCounterKey string + log.Infof("YangToDb_otn_esnr_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + index := pathInfo.Var("index") + if index != "" { + ochkey := "CH" + index + log.Infof("YangToDb_otn_esnr_counter_key_xfmr:ochkey:%v", ochkey) + tdCounterKey = ochkey + OTN_ESNR + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_otn_esnr_counter_key_xfmr: key:", tdCounterKey) + } + + return tdCounterKey, nil +} + +var DbToYang_otn_esnr_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_otn_esnr_counter_key_xfmr: ", inParams.key) + rmap, err := otnKeyDbtoYang(inParams) + + return rmap, err +} + +var YangToDb_otn_qvalue_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + var tdCounterKey string + log.Infof("YangToDb_otn_qvalue_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + index := pathInfo.Var("index") + if index != "" { + ochkey := "CH" + index + log.Infof("YangToDb_otn_qvalue_counter_key_xfmr:ochkey:%v", ochkey) + tdCounterKey = ochkey + OTN_QVALUE + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_otn_qvalue_counter_key_xfmr: key:", tdCounterKey) + } + + return tdCounterKey, nil +} + +var DbToYang_otn_qvalue_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_otn_qvalue_counter_key_xfmr: ", inParams.key) + rmap, err := otnKeyDbtoYang(inParams) + + return rmap, err +} + +func ochNameKeyDbtoYang(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + log.Info("ochNameKeyDbtoYang: ", inParams.key) + rmap["name"] = inParams.key + + return rmap, nil +} + +var YangToDb_och_chromatic_dispersion_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.Infof("YangToDb_och_chromatic_dispersion_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + och_chromatic_dispersionkey := pathInfo.Var("name") + log.Infof("YangToDb_och_chromatic_dispersion_counter_key_xfmr:och_chromatic_dispersionkey:%v", och_chromatic_dispersionkey) + + tdCounterKey := och_chromatic_dispersionkey + CHROMATIC_DISPERSION + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_och_chromatic_dispersion_counter_key_xfmr: key:", tdCounterKey) + + return tdCounterKey, nil +} + +var DbToYang_och_chromatic_dispersion_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_och_chromatic_dispersion_counter_key_xfmr: ", inParams.key) + rmap, err := ochNameKeyDbtoYang(inParams) + + return rmap, err +} + +var YangToDb_och_pmd_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.Infof("YangToDb_och_pmd_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + och_pmdkey := pathInfo.Var("name") + log.Infof("YangToDb_och_pmd_counter_key_xfmr:och_pmdkey:%v", och_pmdkey) + + tdCounterKey := och_pmdkey + POLARIZATION_MODE_DISPERSION + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_och_pmd_counter_key_xfmr: key:", tdCounterKey) + + return tdCounterKey, nil +} + +var DbToYang_och_pmd_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_och_pmd_counter_key_xfmr: ", inParams.key) + rmap, err := ochNameKeyDbtoYang(inParams) + + return rmap, err +} + +var YangToDb_och_second_pmd_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.Infof("YangToDb_och_second_pmd_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + och_so_pmdkey := pathInfo.Var("name") + log.Infof("YangToDb_och_second_pmd_counter_key_xfmr:och_so_pmdkey:%v", och_so_pmdkey) + + tdCounterKey := och_so_pmdkey + SECOND_ORDER_POLARIZATION_MODE_DISPERSION + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_och_second_pmd_counter_key_xfmr: key:", tdCounterKey) + + return tdCounterKey, nil +} + +var DbToYang_och_second_pmd_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_och_second_pmd_counter_key_xfmr: ", inParams.key) + rmap, err := ochNameKeyDbtoYang(inParams) + + return rmap, err +} + +var YangToDb_och_pd_loss_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.Infof("YangToDb_och_pd_loss_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + och_pd_losskey := pathInfo.Var("name") + log.Infof("YangToDb_och_pd_loss_counter_key_xfmr:och_pd_losskey:%v", och_pd_losskey) + + tdCounterKey := och_pd_losskey + POLARIZATION_DEPENDENT_LOSS + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_och_pd_loss_counter_key_xfmr: key:", tdCounterKey) + + return tdCounterKey, nil +} + +var DbToYang_och_pd_loss_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_och_pd_loss_counter_key_xfmr: ", inParams.key) + rmap, err := ochNameKeyDbtoYang(inParams) + + return rmap, err +} + +var YangToDb_och_osnr_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.Infof("YangToDb_och_osnr_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + och_osnrkey := pathInfo.Var("name") + log.Infof("YangToDb_och_osnr_counter_key_xfmr:och_osnrkey:%v", och_osnrkey) + + tdCounterKey := och_osnrkey + OSNR + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_och_osnr_counter_key_xfmr: key:", tdCounterKey) + + return tdCounterKey, nil +} + +var DbToYang_och_osnr_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_och_osnr_counter_key_xfmr: ", inParams.key) + rmap, err := ochNameKeyDbtoYang(inParams) + + return rmap, err +} + +var YangToDb_och_cfo_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.Infof("YangToDb_och_cfo_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + och_cfokey := pathInfo.Var("name") + log.Infof("YangToDb_och_cfo_counter_key_xfmr:och_cfokey:%v", och_cfokey) + + tdCounterKey := och_cfokey + CARRIER_FREQUENCY_OFFSET + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_och_cfo_counter_key_xfmr: key:", tdCounterKey) + + return tdCounterKey, nil +} + +var DbToYang_och_cfo_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_och_cfo_counter_key_xfmr: ", inParams.key) + rmap, err := ochNameKeyDbtoYang(inParams) + + return rmap, err +} + +var YangToDb_och_output_power_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.Infof("YangToDb_och_output_power_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + och_output_powerkey := pathInfo.Var("name") + log.Infof("YangToDb_och_output_power_counter_key_xfmr:och_output_powerkey:%v", och_output_powerkey) + + tdCounterKey := och_output_powerkey + OCH_OUTPUT_POWER + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_och_output_power_counter_key_xfmr: key:", tdCounterKey) + + return tdCounterKey, nil +} + +var DbToYang_och_output_power_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_och_output_power_counter_key_xfmr: ", inParams.key) + rmap, err := ochNameKeyDbtoYang(inParams) + + return rmap, err +} + +var YangToDb_och_input_power_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.Infof("YangToDb_och_input_power_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + och_input_powerkey := pathInfo.Var("name") + log.Infof("YangToDb_och_input_power_counter_key_xfmr:och_input_powerkey:%v", och_input_powerkey) + + tdCounterKey := och_input_powerkey + OCH_INPUT_POWER + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_och_input_power_counter_key_xfmr: key:", tdCounterKey) + + return tdCounterKey, nil +} + +var DbToYang_och_input_power_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_och_input_power_counter_key_xfmr: ", inParams.key) + rmap, err := ochNameKeyDbtoYang(inParams) + + return rmap, err +} + +var YangToDb_och_laser_bias_counter_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.Infof("YangToDb_och_laser_bias_counter_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + och_laser_biaskey := pathInfo.Var("name") + log.Infof("YangToDb_och_laser_bias_counter_key_xfmr:och_laser_biaskey:%v", och_laser_biaskey) + + tdCounterKey := och_laser_biaskey + OCH_LASER_BIAS_CURRENT + TD_INTERVAL_CURRENT_VAL + log.Infof("YangToDb_och_laser_bias_counter_key_xfmr: key:", tdCounterKey) + + return tdCounterKey, nil +} + +var DbToYang_och_laser_bias_counter_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.Info("DbToYang_och_laser_bias_counter_key_xfmr: ", inParams.key) + rmap, err := ochNameKeyDbtoYang(inParams) + + return rmap, err +} + +// Function to process key and generate dbName based on the type of key +func getDbNameFromKey(key interface{}) (string, error) { + var dbName string + + switch v := key.(type) { + case uint32: + dbName = db.GetMDBNameFromEntity(v) + + case uint16: + dbName = db.GetMDBNameFromEntity(v) + + case string: + dbName = db.GetMDBNameFromEntity(v) + + default: + log.Errorf("Unsupported key type: %v", key) + return "", fmt.Errorf("unsupported key type: %T", key) + } + + return dbName, nil +} + +func getTerminalDeviceRootObj(s *ygot.GoStruct) *ocbinds.OpenconfigTerminalDevice_TerminalDevice { + deviceObj := (*s).(*ocbinds.Device) + return deviceObj.TerminalDevice +} + +func getPlatformRootObj(s *ygot.GoStruct) *ocbinds.OpenconfigPlatform_Components { + deviceObj := (*s).(*ocbinds.Device) + return deviceObj.Components +} + +var td_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]NamespacePayload, error) { + + type payloadWithKey struct { + payload map[string]interface{} + key string + } + + var nsPayloadMap = make(map[string][]payloadWithKey) + var key, dbName string + var isKeyIndex, isKeyModeId bool + + log.Infof("td_get_namespace_xfmr: inParams:%v ", inParams) + pathInfo := NewPathInfo(inParams.uri) + + switch { + case strings.Contains(inParams.uri, "optical-channel") && !strings.Contains(inParams.uri, "assignment"): + key = pathInfo.Var("name") + + case strings.Contains(inParams.uri, "operational-modes"): + key = pathInfo.Var("mode-id") + isKeyModeId = true + + case strings.Contains(inParams.uri, "ethernet") && strings.Contains(inParams.uri, "terminal-device"), + strings.Contains(inParams.uri, "lldp"), + strings.Contains(inParams.uri, "otn"), + strings.Contains(inParams.uri, "neighbor"), + strings.Contains(inParams.uri, "assignment"), + strings.Contains(inParams.uri, "logical-channel"): + key = pathInfo.Var("index") + isKeyIndex = true + + case strings.Contains(inParams.uri, "component"): + key = pathInfo.Var("name") + } + + if key != "" && key != "*" { + // Convert key to appropriate type before passing to GetMDBNameFromEntity + if isKeyIndex { + nKey, err := strconv.ParseUint(key, 10, 32) + if err != nil { + log.Errorf("Error parsing key %s: %v", key, err) + return nil, err + } + dbName = db.GetMDBNameFromEntity(uint32(nKey)) + key = "CH" + key + } else if isKeyModeId { + nKey, err := strconv.ParseUint(key, 10, 16) + if err != nil { + log.Errorf("Error parsing key %s: %v", key, err) + return nil, err + } + dbName = db.GetMDBNameFromEntity(uint16(nKey)) + } else { + dbName = db.GetMDBNameFromEntity(key) + } + + log.Infof("td_get_namespace_xfmr: dbName: %v", dbName) + + // Parse body into payloads + var raw interface{} + var payloads []map[string]interface{} + + if inParams.body != nil && len(inParams.body) > 0 { + if err := json.Unmarshal(inParams.body, &raw); err != nil { + return nil, err + } + + switch val := raw.(type) { + case map[string]interface{}: + payloads = append(payloads, val) + case []interface{}: + for _, item := range val { + if m, ok := item.(map[string]interface{}); ok { + payloads = append(payloads, m) + } else { + return nil, fmt.Errorf("Invalid JSON payload: %v", inParams.body) + } + } + default: + return nil, fmt.Errorf("Unsupported JSON structure in payload") + } + } else { + payloads = []map[string]interface{}{} + } + + // Return early with constructed payload + return []NamespacePayload{ + { + Namespace: dbName, + Payloads: payloads, + Key: key, + }, + }, nil + } + var containerPrefix string + log.Infof("td_get_namespace_xfmr: inParams:%v ", inParams) + + // Extract container prefix for reconstructing payload + if inParams.body != nil { + bodyStr := string(inParams.body) + idx := strings.Index(bodyStr, "[") + if idx != -1 { + containerPrefix = bodyStr[:idx] + containerPrefix = strings.TrimRight(containerPrefix, ": \t\r\n") + } + } + + if inParams.ygRoot != nil { + td := getTerminalDeviceRootObj(inParams.ygRoot) + pf := getPlatformRootObj(inParams.ygRoot) + + processEntities := func(entities interface{}) { + val := reflect.ValueOf(entities) + if val.Kind() != reflect.Map { + log.Info("Entities is not a map") + return + } + + for _, key := range val.MapKeys() { + var isKeyIndex bool + entity := val.MapIndex(key).Interface() + var dbName string + + switch key.Kind() { + case reflect.String: + dbName = db.GetMDBNameFromEntity(key.String()) + case reflect.Uint32: + dbName = db.GetMDBNameFromEntity(uint32(key.Uint())) + isKeyIndex = true + case reflect.Uint16: + dbName = db.GetMDBNameFromEntity(uint16(key.Uint())) + default: + log.Infof("Unexpected key type: %s", key.Kind()) + continue + } + + ygotStruct, ok := entity.(ygot.ValidatedGoStruct) + if !ok { + log.Errorf("Entity does not implement ygot.ValidatedGoStruct") + continue + } + + entityJson, err := ygot.EmitJSON(ygotStruct, &ygot.EmitJSONConfig{ + Format: ygot.RFC7951, + Indent: "", + SkipValidation: true, + }) + if err != nil { + log.Errorf("Failed to marshal entity with ygot.EmitJSON: %v", err) + continue + } + + openBraces := strings.Count(containerPrefix, "{") + finalJson := fmt.Sprintf("%s:[%s]%s", containerPrefix, string(entityJson), strings.Repeat("}", openBraces)) + + var finalMap map[string]interface{} + if err := json.Unmarshal([]byte(finalJson), &finalMap); err != nil { + log.Errorf("Failed to unmarshal reconstructed payload: %v", err) + continue + } + + // Determine the final key string + var keyStr string + if isKeyIndex { + keyStr = "CH" + fmt.Sprintf("%v", key.Interface()) + } else { + keyStr = fmt.Sprintf("%v", key.Interface()) + } + + nsPayloadMap[dbName] = append(nsPayloadMap[dbName], payloadWithKey{ + payload: finalMap, + key: keyStr, + }) + + if outStr, err := json.MarshalIndent(finalMap, "", " "); err == nil { + log.Infof("Namespace: %s\nWrapped Output:\n%s", dbName, string(outStr)) + } + } + } + + // URI-based filtering + if strings.Contains(inParams.uri, "component") && pf.Component != nil { + processEntities(pf.Component) + } + + if strings.Contains(inParams.uri, "terminal-device") && !(strings.Contains(inParams.uri, "component")) { + log.Infof("td_get_namespace_xfmr: Terminal-device found in uri") + + if td.OperationalModes != nil && strings.Contains(inParams.uri, "operational-modes") { + processEntities(td.OperationalModes.Mode) + } else if td.LogicalChannels != nil { + processEntities(td.LogicalChannels.Channel) + } + } + } + + if len(nsPayloadMap) == 0 { + log.Infof("No specific key found, using '*' to include all DBs.") + return []NamespacePayload{ + { + Namespace: "*", + Payloads: []map[string]interface{}{}, + Key: "*", + }, + }, nil + } + + var result []NamespacePayload + for ns, pwkList := range nsPayloadMap { + for _, pwk := range pwkList { + result = append(result, NamespacePayload{ + Namespace: ns, + Payloads: []map[string]interface{}{pwk.payload}, + Key: pwk.key, + Commited: false, + }) + } + } + + log.Infof("td_get_namespace_xfmr: Final result: %+v", result) + return result, nil +} + +// Define a new implementation for GetNamespaceFunc +func customOcGetNamespaceFunc(inParams XfmrParams) ([]NamespacePayload, error) { + + // Your custom implementation here + nameSpaceList, err := oa_name_get_namespace_xfmr(inParams) + + return nameSpaceList, err +} + +var terminal_device_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[string]map[string]db.Value, error) { + if inParams.dbDataMap == nil || *inParams.dbDataMap == nil { + return nil, fmt.Errorf("dbDataMap is nil") + } + + retDbDataMap := (*inParams.dbDataMap)[inParams.curDb] + if retDbDataMap == nil { + retDbDataMap = make(map[string]map[string]db.Value) + (*inParams.dbDataMap)[inParams.curDb] = retDbDataMap + } + + // DELETE operation: mark child entries + if inParams.oper == DELETE { + pathInfo := NewPathInfo(inParams.requestUri) + key := pathInfo.Var("index") + if key != "" { + key = "CH" + key + } + + childTables := []string{ETHERNET_TBL, OTN_TBL} + for _, tbl := range childTables { + if retDbDataMap[tbl] == nil { + retDbDataMap[tbl] = make(map[string]db.Value) + } + + if key != "" { + // Mark specific key for deletion + retDbDataMap[tbl][key] = db.Value{} + } else { + // Mark all keys for deletion + retDbDataMap[tbl] = make(map[string]db.Value) + } + } + } + + return retDbDataMap, nil +} + +func DbToYang_ethernet_subtree_xfmr(inParams XfmrParams) error { + log.Infof("EthernetStateTransformer Subtree - URI: %s", inParams.uri) + + pathInfo := NewPathInfo(inParams.uri) + channelIDStr := pathInfo.Var("index") + channelID, err := strconv.ParseUint(channelIDStr, 10, 32) + if err != nil { + log.Errorf("Invalid channel ID format: %s", channelIDStr) + return err + } + + // Get root object for YANG model + root := getTerminalDeviceRootObj(inParams.ygRoot) + if root == nil { + log.Warning("Root YANG object is nil") + return nil + } + + if root.LogicalChannels == nil { + root.LogicalChannels = &ocbinds.OpenconfigTerminalDevice_TerminalDevice_LogicalChannels{} + } + + if root.LogicalChannels.Channel == nil { + root.LogicalChannels.Channel = make(map[uint32]*ocbinds.OpenconfigTerminalDevice_TerminalDevice_LogicalChannels_Channel) + } + + if root.LogicalChannels.Channel[uint32(channelID)] == nil { + root.LogicalChannels.Channel[uint32(channelID)] = &ocbinds.OpenconfigTerminalDevice_TerminalDevice_LogicalChannels_Channel{} + } + + channel := root.LogicalChannels.Channel[uint32(channelID)] + + if channel.Ethernet == nil { + channel.Ethernet = &ocbinds.OpenconfigTerminalDevice_TerminalDevice_LogicalChannels_Channel_Ethernet{} + } + + ygot.BuildEmptyTree(channel.Ethernet.State) // Build the State tree if nil + + state := channel.Ethernet.State + + // Access databases for state data + countersDb := inParams.dbs[db.CountersDB] + stateDb := inParams.dbs[db.StateDB] + + // Key generation + stateKey := "CH" + channelIDStr + countersKey := stateKey + ":15_pm_current" + + // Fetch counters data from COUNTERS_DB + countersTbl := "ETHERNET" + countersVal, err := countersDb.GetEntry(&db.TableSpec{Name: countersTbl}, db.Key{Comp: []string{countersKey}}) + if err != nil { + log.Errorf("Error fetching from COUNTERS_DB with key %s: %v", countersKey, err) + return err + } + + // Fields to be transformed from COUNTERS_DB + fields := []string{ + "in-block-errors", "in-fragment-frames", "in-jabber-frames", + "in-pcs-bip-errors", "in-pcs-errored-seconds", "in-pcs-severely-errored-seconds", + "out-block-errors", "out-pcs-bip-errors", + } + + // Process the fields and populate the state + for _, field := range fields { + val := countersVal.Get(field) + if val == "" { + continue + } + + parsed, err := strconv.ParseUint(val, 10, 64) + if err != nil { + log.Warningf("Could not parse %s: %v", field, err) + continue + } + + switch field { + case "in-block-errors": + state.InBlockErrors = ygot.Uint64(parsed) + case "in-fragment-frames": + state.InFragmentFrames = ygot.Uint64(parsed) + case "in-jabber-frames": + state.InJabberFrames = ygot.Uint64(parsed) + case "in-pcs-bip-errors": + state.InPcsBipErrors = ygot.Uint64(parsed) + case "in-pcs-errored-seconds": + state.InPcsErroredSeconds = ygot.Uint64(parsed) + case "in-pcs-severely-errored-seconds": + state.InPcsSeverelyErroredSeconds = ygot.Uint64(parsed) + case "out-block-errors": + state.OutBlockErrors = ygot.Uint64(parsed) + case "out-pcs-bip-errors": + state.OutPcsBipErrors = ygot.Uint64(parsed) + } + } + + // Fetch state data from STATE_DB + stateTbl := "ETHERNET_TABLE" + stateVal, err := stateDb.GetEntry(&db.TableSpec{Name: stateTbl}, db.Key{Comp: []string{stateKey}}) + if err != nil { + log.Errorf("Error fetching from STATE_DB with key %s: %v", stateKey, err) + return err + } + + // Process als_delay + if val := stateVal.Get("als-delay"); val != "" { + if parsed, err := strconv.ParseUint(val, 10, 32); err == nil { + als := uint32(parsed) + state.AlsDelay = &als + } else { + log.Warningf("Invalid als_delay value: %s", val) + } + } + + // Process client_als + if val := stateVal.Get("client-als"); val != "" { + var enumVal ocbinds.E_OpenconfigTerminalDevice_TerminalDevice_LogicalChannels_Channel_Ethernet_Config_ClientAls + switch val { + case "UNSET": + enumVal = ocbinds.OpenconfigTerminalDevice_TerminalDevice_LogicalChannels_Channel_Ethernet_Config_ClientAls_UNSET + case "NONE": + enumVal = ocbinds.OpenconfigTerminalDevice_TerminalDevice_LogicalChannels_Channel_Ethernet_Config_ClientAls_NONE + case "LASER_SHUTDOWN": + enumVal = ocbinds.OpenconfigTerminalDevice_TerminalDevice_LogicalChannels_Channel_Ethernet_Config_ClientAls_LASER_SHUTDOWN + case "ETHERNET": + enumVal = ocbinds.OpenconfigTerminalDevice_TerminalDevice_LogicalChannels_Channel_Ethernet_Config_ClientAls_ETHERNET + default: + log.Warningf("Unknown client_als value: %s", val) + } + + state.ClientAls = enumVal + } + + // Log the state values + log.Infof("Ethernet State for Channel %d:", channelID) + log.Infof(" InBlockErrors: %v", state.InBlockErrors) + log.Infof(" InFragmentFrames: %v", state.InFragmentFrames) + log.Infof(" InJabberFrames: %v", state.InJabberFrames) + log.Infof(" InPcsBipErrors: %v", state.InPcsBipErrors) + log.Infof(" InPcsErroredSeconds: %v", state.InPcsErroredSeconds) + log.Infof(" InPcsSeverelyErroredSeconds: %v", state.InPcsSeverelyErroredSeconds) + log.Infof(" OutBlockErrors: %v", state.OutBlockErrors) + log.Infof(" OutPcsBipErrors: %v", state.OutPcsBipErrors) + log.Infof(" AlsDelay: %v", state.AlsDelay) + log.Infof(" ClientAls: %v", state.ClientAls) + + log.Infof("Transformed Ethernet State for Channel %d", channelID) + return nil +} + +var Subscribe_ethernet_subtree_xfmr SubTreeXfmrSubscribe = func(inParams XfmrSubscInParams) (XfmrSubscOutParams, error) { + var err error + var result XfmrSubscOutParams + result.dbDataMap = make(RedisDbSubscribeMap) + + pathInfo := NewPathInfo(inParams.uri) + channelIDStr := pathInfo.Var("index") + + var stateKey, countersKey string + + if channelIDStr == "" { + // Wildcard case + stateKey = "*" + countersKey = "*" + } else { + // Specific key case + stateKey = "CH" + channelIDStr + countersKey = stateKey + ":15_pm_current" + } + + log.Infof("Subscribe_ethernet_xfmr - stateKey: %s, countersKey: %s", stateKey, countersKey) + + result.dbDataMap = RedisDbSubscribeMap{ + db.CountersDB: { + "ETHERNET": { + countersKey: { + "in-block-errors": "in-block-errors", + "in-fragment-frames": "in-fragment-frames", + "in-jabber-frames": "in-jabber-frames", + "in-pcs-bip-errors": "in-pcs-bip-errors", + "in-pcs-errored-seconds": "in-pcs-errored-seconds", + "in-pcs-severely-errored-seconds": "in-pcs-severely-errored-seconds", + "out-block-errors": "out-block-errors", + "out-pcs-bip-errors": "out-pcs-bip-errors", + }, + }, + }, + db.StateDB: { + "ETHERNET_TABLE": { + stateKey: { + "als-delay": "als-delay", + "client-als": "client-als", + }, + }, + }, + db.ConfigDB: { + "ETHERNET": { + stateKey: { + "als-delay": "als-delay", + "client-als": "client-als", + }, + }, + }, + } + + return result, err +} diff --git a/translib/transformer/xfmr_terminal_device_test.go b/translib/transformer/xfmr_terminal_device_test.go new file mode 100644 index 000000000..f1989f1d7 --- /dev/null +++ b/translib/transformer/xfmr_terminal_device_test.go @@ -0,0 +1,376 @@ +//go:build xfmrtest +// +build xfmrtest + +package transformer_test + +import ( + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "testing" + "time" +) + +/* terminal device counters, state DB fields and values */ +func Test_terminal_device_config_state_counter_DB_key(t *testing.T) { + var pre_req_map, cleanuptbl, cleanupstatetbl, cleanupcountertbl map[string]interface{} + var expected_get_json, url []string + + for idx, dbName := range getMdbNames() { + /* terminal device config DB test */ + t.Log("\n\n+++++++++++++ Performing Get on configDB terminal device Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "OC_COMPONENT": map[string]interface{}{ + fmt.Sprintf("OCH-1-%d-L2", idx+1): map[string]interface{}{ + "name": fmt.Sprintf("OCH-1-%d-L2", idx+1), + }, + }, + "OCH": map[string]interface{}{ + fmt.Sprintf("OCH-1-%d-L2", idx+1): map[string]interface{}{ + "operational-mode": "test_data", + "frequency": "2", + "target-output-power": "0.0", + }, + }, + "LOGICAL_CHANNEL": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): map[string]interface{}{ + "test-signal": "false", + "loopback-mode": "NONE", + "admin-state": "MAINT", + }, + }, + "ETHERNET": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): map[string]interface{}{ + "index": fmt.Sprintf("%d02", idx+1), + "client-als": "LASER_SHUTDOWN", + "als-delay": 1000, // float to string + + }, + }, + "LLDP": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): map[string]interface{}{ + "index": fmt.Sprintf("%d02", idx+1), + "enabled": "true", + "snooping": "true", + }, + }, + } + loadDB(dbName, db.ConfigDB, pre_req_map) + time.Sleep(1 * time.Second) + expected_get_json = []string{fmt.Sprintf("{\"openconfig-terminal-device:config\":{\"admin-state\":\"MAINT\",\"index\":%d02,\"loopback-mode\":\"NONE\",\"test-signal\":false}}", idx+1), "{\"openconfig-terminal-device:config\":{\"als-delay\":1000,\"client-als\":\"LASER_SHUTDOWN\"}}"} + url = []string{ + fmt.Sprintf("/openconfig-terminal-device:terminal-device/logical-channels/channel[index=%d02]/config", idx+1), + fmt.Sprintf("/openconfig-terminal-device:terminal-device/logical-channels/channel[index=%d02]/ethernet/config", idx+1), + } + + for idx, url := range url { + t.Run("Test get on config DB Key for "+url, processGetRequest(url, nil, expected_get_json[idx], false)) + time.Sleep(1 * time.Second) + } + t.Log("\n\n+++++++++++++ Done Performing Get on configDB terminal device Key ++++++++++++") + + /* terminal device state DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB terminal device Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "LOGICAL_CHANNEL_TABLE": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): map[string]interface{}{ + "index": fmt.Sprintf("%d02", idx+1), + "rate-class": "TRIB_RATE_200G", + "description": "GE-1-1-C3", + "loopback-mode": "NONE", + "test-signal": "false", + "admin-state": "MAINT", + "trib-protocol": "PROT_1GE", + "link-state": "DOWN", + }, + }, + "ETHERNET_TABLE": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): map[string]interface{}{ + "index": fmt.Sprintf("%d02", idx+1), + "client-als": "LASER_SHUTDOWN", + "als-delay": 1000, + }, + }, + "LLDP_TABLE": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): map[string]interface{}{ + "index": fmt.Sprintf("%d02", idx+1), + "enabled": "true", + "snooping": "true", + }, + }, + "NEIGHBOR_TABLE": map[string]interface{}{ + fmt.Sprintf("CH%d02|1", idx+1): map[string]interface{}{ + "id": "1", + "system-name": "test_sysname", + "system-description": "test_desc", + "chassis-id": "test_chassis_id", + "chassis-id-type": "PORT_COMPONENT", + "age": "12", + "last-update": "12", + "ttl": "100", + "port-id": "test_portid", + "port-id-type": "PORT_COMPONENT", + "port-description": "test_pdes", + "management-address": "test_mg_add", + "management-address-type": "test_mg_type", + }, + }, + "ASSIGNMENT_TABLE": map[string]interface{}{ + fmt.Sprintf("CH%d02|ASS1", idx+1): map[string]interface{}{ + "index": fmt.Sprintf("%d02", idx+1), + "assignment-type": "LOGICAL_CHANNEL", + "description": "ASSIGNMENT-1-1-18", + "tributary-slot-index": "1", + "mapping": "GMP", + "allocation": "400.0", + "logical-channel": "102", + "optical-channel": "102", + }, + }, + "MODE_TABLE": map[string]interface{}{ + fmt.Sprintf("%d02", idx+1): map[string]interface{}{ + "mode-id": fmt.Sprintf("%d02", idx+1), + "description": "600G::DP-64QAM::FEC-15::63.054::BICHM[0]", + "vendor-id": "Accelink", + }, + }, + } + loadDB(dbName, db.StateDB, pre_req_map) + time.Sleep(1 * time.Second) + expected_get_json = []string{ + fmt.Sprintf("{\"openconfig-terminal-device:state\":{\"admin-state\":\"MAINT\",\"description\":\"GE-1-1-C3\",\"index\":%d02,\"link-state\":\"DOWN\",\"loopback-mode\":\"NONE\",\"rate-class\":\"openconfig-transport-types:TRIB_RATE_200G\",\"test-signal\":false,\"trib-protocol\":\"openconfig-transport-types:PROT_1GE\"}}", idx+1), + + fmt.Sprintf("{\"openconfig-terminal-device:state\":{\"description\":\"600G::DP-64QAM::FEC-15::63.054::BICHM[0]\",\"mode-id\":%d02,\"vendor-id\":\"Accelink\"}}", idx+1), + + "{\"openconfig-terminal-device:state\":{\"age\":\"12\",\"chassis-id\":\"test_chassis_id\",\"chassis-id-type\":\"PORT_COMPONENT\",\"id\":\"1\",\"last-update\":\"12\",\"management-address\":\"test_mg_add\",\"management-address-type\":\"test_mg_type\",\"port-description\":\"test_pdes\",\"port-id\":\"test_portid\",\"port-id-type\":\"PORT_COMPONENT\",\"system-description\":\"test_desc\",\"system-name\":\"test_sysname\",\"ttl\":100}}", + } + url = []string{ + fmt.Sprintf("/openconfig-terminal-device:terminal-device/logical-channels/channel[index=%d02]/state", idx+1), + fmt.Sprintf("/openconfig-terminal-device:terminal-device/operational-modes/mode[mode-id=%d02]/state", idx+1), + fmt.Sprintf("/openconfig-terminal-device:terminal-device/logical-channels/channel[index=%d02]/ethernet/lldp/neighbors/neighbor[id=1]/state", idx+1), + } + for idx, url := range url { + t.Run("Test get on state DB Key for "+url, processGetRequest(url, nil, expected_get_json[idx], false)) + time.Sleep(1 * time.Second) + } + t.Log("\n\n+++++++++++++ Done Performing Get on configDB terminal device Key ++++++++++++") + + /* terminal monitor Counters DB test */ + t.Log("\n\n+++++++++++++ Performing Get on counterDB terminal device Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "ETHERNET": map[string]interface{}{ + fmt.Sprintf("CH%d02:15_pm_current", idx+1): map[string]interface{}{ + "in-pcs-errored-seconds": "0", + "out-pcs-bip-errors": "0", + "in-block-errors": "0", + "out-block-errors": "0", + "in-pcs-severely-errored-seconds": "0", + "in-pcs-bip-errors": "0", + "in-jabber-frames": "0", + "in-fragment-frames": "0", + "in-oversize-frames": "0", + "out-crc-errors": "0", + "in-pcs-unavailable-seconds": "0", + "in-undersize-frames": "0", + "in-crc-errors": "0", + }, + }, + } + loadDB(dbName, db.CountersDB, pre_req_map) + expected_get_json = []string{"{\"openconfig-terminal-device:state\":{\"als-delay\":1000,\"client-als\":\"LASER_SHUTDOWN\",\"in-block-errors\":\"0\",\"in-fragment-frames\":\"0\",\"in-jabber-frames\":\"0\",\"in-pcs-bip-errors\":\"0\",\"in-pcs-errored-seconds\":\"0\",\"in-pcs-severely-errored-seconds\":\"0\",\"out-block-errors\":\"0\",\"out-pcs-bip-errors\":\"0\"}}"} + url = []string{fmt.Sprintf("/openconfig-terminal-device:terminal-device/logical-channels/channel[index=%d02]/ethernet/state", idx+1)} + t.Run("Test get on counter DB Ethernet Key-Xfmr and Field-Xfmr.", processGetRequest(url[0], nil, expected_get_json[0], false)) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Get on counterDB terminal device Key ++++++++++++") + + //Unload the Data + cleanuptbl = map[string]interface{}{ + "OCH": map[string]interface{}{ + fmt.Sprintf("OCH-1-%d-L2", idx+1): "", + }, + "OC_COMPONENT": map[string]interface{}{ + fmt.Sprintf("OCH-1-%d-L2", idx+1): "", + }, + "LOGICAL_CHANNEL": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): "", + }, + "ETHERNET": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): "", + }, + "LLDP": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): "", + }, + } + unloadDB(dbName, db.ConfigDB, cleanuptbl) + + cleanupstatetbl = map[string]interface{}{ + "LOGICAL_CHANNEL_TABLE": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): "", + }, + "ETHERNET_TABLE": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): "", + }, + "LLDP_TABLE": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): "", + }, + "NEIGHBOR_TABLE": map[string]interface{}{ + fmt.Sprintf("CH%d02|1", idx+1): "", + }, + "ASSIGNMENT_TABLE": map[string]interface{}{ + fmt.Sprintf("CH%d02|ASS1", idx+1): "", + }, + "MODE_TABLE": map[string]interface{}{ + fmt.Sprintf("%d02", idx+1): "", + }, + } + unloadDB(dbName, db.StateDB, cleanupstatetbl) + + cleanupcountertbl = map[string]interface{}{ + "ETHERNET": map[string]interface{}{ + fmt.Sprintf("CH%d02:15_pm_current", idx+1): "", + }, + } + unloadDB(dbName, db.CountersDB, cleanupcountertbl) + } +} + +func Test_set_terminal_device_config_DB_key_and_field_xfmr(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing Create/Replace/Delete on terminal_device ++++++++++++") + + for idx, dbName := range getMdbNames() { + url := fmt.Sprintf("/openconfig-terminal-device:terminal-device/logical-channels/channel[index=%d02]/config", idx+1) + url_body_json := "{\"config\":{\"loopback-mode\":\"NONE\",\"admin-state\":\"ENABLED\",\"test-signal\":true}}" + + pre_req_map := map[string]interface{}{ + "LOGICAL_CHANNEL": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): map[string]interface{}{ + "test-signal": "false", + "loopback-mode": "NONE", + "admin-state": "MAINT", + }, + }, + } + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_map := map[string]interface{}{ + "LOGICAL_CHANNEL": map[string]interface{}{ + fmt.Sprintf("CH%d02", idx+1): map[string]interface{}{ + "test-signal": "true", + "loopback-mode": "NONE", + "admin-state": "ENABLED", + }, + }, + } + time.Sleep(1 * time.Second) + + //PUT Test + t.Run("Replace Test on terminal_device yang", processSetRequest(url, url_body_json, "PUT", false)) + time.Sleep(1 * time.Second) + + //GET Test + t.Run("Verify replace on terminal_device yang", verifyDbResult(rclient[dbName], fmt.Sprintf("LOGICAL_CHANNEL|CH%d02", idx+1), expected_map, false)) + time.Sleep(1 * time.Second) + + //Delete Test + url = fmt.Sprintf("/openconfig-terminal-device:terminal-device/logical-channels/channel[index=%d02]/config", idx+1) + t.Run("DELETE Test on terminal_device yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + //POST Test + url = "/openconfig-terminal-device:terminal-device/logical-channels" + post_payload := fmt.Sprintf("{\"channel\":[{\"index\":%d03,\"config\":{\"loopback-mode\":\"NONE\",\"admin-state\":\"ENABLED\",\"test-signal\":true}}]}", idx+1) + t.Run("Create test on terminal_device yang", processSetRequest(url, post_payload, "POST", false)) + time.Sleep(1 * time.Second) + + expected_map = map[string]interface{}{ + "LOGICAL_CHANNEL": map[string]interface{}{ + fmt.Sprintf("CH%d03", idx+1): map[string]interface{}{ + "test-signal": "true", + "loopback-mode": "NONE", + "admin-state": "ENABLED", + }, + }, + } + + //Verify After the POST test + t.Run("Verify After the POST test on terminal_device yang", verifyDbResult(rclient[dbName], fmt.Sprintf("LOGICAL_CHANNEL|CH%d03", idx+1), expected_map, false)) + + //Delete After the POST test + url = fmt.Sprintf("/openconfig-terminal-device:terminal-device/logical-channels/channel[index=%d03]/config", idx+1) + t.Run("DELETE After the POST test on terminal_device yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = "/openconfig-terminal-device:terminal-device/logical-channels" + //Bulk POST Test + Bulk_post_payload := fmt.Sprintf("{\"channel\":[{\"index\":%d04,\"config\":{\"loopback-mode\":\"NONE\",\"admin-state\":\"ENABLED\",\"test-signal\":true}},{\"index\":%d05,\"config\":{\"loopback-mode\":\"NONE\",\"admin-state\":\"ENABLED\",\"test-signal\":false}}]}", idx+1, idx+1) + t.Run("Create test on terminal_device yang", processSetRequest(url, Bulk_post_payload, "POST", false)) + + expected_map = map[string]interface{}{ + "LOGICAL_CHANNEL": map[string]interface{}{ + fmt.Sprintf("CH%d04", idx+1): map[string]interface{}{ + "test-signal": "true", + "loopback-mode": "NONE", + "admin-state": "ENABLED", + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the Bulk test + t.Run("Verify After the Bulk test on terminal_device yang", verifyDbResult(rclient[dbName], fmt.Sprintf("LOGICAL_CHANNEL|CH%d04", idx+1), expected_map, false)) + + expected_map = map[string]interface{}{ + "LOGICAL_CHANNEL": map[string]interface{}{ + fmt.Sprintf("CH%d05", idx+1): map[string]interface{}{ + "test-signal": "false", + "loopback-mode": "NONE", + "admin-state": "ENABLED", + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the POST test + t.Run("Verify After the Bulk test on terminal_device yang", verifyDbResult(rclient[dbName], fmt.Sprintf("LOGICAL_CHANNEL|CH%d05", idx+1), expected_map, false)) + + //Delete keys After the Bulk Test + url = fmt.Sprintf("/openconfig-terminal-device:terminal-device/logical-channels/channel[index=%d04]/config", idx+1) + t.Run("DELETE After the Bulk Test on terminal_device yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = fmt.Sprintf("/openconfig-terminal-device:terminal-device/logical-channels/channel[index=%d05]/config", idx+1) + t.Run("DELETE After the Bulk Test on terminal_device yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + } + + t.Log("\n\n+++++++++++++ Done Performing Create/Replace/Delete on terminal_device ++++++++++++") +} + +func Test_terminal_device_allow_write_multiple_namespace(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing terminal_device write for multiple namespace (should be allowed) ++++++++++++") + + url := "/openconfig-terminal-device:terminal-device/logical-channels" + url_body_json := `{ + "channel": [ + { + "index": 104, + "config": { + "loopback-mode": "NONE", + "admin-state": "ENABLED", + "test-signal": true + } + }, + { + "index": 205, + "config": { + "loopback-mode": "NONE", + "admin-state": "ENABLED", + "test-signal": false + } + } + ] + }` + + // false = no error expected + t.Run("Test allow writing multiple namespace for terminal_device", processSetRequest(url, url_body_json, "POST", false, nil)) + + t.Log("\n\n+++++++++++++ Done Performing terminal_device write for multiple namespace ++++++++++++") +} diff --git a/translib/transformer/xfmr_tlmt.go b/translib/transformer/xfmr_tlmt.go new file mode 100644 index 000000000..6dccc3a08 --- /dev/null +++ b/translib/transformer/xfmr_tlmt.go @@ -0,0 +1,619 @@ +package transformer + +import ( + "github.com/Azure/sonic-mgmt-common/translib/db" + log "github.com/golang/glog" + "strconv" + "strings" +) + +const ( + OPENCONFIG_YANG = "/openconfig-" + SONIC_YANG = "/sonic-" + DESTINATION_ADDRESS = "destination-address" + DESTINATION_PORT = "destination-port" + SENSOR_GROUP_TBL = "SENSOR_GROUP" + DEST_GROUP_TBL = "DESTINATION_GROUP" + DESTINATION_TBL = "DESTINATION" + TELEMETRY_CLIENT_TBL = "TELEMETRY_CLIENT" + SUB_DEST_GROUP_TBL = "SUBSCRIPTION_DESTINATION_GROUP" + SENSOR_PROFILE_TBL = "SENSOR_PROFILE" + GLOBAL_KEY = "Global" +) + +func init() { + + /* Key transformer for SENSOR_GROUP table*/ + XlateFuncBind("YangToDb_telemetry_sensor_group_id_key_xfmr", YangToDb_telemetry_sensor_group_id_key_xfmr) + XlateFuncBind("DbToYang_telemetry_sensor_group_id_key_xfmr", DbToYang_telemetry_sensor_group_id_key_xfmr) + XlateFuncBind("YangToDb_telemetry_sensor_path_key_xfmr", YangToDb_telemetry_sensor_path_key_xfmr) + XlateFuncBind("DbToYang_telemetry_sensor_path_key_xfmr", DbToYang_telemetry_sensor_path_key_xfmr) + + /* Field transformer for SENSOR_GROUP table*/ + XlateFuncBind("YangToDb_telemetry_sensor_group_id_field_xfmr", YangToDb_telemetry_sensor_group_id_field_xfmr) + XlateFuncBind("DbToYang_telemetry_sensor_group_id_field_xfmr", DbToYang_telemetry_sensor_group_id_field_xfmr) + + /* Key transformer for DESTINATION_GROUP and table*/ + XlateFuncBind("YangToDb_telemetry_group_id_key_xfmr", YangToDb_telemetry_group_id_key_xfmr) + XlateFuncBind("DbToYang_telemetry_group_id_key_xfmr", DbToYang_telemetry_group_id_key_xfmr) + + /* Field transformer for DESTINATION_GROUP table*/ + XlateFuncBind("YangToDb_telemetry_group_id_field_xfmr", YangToDb_telemetry_group_id_field_xfmr) + XlateFuncBind("DbToYang_telemetry_group_id_field_xfmr", DbToYang_telemetry_group_id_field_xfmr) + + /* Key transformer for SUBSCRIPTION_DESTINATION_GROUP table*/ + XlateFuncBind("YangToDb_telemetry_sub_dest_group_id_key_xfmr", YangToDb_telemetry_sub_dest_group_id_key_xfmr) + XlateFuncBind("DbToYang_telemetry_sub_dest_group_id_key_xfmr", DbToYang_telemetry_sub_dest_group_id_key_xfmr) + + /* Field transformer for SUBSCRIPTION_DESTINATION_GROUP table*/ + XlateFuncBind("YangToDb_telemetry_sub_dest_group_id_field_xfmr", YangToDb_telemetry_sub_dest_group_id_field_xfmr) + XlateFuncBind("DbToYang_telemetry_sub_dest_group_id_field_xfmr", DbToYang_telemetry_sub_dest_group_id_field_xfmr) + + /* Key transformer for DESTINATION table */ + XlateFuncBind("YangToDb_telemetry_destination_key_xfmr", YangToDb_telemetry_destination_key_xfmr) + XlateFuncBind("DbToYang_telemetry_destination_key_xfmr", DbToYang_telemetry_destination_key_xfmr) + + /* Field transformer for DESTINATION table */ + XlateFuncBind("YangToDb_telemetry_destination_address_field_xfmr", YangToDb_telemetry_destination_address_field_xfmr) + XlateFuncBind("DbToYang_telemetry_destination_address_field_xfmr", DbToYang_telemetry_destination_address_field_xfmr) + XlateFuncBind("YangToDb_telemetry_destination_port_field_xfmr", YangToDb_telemetry_destination_port_field_xfmr) + XlateFuncBind("DbToYang_telemetry_destination_port_field_xfmr", DbToYang_telemetry_destination_port_field_xfmr) + + /* Key transformer for PERSISTENT_SUBSCRIPTION table */ + + /* Key transformer for PERSISTENT_SUBSCRIPTION table */ + XlateFuncBind("YangToDb_telemetry_persistent_subscription_key_xfmr", YangToDb_telemetry_persistent_subscription_key_xfmr) + XlateFuncBind("DbToYang_telemetry_persistent_subscription_key_xfmr", DbToYang_telemetry_persistent_subscription_key_xfmr) + + /* Field transformer for PERSISTENT_SUBSCRIPTION table */ + XlateFuncBind("YangToDb_telemetry_persistent_subscription_field_xfmr", YangToDb_telemetry_persistent_subscription_field_xfmr) + XlateFuncBind("DbToYang_telemetry_persistent_subscription_field_xfmr", DbToYang_telemetry_persistent_subscription_field_xfmr) + + /* Key transformer for SENSOR_PROFILE table */ + XlateFuncBind("YangToDb_telemetry_sensor_profile_key_xfmr", YangToDb_telemetry_sensor_profile_key_xfmr) + XlateFuncBind("DbToYang_telemetry_sensor_profile_key_xfmr", DbToYang_telemetry_sensor_profile_key_xfmr) + + /* Field transformer for SENSOR_PROFILE table */ + XlateFuncBind("YangToDb_telemetry_sensor_profile_field_xfmr", YangToDb_telemetry_sensor_profile_field_xfmr) + XlateFuncBind("DbToYang_telemetry_sensor_profile_field_xfmr", DbToYang_telemetry_sensor_profile_field_xfmr) + + /* Get Namespace transformer for Telemetry */ + XlateFuncBind("telemetry_get_namespace_xfmr", telemetry_get_namespace_xfmr) + + XlateFuncBind("telemetry_client_sync_post_xfmr", telemetry_client_sync_post_xfmr) +} + +var YangToDb_telemetry_sensor_group_id_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_telemetry_sensor_group_id_key_xfmr root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("sensor-group-id") + log.V(3).Infof("YangToDb_telemetry_sensor_group_id_key_xfmr : key", key) + + return key, nil +} + +var DbToYang_telemetry_sensor_group_id_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + log.V(3).Info("DbToYang_telemetry_sensor_group_id_key_xfmr: ", inParams.key) + rmap["sensor-group-id"] = inParams.key + + return rmap, nil +} + +var YangToDb_telemetry_sensor_group_id_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_telemetry_sensor_group_id_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + rmap["sensor-group-id"] = inParams.key + + return rmap, nil +} + +var YangToDb_telemetry_sensor_path_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_telemetry_sensor_path_key_xfmr root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("sensor-group-id") + log.V(3).Infof("YangToDb_telemetry_sensor_path_key_xfmr : key", key) + + return key, nil +} + +var DbToYang_telemetry_sensor_path_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + pathInfo := NewPathInfo(inParams.uri) + rmap["path"] = pathInfo.Var("path") + + return rmap, nil +} + +var YangToDb_telemetry_group_id_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_telemetry_group_id_key_xfmr root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + key := pathInfo.Var("group-id") + log.V(3).Infof("YangToDb_telemetry_group_id_key_xfmr : key", key) + + return key, nil +} + +var DbToYang_telemetry_group_id_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + rmap["group-id"] = inParams.key + + return rmap, nil +} + +var YangToDb_telemetry_group_id_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_telemetry_group_id_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + rmap["group-id"] = inParams.key + + return rmap, nil +} + +var YangToDb_telemetry_destination_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_telemetry_destination_key_xfmr root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + group_id := pathInfo.Var("group-id") + dest_addr := pathInfo.Var("destination-address") + dest_port := pathInfo.Var("destination-port") + key := group_id + "|" + dest_addr + "|" + dest_port + + log.V(3).Infof("YangToDb_telemetry_destination_key_xfmr : key", key) + + return key, nil +} + +var DbToYang_telemetry_destination_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + keyParts := strings.Split(inParams.key, "|") + rmap["group-id"] = keyParts[0] + rmap["destination-address"] = keyParts[1] + rmap["destination-port"] = keyParts[2] + + log.V(3).Infof("DbToYang_telemetry_destination_key_xfmr : rmap:%v", rmap) + + return rmap, nil +} + +var YangToDb_telemetry_destination_address_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + log.V(3).Infof("YangToDb_telemetry_destination_address_field_xfmr : inParams.uri:%v", inParams.uri) + rmap["NULL"] = "NULL" + return rmap, nil +} + +var DbToYang_telemetry_destination_address_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Infof("DbToYang_telemetry_destination_address_field_xfmr : inParams.key:%v", inParams.key) + rmap := make(map[string]interface{}, 1) + keyParts := strings.Split(inParams.key, "|") + rmap["group-id"] = keyParts[0] + rmap["destination-address"] = keyParts[1] + + return rmap, nil +} + +var YangToDb_telemetry_destination_port_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + log.V(3).Infof("YangToDb_telemetry_destination_port_field_xfmr : inParams.uri:%v", inParams.uri) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_telemetry_destination_port_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + log.V(3).Infof("DbToYang_telemetry_destination_port_field_xfmr : inParams.key:%v", inParams.key) + rmap := make(map[string]interface{}, 1) + keyParts := strings.Split(inParams.key, "|") + rmap["group-id"] = keyParts[0] + rmap["destination-port"] = keyParts[2] + + return rmap, nil +} + +var YangToDb_telemetry_persistent_subscription_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_telemetry_persistent_subscription_key_xfmr root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + key := pathInfo.Var("name") + log.V(3).Infof("YangToDb_telemetry_persistent_subscription_key_xfmr : key", key) + + return key, nil +} + +var DbToYang_telemetry_persistent_subscription_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + rmap["name"] = inParams.key + + return rmap, nil +} + +var YangToDb_telemetry_persistent_subscription_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + return rmap, nil +} + +var DbToYang_telemetry_persistent_subscription_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + rmap["name"] = inParams.key + + return rmap, nil +} + +var YangToDb_telemetry_sensor_profile_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_telemetry_sensor_profile_key_xfmr root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + sensor_group := pathInfo.Var("sensor-group") + sub_name := pathInfo.Var("name") + key := sub_name + "|" + sensor_group + log.V(3).Infof("YangToDb_telemetry_sensor_profile_key_xfmr : key", key) + + return key, nil +} + +var DbToYang_telemetry_sensor_profile_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + parts := strings.Split(inParams.key, "|") + rmap["name"] = parts[0] + rmap["sensor-group"] = parts[1] + + return rmap, nil +} + +var YangToDb_telemetry_sensor_profile_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_telemetry_sensor_profile_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + + parts := strings.Split(inParams.key, "|") + rmap["name"] = parts[0] + rmap["sensor-group"] = parts[1] + + return rmap, nil +} + +var YangToDb_telemetry_sub_dest_group_id_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_telemetry_sub_dest_group_id_key_xfmr root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + sub_name := pathInfo.Var("name") + group_id := pathInfo.Var("group-id") + key := sub_name + "|" + group_id + + log.V(3).Infof("YangToDb_telemetry_sub_dest_group_id_key_xfmr : key", key) + + return key, nil +} + +var DbToYang_telemetry_sub_dest_group_id_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + parts := strings.Split(inParams.key, "|") + rmap["name"] = parts[0] + rmap["group-id"] = parts[1] + + return rmap, nil +} + +var YangToDb_telemetry_sub_dest_group_id_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_telemetry_sub_dest_group_id_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + + parts := strings.Split(inParams.key, "|") + rmap["name"] = parts[0] + rmap["group-id"] = parts[1] + + return rmap, nil +} + +var telemetry_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]NamespacePayload, error) { + // Since Telemetry configuration is stored only in HOST db. + return []NamespacePayload{ + { + Namespace: "host", + Payloads: []map[string]interface{}{}, + Key: "", + }, + }, nil + +} + +// Function to determine path_target based on sensorPaths +func determinePathTarget(sensorPaths string) string { + + if strings.Contains(sensorPaths, OPENCONFIG_YANG) { + return "OC-YANG" + } else if strings.Contains(sensorPaths, SONIC_YANG) { + // Adjust this logic based on your requirements for SONIC_YANG + return "" // Placeholder, replace with actual value + } + + // Default case if neither OPENCONFIG_YANG nor SONIC_YANG is found + return "" +} + +func processSensorGroup(retDbDataMap map[string]map[string]db.Value, sensorGroupId, sensorPaths string) { + + if sensorGroupId != "" && sensorPaths != "" { + // Forming key for TELEMETRY_CLIENT table + tclientKey := "Subscription_" + sensorGroupId + log.V(3).Info(" processSensorGroup:tclientKey ", tclientKey) + + // Populating TELEMETRY_CLIENT table + retDbDataMap[TELEMETRY_CLIENT_TBL][tclientKey] = db.Value{Field: make(map[string]string)} + retDbDataMap[TELEMETRY_CLIENT_TBL][tclientKey].Field["paths"] = sensorPaths + // Determine path_target + pathTarget := determinePathTarget(sensorPaths) + retDbDataMap[TELEMETRY_CLIENT_TBL][tclientKey].Field["path_target"] = pathTarget + } +} + +func processSubscriptions(retDbDataMap map[string]map[string]db.Value, sensorGroupId, subscriptionName, sample_interval, heartbeat_interval string) error { + + // Forming key for TELEMETRY_CLIENT table + tclientKey := "Subscription_" + sensorGroupId + log.V(3).Info(" processSubscriptions:tclientKey ", tclientKey) + sIntervalInt, err := strconv.Atoi(sample_interval) + if err != nil { + log.Errorf("Error in parsing sample_interval %s: %v", sample_interval, err) + return err + } + + hIntervalInt, err := strconv.Atoi(heartbeat_interval) + if err != nil { + log.Errorf("Error in parsing heartbeat_interval %s: %v", heartbeat_interval, err) + return err + } + + if sIntervalInt == 0 && hIntervalInt == 0 { + retDbDataMap[TELEMETRY_CLIENT_TBL][tclientKey].Field["report_type"] = "once" + } else if hIntervalInt > 0 { + retDbDataMap[TELEMETRY_CLIENT_TBL][tclientKey].Field["report_type"] = "stream" + } else { + retDbDataMap[TELEMETRY_CLIENT_TBL][tclientKey].Field["report_type"] = "periodic" + } + + retDbDataMap[TELEMETRY_CLIENT_TBL][tclientKey].Field["heartbeat_interval"] = heartbeat_interval + retDbDataMap[TELEMETRY_CLIENT_TBL][tclientKey].Field["report_interval"] = sample_interval + + for key, _ := range retDbDataMap[SUB_DEST_GROUP_TBL] { + if strings.Contains(key, subscriptionName) { + + parts := strings.Split(key, "|") + dest_group_name := parts[1] + log.V(3).Infof(" processSubscriptions: dest_group:%v", dest_group_name) + retDbDataMap[TELEMETRY_CLIENT_TBL][tclientKey].Field["dst_group"] = dest_group_name + } + } + + return nil +} + +func processDestinationGroup(retDbDataMap map[string]map[string]db.Value, destinationGroupId, destinationGroupAddress, destinationGroupPort string) { + + if destinationGroupId != "" && destinationGroupAddress != "" && destinationGroupPort != "" { + tclientDestGroupKey := "DestinationGroup_" + destinationGroupId + retDbDataMap[TELEMETRY_CLIENT_TBL][tclientDestGroupKey] = db.Value{Field: make(map[string]string)} + retDbDataMap[TELEMETRY_CLIENT_TBL][tclientDestGroupKey].Field["dst_addr"] = destinationGroupAddress + ":" + destinationGroupPort + } + +} + +func populateTelemetryGlobal(retDbDataMap map[string]map[string]db.Value) { + + retDbDataMap[TELEMETRY_CLIENT_TBL][GLOBAL_KEY] = db.Value{Field: make(map[string]string)} + // Encoding and unidirectional values are set in dialout_client.go + retDbDataMap[TELEMETRY_CLIENT_TBL][GLOBAL_KEY].Field["retry_interval"] = "20" +} + +func deleteTables(inParams XfmrParams) error { + + var tableNames []string + var keyValueContains string + + // Determine which tables to delete based on requestUri + switch { + case strings.Contains(inParams.requestUri, "sensor-groups"): + tableNames = append(tableNames, SENSOR_GROUP_TBL) + case strings.Contains(inParams.requestUri, "destination-groups"): + tableNames = append(tableNames, DEST_GROUP_TBL, DESTINATION_TBL, TELEMETRY_CLIENT_TBL) + keyValueContains = "DestinationGroup_" + case strings.Contains(inParams.requestUri, "subscriptions"): + tableNames = append(tableNames, SENSOR_PROFILE_TBL, SUB_DEST_GROUP_TBL, TELEMETRY_CLIENT_TBL) + keyValueContains = "Subscription_" + } + + for _, tableName := range tableNames { + telemetryTs := &db.TableSpec{Name: tableName} + telemetryKeys, err := inParams.d.GetKeys(telemetryTs) + if err != nil { + return err + } + + for key := range telemetryKeys { + telemetryClientKey := telemetryKeys[key].Get(0) + // Deleting only corresponding TELEMETRY_CLIENT entries according to requestUri path + if tableName == TELEMETRY_CLIENT_TBL && !strings.Contains(telemetryClientKey, GLOBAL_KEY) { + if tableName == TELEMETRY_CLIENT_TBL && !strings.Contains(telemetryClientKey, keyValueContains) { + continue + } + } + log.V(3).Info(" telemetry_client_sync_post_xfmr:deleteTables, Deleting", tableName) + log.V(3).Info(" telemetry_client_sync_post_xfmr:Key:", telemetryClientKey) + err := inParams.d.DeleteEntry(telemetryTs, telemetryKeys[key]) + if err != nil { + return err + } + } + } + return nil +} + +var telemetry_client_sync_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[string]map[string]db.Value, error) { + + retDbDataMap := (*inParams.dbDataMap)[inParams.curDb] + var sensorGroupId string + var destinationGroupId string + var subscriptionName string + + log.V(3).Info(" telemetry_client_sync_post_xfmr:Entering Request URI path = ", inParams.requestUri) + if inParams.oper == DELETE { + err := deleteTables(inParams) + if err != nil { + return retDbDataMap, err + } + return retDbDataMap, nil + } + + if retDbDataMap[TELEMETRY_CLIENT_TBL] == nil { + retDbDataMap[TELEMETRY_CLIENT_TBL] = make(map[string]db.Value) + } + + // Populating TELEMTRY_CLIENT|Global configurations + populateTelemetryGlobal(retDbDataMap) + + if strings.Contains(inParams.requestUri, "sensor-groups") { + + for sensorGroupId, _ := range retDbDataMap[SENSOR_GROUP_TBL] { + log.V(3).Infof(" telemetry_client_sync_post_xfmr:sensorGroupId:%v ", sensorGroupId) + sensorPaths := retDbDataMap[SENSOR_GROUP_TBL][sensorGroupId].Field["sensor-paths"] + log.V(3).Infof("telemetry_client_sync_post_xfmr:Sensor Group paths: %v", sensorPaths) + // Populating TELEMETRY_CLIENT table with sensor-group data + processSensorGroup(retDbDataMap, sensorGroupId, sensorPaths) + + } + } + if strings.Contains(inParams.requestUri, "subscriptions") { + + log.V(3).Infof(" telemetry_client_sync_post_xfmr:retDbDataMap:%v", retDbDataMap) + // Fetching SENSOR_GROUP table keys + sensorGroupTs := &db.TableSpec{Name: SENSOR_GROUP_TBL} + sensorGroupKeys, sensorGrpKeyserr := inParams.d.GetKeys(sensorGroupTs) + if sensorGrpKeyserr != nil { + return retDbDataMap, sensorGrpKeyserr + } + + for key := range sensorGroupKeys { + log.V(3).Infof(" telemetry_client_sync_post_xfmr:sensor_group_keys:%v ", sensorGroupKeys[key].Get(0)) + sensorGroupId = sensorGroupKeys[key].Get(0) + sensorGroupEntry, sensorGrpEntryerr := inParams.d.GetEntry(sensorGroupTs, sensorGroupKeys[key]) + if sensorGrpEntryerr != nil { + return retDbDataMap, sensorGrpEntryerr + } + sensorPaths := sensorGroupEntry.Get("sensor-paths") + log.V(3).Infof("telemetry_client_sync_post_xfmr:Sensor Group paths: %v", sensorPaths) + if sensorGroupId != "" && sensorPaths != "" { + // Forming key for TELEMETRY_CLIENT table + tclientKey := "Subscription_" + sensorGroupId + log.V(3).Info(" telemetry_client_sync_post_xfmr:tclientKey ", tclientKey) + + for key, _ := range retDbDataMap[SENSOR_PROFILE_TBL] { + if strings.Contains(key, sensorGroupId) { + + parts := strings.Split(key, "|") + subscriptionName = parts[0] + + processSensorGroup(retDbDataMap, sensorGroupId, sensorPaths) + log.V(3).Infof(" telemetry_client_sync_post_xfmr: sensor_paths:%v", retDbDataMap[TELEMETRY_CLIENT_TBL][tclientKey].Field["paths"]) + + sample_interval := retDbDataMap[SENSOR_PROFILE_TBL][key].Field["sample-interval"] + heartbeat_interval := retDbDataMap[SENSOR_PROFILE_TBL][key].Field["heartbeat-interval"] + log.V(3).Infof(" telemetry_client_sync_post_xfmr: sample_interval:%v, heartbeat_interval:%v", sample_interval, heartbeat_interval) + + // Populating TELEMETRY_CLIENT table with subscription data + err := processSubscriptions(retDbDataMap, sensorGroupId, subscriptionName, sample_interval, heartbeat_interval) + if err != nil { + log.Errorf("Error returned from processSubscriptions :%v", err) + return retDbDataMap, err + } + + } + + } + } + } + + } + + if strings.Contains(inParams.requestUri, "destination-groups") { + for key, _ := range retDbDataMap[DESTINATION_TBL] { + + parts := strings.Split(key, "|") + destinationGroupId = parts[0] + destinationGroupAddress := parts[1] + destinationGroupPort := parts[2] + + log.V(3).Infof(" telemetry_client_sync_post_xfmr:destinationKeys:%v,%v,%v ", destinationGroupId, destinationGroupAddress, destinationGroupPort) + + // Populating TELEMETRY_CLIENT table with destinations + processDestinationGroup(retDbDataMap, destinationGroupId, destinationGroupAddress, destinationGroupPort) + + } + + } + log.V(3).Infof(" telemetry_client_sync_post_xfmr:retDbDataMap:%v", retDbDataMap) + + return retDbDataMap, nil + +} diff --git a/translib/transformer/xfmr_wavelength_router.go b/translib/transformer/xfmr_wavelength_router.go new file mode 100644 index 000000000..eccb1cfbe --- /dev/null +++ b/translib/transformer/xfmr_wavelength_router.go @@ -0,0 +1,412 @@ +package transformer + +import ( + "encoding/json" + "fmt" + db "github.com/Azure/sonic-mgmt-common/translib/db" + "github.com/Azure/sonic-mgmt-common/translib/ocbinds" + log "github.com/golang/glog" + "github.com/openconfig/ygot/ygot" + "reflect" + "strconv" + "strings" +) + +func init() { + + /* Key transformer for MEDIA_CHANNEL table*/ + XlateFuncBind("YangToDb_media_channel_key_xfmr", YangToDb_media_channel_key_xfmr) + XlateFuncBind("DbToYang_media_channel_key_xfmr", DbToYang_media_channel_key_xfmr) + + /*Field transformer for MEDIA_CHANNEL table*/ + XlateFuncBind("YangToDb_media_channel_field_xfmr", YangToDb_media_channel_field_xfmr) + XlateFuncBind("DbToYang_media_channel_field_xfmr", DbToYang_media_channel_field_xfmr) + + /* Key transformer for MEDIA_CHANNEL_DISTRIBUTION table*/ + XlateFuncBind("YangToDb_media_channel_distribution_key_xfmr", YangToDb_media_channel_distribution_key_xfmr) + XlateFuncBind("DbToYang_media_channel_distribution_key_xfmr", DbToYang_media_channel_distribution_key_xfmr) + + /* Field transformer for MEDIA_CHANNEL_DISTRIBUTION table*/ + XlateFuncBind("YangToDb_media_channel_lf_field_xfmr", YangToDb_media_channel_lf_field_xfmr) + XlateFuncBind("DbToYang_media_channel_lf_field_xfmr", DbToYang_media_channel_lf_field_xfmr) + XlateFuncBind("YangToDb_media_channel_uf_field_xfmr", YangToDb_media_channel_uf_field_xfmr) + XlateFuncBind("DbToYang_media_channel_uf_field_xfmr", DbToYang_media_channel_uf_field_xfmr) + + // Override the existing function with the new implementation + // Uncomment the below line to override the existing GetNamespaceFunc + // media_channel_get_namespace_xfmr = customMcGetNamespaceFunc + + /* Get Namespace transformer for MEDIA_CHANNEL table*/ + XlateFuncBind("media_channel_get_namespace_xfmr", media_channel_get_namespace_xfmr) + XlateFuncBind("media_channel_post_xfmr", media_channel_post_xfmr) + +} + +var YangToDb_media_channel_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_media_channel_key_xfmr : root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + key := pathInfo.Var("index") + log.V(3).Infof("YangToDb_media_channel_key_xfmr : key:", key) + + return key, nil +} + +var DbToYang_media_channel_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}, 1) + log.V(3).Info("DbToYang_media_channel_key_xfmr : ", inParams.key) + TableKeys := strings.Split(inParams.key, "|") + + keyUint, err := strconv.ParseUint(TableKeys[0], 10, 32) + if err != nil { + log.Errorf("Error in parsing key %s: %v", TableKeys[0], err) + return rmap, err + } + rmap["index"] = uint32(keyUint) + log.V(3).Info("DbToYang_media_channel_key_xfmr : resp_map", rmap) + + return rmap, nil +} + +var YangToDb_media_channel_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_media_channel_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + log.V(3).Info("DbToYang_media_channel_field_xfmr : ", inParams.key) + + keyUint, err := strconv.ParseUint(inParams.key, 10, 32) + if err != nil { + log.Errorf("Error in parsing key %s: %v", inParams.key, err) + return rmap, err + } + rmap["index"] = uint32(keyUint) + + return rmap, nil +} + +var YangToDb_media_channel_distribution_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + + log.V(3).Infof("YangToDb_media_channel_distribution_key_xfmr : root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + idx := pathInfo.Var("index") + lower := pathInfo.Var("lower-frequency") + upper := pathInfo.Var("upper-frequency") + key := idx + "|" + lower + "|" + upper + log.V(3).Infof("YangToDb_media_channel_distribution_key_xfmr : key:", key) + + return key, nil +} + +var DbToYang_media_channel_distribution_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + log.V(3).Info("DbToYang_media_channel_distribution_key_xfmr : ", inParams.key) + key := inParams.key + + TableKeys := strings.Split(key, "|") + if len(TableKeys) >= 3 { + rmap["lower-frequency"] = TableKeys[1] + rmap["upper-frequency"] = TableKeys[2] + } + log.V(3).Info("DbToYang_media_channel_distribution_key_xfmr : ", rmap) + + return rmap, nil +} + +var YangToDb_media_channel_lf_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_media_channel_lf_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + log.V(3).Infof("YangToDb_media_channel_lf_field_xfmr : root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + key := inParams.key + + TableKeys := strings.Split(key, "|") + if len(TableKeys) >= 3 { + rmap["lower-frequency"] = TableKeys[1] + } + + return rmap, nil +} + +var YangToDb_media_channel_uf_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + + rmap := make(map[string]string) + rmap["NULL"] = "NULL" + + return rmap, nil +} + +var DbToYang_media_channel_uf_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + + rmap := make(map[string]interface{}) + log.V(3).Infof("YangToDb_media_channel_uf_field_xfmr : root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + key := inParams.key + + TableKeys := strings.Split(key, "|") + if len(TableKeys) >= 3 { + rmap["upper-frequency"] = TableKeys[2] + } + + return rmap, nil +} + + +func getMediaChannelObj(s *ygot.GoStruct) *ocbinds.OpenconfigWavelengthRouter_WavelengthRouter { + deviceObj := (*s).(*ocbinds.Device) + return deviceObj.WavelengthRouter +} + +var media_channel_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]NamespacePayload, error) { + + // Struct to hold payload and associated key + type payloadWithKey struct { + payload map[string]interface{} + key string + } + + + // Updated map to hold list of payload+key per namespace + var nsPayloadMap = make(map[string][]payloadWithKey) + + log.Infof("media_channel_get_namespace_xfmr: inParams: %v", inParams) + + pathInfo := NewPathInfo(inParams.uri) + + keyStr := pathInfo.Var("index") + + log.Infof("media_channel_get_namespace_xfmr: key: %v", keyStr) + + if len(keyStr) > 0 { + + keyUint64, err := strconv.ParseUint(keyStr, 10, 32) + if err != nil { + log.Errorf("Invalid key format: %v", keyStr) + return nil, fmt.Errorf("Invalid key format: %v", keyStr) + } + key := uint32(keyUint64) + + dbName := db.GetMDBNameFromEntity(key) + log.Infof("media_channel_get_namespace_xfmr: dbName: %v", dbName) + + var raw map[string]interface{} + var payloads []map[string]interface{} + + if inParams.body != nil && len(inParams.body) > 0 { + if err := json.Unmarshal(inParams.body, &raw); err != nil { + log.Warning("Failed during unmarshal the userPayload: %v", err) + return nil, err + } + payloads = append(payloads, raw) + log.Infof("appending raw to the payloads %v", payloads) + + } else { + payloads = []map[string]interface{}{} //delete purpose instead of nil used empty payload for consistency + } + log.Infof("based on the key return %v=dbName %v=key", dbName, key) + return []NamespacePayload{ + { + Namespace: dbName, + Payloads: payloads, + + Key: fmt.Sprintf("%d", key), + }, + }, nil + } + + var containerPrefix string + if inParams.body != nil { + bodyStr := string(inParams.body) + idx := strings.Index(bodyStr, "[") + if idx != -1 { + containerPrefix = bodyStr[:idx] + containerPrefix = strings.TrimRight(containerPrefix, ": \t\r\n") + } + } + + if inParams.ygRoot != nil { + mediaChannel := getMediaChannelObj(inParams.ygRoot) + + printPayloads := func(entities interface{}) { + val := reflect.ValueOf(entities) + if val.Kind() != reflect.Map { + log.Info("entities is not a map") + return + } + + for _, key := range val.MapKeys() { + entity := val.MapIndex(key).Interface() + dbName := db.GetMDBNameFromEntity(key.Interface()) + + ygotStruct, ok := entity.(ygot.ValidatedGoStruct) + if !ok { + log.Errorf("Entity does not implement ygot.ValidatedGoStruct") + continue + } + + entityJson, err := ygot.EmitJSON(ygotStruct, &ygot.EmitJSONConfig{ + Format: ygot.RFC7951, + Indent: "", + SkipValidation: true, + }) + if err != nil { + log.Errorf("Failed to marshal entity with ygot.EmitJSON: %v", err) + continue + } + openBraces := strings.Count(containerPrefix, "{") + finalJson := fmt.Sprintf("%s:[%s]%s", containerPrefix, string(entityJson), strings.Repeat("}", openBraces)) + log.Errorf("reconstructed payload: %v", finalJson) + + var finalMap map[string]interface{} + if err := json.Unmarshal([]byte(finalJson), &finalMap); err != nil { + log.Errorf("Failed to unmarshal reconstructed payload: %v", err) + continue + } + + nsPayloadMap[dbName] = append(nsPayloadMap[dbName], payloadWithKey{ + payload: finalMap, + key: key.String(), + }) //"asic0" : payloadWithKey{payload, key} + + if outStr, err := json.MarshalIndent(finalMap, "", " "); err == nil { + log.Infof("Namespace: %s\nWrapped Output:\n%s", dbName, string(outStr)) + } + } + } + + if mediaChannel.MediaChannels.Channel != nil { + printPayloads(mediaChannel.MediaChannels.Channel) + } + } + // If no payloads found, use wildcard namespace + if len(nsPayloadMap) == 0 { + log.Infof("No specific key found, using '*' to include all DBs.") + return []NamespacePayload{ + { + Namespace: "*", + Payloads: []map[string]interface{}{}, + Key: "*", + }, + }, nil + } + + // Construct final result + var result []NamespacePayload + for ns, pwkList := range nsPayloadMap { + for _, pwk := range pwkList { + result = append(result, NamespacePayload{ + Namespace: ns, //asic0 + Payloads: []map[string]interface{}{pwk.payload}, //payload from payloadWithKey struct + Key: pwk.key, // key from payloadWithkey struct + Commited: false, // commited flag as a false + }) + } + } + + return result, nil +} + + + +var media_channel_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[string]map[string]db.Value, error) { + + retDbDataMap := (*inParams.dbDataMap)[inParams.curDb] + pathInfo := NewPathInfo(inParams.uri) + index := pathInfo.Var("index") + lowerFrequency := pathInfo.Var("lower-frequency") + upperFrequency := pathInfo.Var("upper-frequency") + + if inParams.dbDataMap == nil || *inParams.dbDataMap == nil { + return nil, fmt.Errorf("dbDataMap is nil") + } + if retDbDataMap == nil { + retDbDataMap = make(map[string]map[string]db.Value) + (*inParams.dbDataMap)[inParams.curDb] = retDbDataMap + } + + if inParams.oper == DELETE { + + if retDbDataMap["MEDIA_CHANNEL_DISTRIBUTION"] == nil { + retDbDataMap["MEDIA_CHANNEL_DISTRIBUTION"] = make(map[string]db.Value) + } + + if lowerFrequency == "" && upperFrequency == "" && index != "" { + mediaChannelTs := &db.TableSpec{Name: "MEDIA_CHANNEL_DISTRIBUTION"} + mediaChannelKeys, err := inParams.d.GetKeys(mediaChannelTs) + log.Infof("media_channel_get_namespace_xfmr: ", mediaChannelKeys) + if err != nil { + log.Errorf("Error retrieving keys from MEDIA_CHANNEL table: %v", err) + return retDbDataMap, err + } + mediaChannelDistributionKeys := []string{} + + for key := range mediaChannelKeys { + log.Infof("media_channel_get_namespace_xfmr: ", index, mediaChannelKeys[key].Get(0), mediaChannelKeys[key]) + if index == mediaChannelKeys[key].Get(0) { + mediaChannelDistribution := "" + for idx, mediaKeyValue := range mediaChannelKeys[key].Comp { + if idx == len(mediaChannelKeys[key].Comp)-1 { + mediaChannelDistribution += mediaKeyValue + } else { + mediaChannelDistribution += mediaKeyValue + "|" + } + } + mediaChannelDistributionKeys = append(mediaChannelDistributionKeys, mediaChannelDistribution) + } + } + log.Info("media_channel_get_namespace_xfmr: ", mediaChannelDistributionKeys) + + tableTs := &db.TableSpec{Name: "MEDIA_CHANNEL_DISTRIBUTION"} + _ = tableTs + for _, DistrubutionKey := range mediaChannelDistributionKeys { + + // Mark specific key for deletion in the return DB map + retDbDataMap["MEDIA_CHANNEL_DISTRIBUTION"][DistrubutionKey] = db.Value{} + } + + log.Infof("media_channel_post_xfmr: marked delete for index=%s in MEDIA_CHANNEL_DISTRIBUTION", index) + + } else { + log.Info("media_channel_post_xfmr:Deleting all entries in MEDIA_CHANNEL_DISTRIBUTION table") + + tableTs := &db.TableSpec{Name: "MEDIA_CHANNEL_DISTRIBUTION"} + _ = tableTs + // Reset per-table map to indicate delete-all + retDbDataMap["MEDIA_CHANNEL_DISTRIBUTION"] = make(map[string]db.Value) + } + } + + log.Infof("media_channel_post_xfmr:retDbDataMap:%v", retDbDataMap) + return retDbDataMap, nil +} + +// Define a new implementation for GetNamespaceFunc +func customMcGetNamespaceFunc(inParams XfmrParams) ([]NamespacePayload, error) { + + // Your custom implementation here + nameSpaceList, err := media_channel_get_namespace_xfmr(inParams) + + return nameSpaceList, err +} + + diff --git a/translib/transformer/xfmr_wavelength_router_test.go b/translib/transformer/xfmr_wavelength_router_test.go new file mode 100644 index 000000000..ad343a63c --- /dev/null +++ b/translib/transformer/xfmr_wavelength_router_test.go @@ -0,0 +1,316 @@ +//go:build xfmrtest +// +build xfmrtest + +package transformer_test + +import ( + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "testing" + "time" +) + +/* MEDIA_CHANNEL config, state DB fields and values */ +func Test_media_channel_config_state_DB_key(t *testing.T) { + var pre_req_map, cleanuptbl, cleanupstatetbl map[string]interface{} + var expected_get_json, url []string + + for idx, dbName := range getMdbNames() { + /* MEDIA_CHANNEL Config DB test */ + t.Log("\n\n+++++++++++++ Performing Get on configDB Media_channel Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "MEDIA_CHANNEL": map[string]interface{}{ + fmt.Sprintf("%d10", idx+1): map[string]interface{}{ + "index": fmt.Sprintf("%d10", idx+1), + "name": "Channel", + "lower-frequency": 193775000, + "upper-frequency": 193775000, + "admin-status": "ENABLED", + "super-channel": "true", + "super-channel-parent": 1, + "attenuation-control-mode": "ATTENUATION_FIXED_LOSS", + "source-port-name": "PORT-1-1-WSS1", + "dest-port-name": "PORT-1-1-WSS2", + "ase-control-mode": "ASE_ENABLED", + "ase-injection-threshold": 10.0, + }, + }, + "MEDIA_CHANNEL_DISTRIBUTION": map[string]interface{}{ + fmt.Sprintf("%d10|193775000|193775000", idx+1): map[string]interface{}{ + "lower-frequency": 193775000, + "upper-frequency": 193775000, + "target-power": -5.0, + }, + }, + } + + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_get_json = []string{ + fmt.Sprintf("{\"openconfig-wavelength-router:config\":{\"admin-status\":\"ENABLED\",\"ase-control-mode\":\"openconfig-wavelength-router:ASE_ENABLED\",\"ase-injection-threshold\":\"10\",\"attenuation-control-mode\":\"openconfig-wavelength-router:ATTENUATION_FIXED_LOSS\",\"index\":%d10,\"lower-frequency\":\"193775000\",\"name\":\"Channel\",\"super-channel\":true,\"super-channel-parent\":1,\"upper-frequency\":\"193775000\"}}", idx+1), + "{\"openconfig-wavelength-router:config\":{\"lower-frequency\":\"193775000\",\"target-power\":\"-5\",\"upper-frequency\":\"193775000\"}}", + } + + url = []string{ + fmt.Sprintf("/openconfig-wavelength-router:wavelength-router/media-channels/channel[index=%d10]/config", idx+1), + fmt.Sprintf("/openconfig-wavelength-router:wavelength-router/media-channels/channel[index=%d10]/spectrum-power-profile/distribution[lower-frequency=193775000][upper-frequency=193775000]/config", idx+1), + } + for idx, url := range url { + t.Run("Test get on config DB Key for "+url, processGetRequest(url, nil, expected_get_json[idx], false)) + time.Sleep(1 * time.Second) + } + t.Log("\n\n+++++++++++++ Done Performing Get on configDB Media_channel Key ++++++++++++") + + /* MEDIA_CHANNEL State DB test */ + t.Log("\n\n+++++++++++++ Performing Get on stateDB Media_channel Key ++++++++++++") + pre_req_map = map[string]interface{}{ + "MEDIA_CHANNEL_TABLE": map[string]interface{}{ + fmt.Sprintf("%d10", idx+1): map[string]interface{}{ + "index": fmt.Sprintf("%d10", idx+1), + "name": "WavelengthRouter1", + "lower-frequency": 193775000, + "upper-frequency": 193775000, + "admin-status": "ENABLED", + "super-channel": "false", + "super-channel-parent": 0, + "ase-control-mode": "ASE_ENABLED", + "ase-injection-mode": "MODE_THRESHOLD", + "ase-injection-threshold": 10.0, + "ase-injection-delta": 2.0, + "attenuation-control-mode": "ATTENUATION_FIXED_LOSS", + "source-port-name": "PORT-1-1-WSS1", + "dest-port-name": "PORT-1-1-WSS2", + "oper-status": "UP", + "ase-status": "PRESENT", + }, + }, + "MEDIA_CHANNEL_DISTRIBUTION_TABLE": map[string]interface{}{ + fmt.Sprintf("%d10|193775000|193775000", idx+1): map[string]interface{}{ + "lower-frequency": 193775000, + "upper-frequency": 193775000, + "target-power": -5.0, + }, + }, + } + + loadDB(dbName, db.StateDB, pre_req_map) + expected_get_json = []string{ + fmt.Sprintf("{\"openconfig-wavelength-router:state\":{\"admin-status\":\"ENABLED\",\"ase-control-mode\":\"openconfig-wavelength-router:ASE_ENABLED\",\"ase-injection-delta\":\"2\",\"ase-injection-mode\":\"MODE_THRESHOLD\",\"ase-injection-threshold\":\"10\",\"ase-status\":\"PRESENT\",\"attenuation-control-mode\":\"openconfig-wavelength-router:ATTENUATION_FIXED_LOSS\",\"index\":%d10,\"lower-frequency\":\"193775000\",\"name\":\"WavelengthRouter1\",\"oper-status\":\"UP\",\"super-channel\":false,\"super-channel-parent\":0,\"upper-frequency\":\"193775000\"}}", idx+1), + "{\"openconfig-wavelength-router:state\":{\"lower-frequency\":\"193775000\",\"target-power\":\"-5\",\"upper-frequency\":\"193775000\"}}", + } + url = []string{ + fmt.Sprintf("/openconfig-wavelength-router:wavelength-router/media-channels/channel[index=%d10]/state", idx+1), + fmt.Sprintf("/openconfig-wavelength-router:wavelength-router/media-channels/channel[index=%d10]/spectrum-power-profile/distribution[lower-frequency=193775000][upper-frequency=193775000]/state", idx+1), + } + for idx, url := range url { + t.Run("Test get on state DB Key for "+url, processGetRequest(url, nil, expected_get_json[idx], false)) + time.Sleep(1 * time.Second) + } + t.Log("\n\n+++++++++++++ Done Get on stateDB Media_channel Key ++++++++++++") + + //Unload the Data + cleanuptbl = map[string]interface{}{ + "MEDIA_CHANNEL": map[string]interface{}{ + fmt.Sprintf("%d10", idx+1): "", + }, + "MEDIA_CHANNEL_DISTRIBUTION": map[string]interface{}{ + fmt.Sprintf("%d10|193775000|193775000", idx+1): "", + }, + } + unloadDB(dbName, db.ConfigDB, cleanuptbl) + + cleanupstatetbl = map[string]interface{}{ + "MEDIA_CHANNEL_TABLE": map[string]interface{}{ + fmt.Sprintf("%d10", idx+1): "", + }, + "MEDIA_CHANNEL_DISTRIBUTION_TABLE": map[string]interface{}{ + fmt.Sprintf("%d10|193775000|193775000", idx+1): "", + }, + } + unloadDB(dbName, db.StateDB, cleanupstatetbl) + } +} + +func Test_set_media_channel_config_DB_key_and_field_xfmr(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing Create/Replace/Delete on Media_channel ++++++++++++") + + for idx, dbName := range getMdbNames() { + url := fmt.Sprintf("/openconfig-wavelength-router:wavelength-router/media-channels/channel[index=%d10]/config", idx+1) + url_body_json := "{\"config\":{\"admin-status\":\"ENABLED\",\"ase-control-mode\":\"openconfig-wavelength-router:ASE_ENABLED\",\"ase-injection-threshold\":\"20\",\"attenuation-control-mode\":\"openconfig-wavelength-router:ATTENUATION_FIXED_LOSS\",\"lower-frequency\":\"193775000\",\"name\":\"Media_Channel\",\"super-channel\":false,\"super-channel-parent\":150,\"upper-frequency\":\"193775000\"}}" + + pre_req_map := map[string]interface{}{ + "MEDIA_CHANNEL": map[string]interface{}{ + fmt.Sprintf("%d10", idx+1): map[string]interface{}{ + "name": "Channel", + "lower-frequency": 193775000, + "upper-frequency": 193775000, + "admin-status": "ENABLED", + "super-channel": "true", + "super-channel-parent": 1, + "attenuation-control-mode": "ATTENUATION_FIXED_LOSS", + "ase-control-mode": "ASE_ENABLED", + "ase-injection-threshold": 10.0, + }, + }, + } + loadDB(dbName, db.ConfigDB, pre_req_map) + expected_map := map[string]interface{}{ + "MEDIA_CHANNEL": map[string]interface{}{ + fmt.Sprintf("%d10", idx+1): map[string]interface{}{ + "name": "Media_Channel", + "lower-frequency": 193775000, + "upper-frequency": 193775000, + "admin-status": "ENABLED", + "super-channel": "false", + "super-channel-parent": 150, + "attenuation-control-mode": "ATTENUATION_FIXED_LOSS", + "ase-control-mode": "ASE_ENABLED", + "ase-injection-threshold": 20.0, + }, + }, + } + + time.Sleep(1 * time.Second) + + //PUT Test + t.Run("Replace Test on MEDIA_CHANNEL yang", processSetRequest(url, url_body_json, "PUT", false)) + time.Sleep(1 * time.Second) + + //GET Test + t.Run("Verify replace on MEDIA_CHANNEL yang", verifyDbResult(rclient[dbName], fmt.Sprintf("MEDIA_CHANNEL|%d10", idx+1), expected_map, false)) + time.Sleep(1 * time.Second) + + //Delete Test + url = fmt.Sprintf("/openconfig-wavelength-router:wavelength-router/media-channels/channel[index=%d10]/config", idx+1) + t.Run("DELETE Test on MEDIA_CHANNEL yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + //POST Test + url = "/openconfig-wavelength-router:wavelength-router/media-channels" + post_payload := fmt.Sprintf("{\"channel\":[{\"index\":%d41,\"config\": {\"name\": \"NewChannel\",\"lower-frequency\": \"193775000\", \"upper-frequency\": \"193775000\", \"admin-status\": \"ENABLED\", \"super-channel\": false, \"super-channel-parent\": 130, \"attenuation-control-mode\": \"ATTENUATION_FIXED_LOSS\",\"ase-control-mode\":\"ASE_ENABLED\",\"ase-injection-threshold\":\"10.40\"}}]}", idx+1) + t.Run("Create test on MEDIA_CHANNEL yang", processSetRequest(url, post_payload, "POST", false)) + time.Sleep(1 * time.Second) + + expected_map = map[string]interface{}{ + "MEDIA_CHANNEL": map[string]interface{}{ + fmt.Sprintf("%d41", idx+1): map[string]interface{}{ + "name": "NewChannel", + "lower-frequency": 193775000, + "upper-frequency": 193775000, + "admin-status": "ENABLED", + "super-channel": "false", + "super-channel-parent": 130, + "attenuation-control-mode": "ATTENUATION_FIXED_LOSS", + "ase-control-mode": "ASE_ENABLED", + "ase-injection-threshold": 10.40, + }, + }, + } + + //Verify After the POST test + t.Run("Verify After the POST test on MEDIA_CHANNEL yang", verifyDbResult(rclient[dbName], fmt.Sprintf("MEDIA_CHANNEL|%d41", idx+1), expected_map, false)) + + //Delete After the POST test + url = fmt.Sprintf("/openconfig-wavelength-router:wavelength-router/media-channels/channel[index=%d41]/config", idx+1) + t.Run("DELETE After the POST test on MEDIA_CHANNEL yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = "/openconfig-wavelength-router:wavelength-router/media-channels" + + //Bulk POST Test + Bulk_post_payload := fmt.Sprintf("{\"channel\":[{\"index\":%d51,\"config\": {\"name\": \"NewChannel\",\"lower-frequency\": \"193775000\", \"upper-frequency\": \"193775000\", \"admin-status\": \"ENABLED\", \"super-channel\": true, \"super-channel-parent\": 150, \"attenuation-control-mode\": \"ATTENUATION_FIXED_LOSS\",\"ase-control-mode\":\"ASE_ENABLED\",\"ase-injection-threshold\":\"15.40\"}},{\"index\":%d61,\"config\": {\"name\": \"NewChannel\",\"lower-frequency\": \"193775000\", \"upper-frequency\": \"193775000\", \"admin-status\": \"ENABLED\", \"super-channel\": false, \"super-channel-parent\": 160, \"attenuation-control-mode\": \"ATTENUATION_FIXED_LOSS\",\"ase-control-mode\":\"ASE_ENABLED\",\"ase-injection-threshold\":\"16.40\"}}]}", idx+1, idx+1) + t.Run("Create test on MEDIA_CHANNEL yang", processSetRequest(url, Bulk_post_payload, "POST", false)) + + expected_map = map[string]interface{}{ + "MEDIA_CHANNEL": map[string]interface{}{ + fmt.Sprintf("%d51", idx+1): map[string]interface{}{ + "name": "NewChannel", + "lower-frequency": 193775000, + "upper-frequency": 193775000, + "admin-status": "ENABLED", + "super-channel": "true", + "super-channel-parent": 150, + "attenuation-control-mode": "ATTENUATION_FIXED_LOSS", + "ase-control-mode": "ASE_ENABLED", + "ase-injection-threshold": 15.40, + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the Bulk test + t.Run("Verify After the Bulk test on MEDIA_CHANNEL yang", verifyDbResult(rclient[dbName], fmt.Sprintf("MEDIA_CHANNEL|%d51", idx+1), expected_map, false)) + + expected_map = map[string]interface{}{ + "MEDIA_CHANNEL": map[string]interface{}{ + fmt.Sprintf("%d61", idx+1): map[string]interface{}{ + "name": "NewChannel", + "lower-frequency": 193775000, + "upper-frequency": 193775000, + "admin-status": "ENABLED", + "super-channel": "false", + "super-channel-parent": 160, + "attenuation-control-mode": "ATTENUATION_FIXED_LOSS", + "ase-control-mode": "ASE_ENABLED", + "ase-injection-threshold": 16.40, + }, + }, + } + + time.Sleep(1 * time.Second) + //Verify After the POST test + t.Run("Verify After the Bulk test on MEDIA_CHANNEL yang", verifyDbResult(rclient[dbName], fmt.Sprintf("MEDIA_CHANNEL|%d61", idx+1), expected_map, false)) + + //Delete keys After the Bulk Test + url = fmt.Sprintf("/openconfig-wavelength-router:wavelength-router/media-channels/channel[index=%d51]/config", idx+1) + t.Run("DELETE After the Bulk Test on MEDIA_CHANNEL yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + + url = fmt.Sprintf("/openconfig-wavelength-router:wavelength-router/media-channels/channel[index=%d61]/config", idx+1) + t.Run("DELETE After the Bulk Test on MEDIA_CHANNEL yang", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + } + t.Log("\n\n+++++++++++++ Done Performing Create/Replace/Delete on Media_channel ++++++++++++") +} + +func Test_media_allow_write_multiple_namespace(t *testing.T) { + t.Log("\n\n+++++++++++++ Performing Media_channel write for multiple namespace (should be allowed) ++++++++++++") + + url := "/openconfig-wavelength-router:wavelength-router/media-channels" + url_body_json := `{ + "channel": [ + { + "index": 121, + "config": { + "name": "NewChannel", + "lower-frequency": "193775000", + "upper-frequency": "193775000", + "admin-status": "ENABLED", + "super-channel": true, + "super-channel-parent": 150, + "attenuation-control-mode": "ATTENUATION_FIXED_LOSS", + "ase-control-mode": "ASE_ENABLED", + "ase-injection-threshold": "15.40" + } + }, + { + "index": 210, + "config": { + "name": "NewChannel", + "lower-frequency": "193775000", + "upper-frequency": "193775000", + "admin-status": "ENABLED", + "super-channel": false, + "super-channel-parent": 160, + "attenuation-control-mode": "ATTENUATION_FIXED_LOSS", + "ase-control-mode": "ASE_ENABLED", + "ase-injection-threshold": "16.40" + } + } + ] + }` + + // false = no error expected + t.Run("Test allow writing multiple namespace for MEDIA_CHANNEL", processSetRequest(url, url_body_json, "POST", false, nil)) + + t.Log("\n\n+++++++++++++ Done Performing Media_channel write for multiple namespace ++++++++++++") +} From b0684dee85dd84988d98488700b5cddf3d3cb65a Mon Sep 17 00:00:00 2001 From: SONIC-ADMIN Date: Tue, 30 Dec 2025 13:06:06 +0530 Subject: [PATCH 4/9] Missed out files --- translib/Makefile | 2 +- translib/acl_app.go | 23 + translib/api_tests_app.go | 21 + translib/app_interface.go | 15 +- translib/app_utils_test.go | 39 +- translib/common_app.go | 388 ++++- translib/db/cvl_db_access.go | 11 +- translib/db/db.go | 112 +- translib/db/db_cache.go | 4 +- translib/db/db_config.go | 37 +- translib/db/db_cursor_test.go | 1 + translib/db/db_cvl_hint_test.go | 1 + translib/db/db_lock.go | 131 +- translib/db/db_lock_test.go | 354 ++--- translib/db/db_onchangecache_test.go | 7 +- translib/db/db_opts_to_test.go | 2 + translib/db/db_redis_opts.go | 12 +- translib/db/db_redis_opts_test.go | 72 +- translib/db/db_redis_pipe_test.go | 1 + translib/db/db_rpcdb_test.go | 2 +- translib/db/db_savepoint_test.go | 2 + translib/db/db_stats.go | 7 +- translib/db/db_subscribe_test.go | 7 +- translib/db/db_table_pattern_test.go | 1 + translib/db/db_test.go | 181 ++- translib/db/subscribe.go | 15 +- translib/lldp_app.go | 23 + translib/pfm_app.go | 86 +- translib/pfm_app_test.go | 7 +- translib/subscribe.go | 244 ++-- translib/subscribe_notify.go | 37 +- translib/subscribe_test.go | 68 +- translib/sys_app.go | 25 +- .../transformer/interfaces_openconfig_test.go | 14 +- translib/transformer/sflow_openconfig_test.go | 86 +- translib/transformer/subscribe_req_xlate.go | 2 +- translib/transformer/subscribe_resp_xlate.go | 47 +- .../test/openconfig-test-xfmr-annot.yang | 1 + .../test/sonic-test-xfmr-annot.yang | 47 +- translib/transformer/testxfmryang_test.go | 794 +++------- translib/transformer/transformer_test.go | 169 ++- translib/transformer/utils_test.go | 11 +- translib/transformer/xfmr_aps.go | 4 +- translib/transformer/xfmr_atten.go | 2 +- translib/transformer/xfmr_channel_monitor.go | 2 +- translib/transformer/xfmr_interface.go | 16 + .../transformer/xfmr_testxfmr_callbacks.go | 2 +- .../transformer/xfmr_wavelength_router.go | 14 +- translib/transformer/xlate.go | 70 + translib/transformer/xlate_from_db.go | 7 +- translib/transformer/xlate_to_db.go | 15 +- translib/transformer/xlate_utils.go | 8 +- translib/transformer/xlate_xfmr_handler.go | 33 + translib/transformer/xspec.go | 155 +- translib/translib.go | 1299 +++++++++++++---- translib/translib_test.go | 4 - translib/yanglib_app.go | 23 + translib/yanglib_app_test.go | 5 +- 58 files changed, 3303 insertions(+), 1465 deletions(-) diff --git a/translib/Makefile b/translib/Makefile index 7957c0c6c..11ddeb451 100644 --- a/translib/Makefile +++ b/translib/Makefile @@ -94,7 +94,7 @@ endif .SECONDEXPANSION: $(FORMAT_CHECK): $(SRCS) $(SRCX) $(TESTS) | $(YGOT_BINDS) $$(@D)/. - $(TOPDIR)/tools/test/format-check.sh \ + $(TOPDIR)/tools/test/format-check.sh -v \ --log=$(TRANSLIB_BLD)/formatcheck.log \ $? touch $@ diff --git a/translib/acl_app.go b/translib/acl_app.go index 40aa38f5b..bbce72ff5 100644 --- a/translib/acl_app.go +++ b/translib/acl_app.go @@ -1785,3 +1785,26 @@ func (app *AclApp) processSubscribe(req processSubRequest) (processSubResponse, return resp, nil } + +func (app *AclApp) getNamespace(path string) ([]NamespacePayload, error) { + + var nameSpaceList []NamespacePayload + + nameSpaceList = append(nameSpaceList, NamespacePayload{ + Namespace: "host", + Payloads: []map[string]interface{}{}, + Key: "", + }) + + log.Infof("AclApp:getNamespace: nameSpaceList:%v ", nameSpaceList) + + return nameSpaceList, nil +} + +func (app *AclApp) processPreparePhase(d *db.DB, ckey string) error { + return nil +} + +func (app *AclApp) rollback(d *db.DB) error { + return nil +} diff --git a/translib/api_tests_app.go b/translib/api_tests_app.go index c9003c4b5..5ce68e40f 100644 --- a/translib/api_tests_app.go +++ b/translib/api_tests_app.go @@ -193,3 +193,24 @@ func (app *apiTests) getError() error { return tlerr.New(app.echoMsg) } } + +func (app *apiTests) getNamespace(path string, payload []byte) ([]string, error) { + var res []string + + res = append(res, "host") + glog.Info("Apitestsapp:getNamespace response", res) + + return res, nil +} + +func (app *apiTests) processPreparePhase(d *db.DB, ckey string) error { + return nil +} + +func (app *apiTests) processPostPhase(d *db.DB, opcode int) error { + return nil +} + +func (app *apiTests) rollback(d *db.DB, opcode int, ckey string) error { + return nil +} diff --git a/translib/app_interface.go b/translib/app_interface.go index 4ddbd7d83..5c4047730 100644 --- a/translib/app_interface.go +++ b/translib/app_interface.go @@ -92,6 +92,13 @@ var appMap map[string]*appInfo // array containing all the supported models var models []ModelData +type NamespacePayload struct { + Namespace string + Payloads []map[string]interface{} + Key string + Commited bool +} + // Interface for all App Modules type appInterface interface { initialize(data appData) @@ -100,8 +107,11 @@ type appInterface interface { translateReplace(d *db.DB) ([]db.WatchKeys, error) translateDelete(d *db.DB) ([]db.WatchKeys, error) translateGet(dbs [db.MaxDB]*db.DB) error + getNamespace(path string) ([]NamespacePayload, error) translateAction(dbs [db.MaxDB]*db.DB) error translateSubscribe(req translateSubRequest) (translateSubResponse, error) + processPreparePhase(d *db.DB, ckey string) error + rollback(d *db.DB) error processCreate(d *db.DB) (SetResponse, error) processUpdate(d *db.DB) (SetResponse, error) processReplace(d *db.DB) (SetResponse, error) @@ -147,7 +157,10 @@ func getAppModuleInfo(path string) (*appInfo, error) { log.Info("getAppModule called for path =", path) for pattern, app := range appMap { - if !strings.HasPrefix(path, pattern) { + if pattern == "/openconfig-platform:components" && (strings.Contains(path, "/openconfig-transport-line-common:optical-port") || strings.Contains(path, "/openconfig-terminal-device:optical-channel") || strings.Contains(path, "FAN") || strings.Contains(path, "PSU") || strings.Contains(path, "CU") || strings.Contains(path, "CHASSIS") || strings.Contains(path, "LINECARD")) { + continue + + } else if !strings.HasPrefix(path, pattern) { continue } diff --git a/translib/app_utils_test.go b/translib/app_utils_test.go index e92ad2302..c46d37c5e 100644 --- a/translib/app_utils_test.go +++ b/translib/app_utils_test.go @@ -96,26 +96,28 @@ func verifyGet(t *testing.T, req GetRequest, expJson string, expError bool) { } var respJson []byte - if req.FmtType == TRANSLIB_FMT_YGOT && response.ValueTree != nil { - respJson, err = dumpIetfJson(response.ValueTree) - if err != nil { - t.Fatalf("GET %s returned invalid YGOT. error=%v", req.Path, err) + for _, resp := range response { + if req.FmtType == TRANSLIB_FMT_YGOT && resp.ValueTree != nil { + respJson, err = dumpIetfJson(resp.ValueTree) + if err != nil { + t.Fatalf("GET %s returned invalid YGOT. error=%v ", req.Path, err) + } + } else if req.FmtType == TRANSLIB_FMT_IETF_JSON { + respJson = resp.Payload } - } else if req.FmtType == TRANSLIB_FMT_IETF_JSON { - respJson = response.Payload - } - var jResponse, jExpected map[string]interface{} - if err := json.Unmarshal(respJson, &jResponse); err != nil { - t.Fatalf("invalid response json; err = %v\npayload = %s", err, respJson) - } - if err := json.Unmarshal([]byte(expJson), &jExpected); err != nil { - t.Fatalf("invalid expected json; err = %v", err) - } - if !reflect.DeepEqual(jResponse, jExpected) { - t.Errorf("GET %s returned invalid response", req.Path) - t.Errorf("Expected: %s", expJson) - t.Fatalf("Received: %s", respJson) + var jResponse, jExpected map[string]interface{} + if err := json.Unmarshal(respJson, &jResponse); err != nil { + t.Fatalf("invalid response json; err = %v\npayload = %s", err, respJson) + } + if err := json.Unmarshal([]byte(expJson), &jExpected); err != nil { + t.Fatalf("invalid expected json; err = %v", err) + } + if !reflect.DeepEqual(jResponse, jExpected) { + t.Errorf("GET %s returned invalid response", req.Path) + t.Errorf("Expected: %s", expJson) + t.Fatalf("Received: %s", respJson) + } } } @@ -152,6 +154,7 @@ func processDeleteRequest(url string) func(*testing.T) { func getConfigDb() *db.DB { configDb, _ := db.NewDB(db.Options{ DBNo: db.ConfigDB, + MDBName: "host", TableNameSeparator: "|", KeySeparator: "|", }) diff --git a/translib/common_app.go b/translib/common_app.go index 289830fdb..c7f28aeb1 100644 --- a/translib/common_app.go +++ b/translib/common_app.go @@ -19,8 +19,12 @@ package translib import ( + "encoding/json" "errors" "fmt" + "io/ioutil" + "os" + "path/filepath" "reflect" "sort" "strings" @@ -41,6 +45,18 @@ import ( var () +type BackupEntry struct { + Operation string `json:"operation"` + Value db.Value `json:"value,omitempty"` // omit if empty (e.g., CREATE no value) +} + +// BackupData maps table name -> key -> BackupEntry +type BackupData map[string]map[string]BackupEntry + +// BackupFile stores all namespaces backup data +// Namespace -> BackupData +type BackupFile map[string]BackupData + type CommonApp struct { pathInfo *PathInfo body []byte @@ -60,6 +76,8 @@ var cmnAppInfo = appInfo{appType: reflect.TypeOf(CommonApp{}), isNative: false, tablesToWatch: nil} +const BackupFilePath = "/tmp/common_app_backup.json" + func init() { register_model_path := []string{"/sonic-", "*"} // register YANG model path(s) to be supported via common app @@ -715,7 +733,14 @@ func (app *CommonApp) cmnAppCRUCommonDbOpn(d *db.DB, opcode int, dbMap map[strin for _, tblKey := range reverOrdDbKeyLst { tblRw := tblVal[tblKey] log.Info("Processing Table key ", tblKey) - existingEntry, _ := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if err != nil { + if !(strings.Contains(err.Error(), "Entry does not exist")) { + log.Errorf("Failed to get old entry for key %v: %v", tblKey, err) + continue + } + } + if existingEntry.IsPopulated() && len(tblRw.Field) == 1 && (opcode == CREATE || opcode == UPDATE) { /*If tbl/key in result map exists in Db and the resultmap has only NULL/NULL field then don't do Db oper */ if _, nullFieldOk := tblRw.Field["NULL"]; nullFieldOk { @@ -1634,3 +1659,364 @@ func markChildTablesToCleanFromTranslatedResult(d *db.DB, resultDbMap map[string childTblToCleanMap[tblNm] = true } } + +func opcodeToStr(opcode int) string { + switch opcode { + case GET: + return "GET" + case CREATE: + return "CREATE" + case REPLACE: + return "REPLACE" + case UPDATE: + return "UPDATE" + case DELETE: + return "DELETE" + default: + return "UNKNOWN" + } +} + +const ( + backupFileDir = "/var/tmp" + backupFilePrefix = "common_backup_" + backupFileExt = ".json" + MAX_BACKUP_FILE_SIZE = 5 * 1024 * 1024 // 5MB +) + +func getNamespaceBackupFilePath(namespace string) string { + return filepath.Join(backupFileDir, backupFilePrefix+namespace+backupFileExt) +} + +func loadBackupFile(namespace string) (BackupData, error) { + var backupData BackupData = make(BackupData) + filePath := getNamespaceBackupFilePath(namespace) + + data, err := ioutil.ReadFile(filePath) + if err != nil { + if os.IsNotExist(err) { + return backupData, nil + } + return nil, fmt.Errorf("failed to read backup file: %v", err) + } + + err = json.Unmarshal(data, &backupData) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal backup file: %v", err) + } + + return backupData, nil +} + +func writeBackupToFile(namespace string, backupData BackupData) error { + filePath := getNamespaceBackupFilePath(namespace) + + data, err := json.MarshalIndent(backupData, "", " ") + if err != nil { + return fmt.Errorf("failed to marshal backup data: %v", err) + } + + if len(data) > MAX_BACKUP_FILE_SIZE { + return fmt.Errorf("backup file size exceeds maximum allowed limit of %d bytes", MAX_BACKUP_FILE_SIZE) + } + + err = ioutil.WriteFile(filePath, data, 0644) + if err != nil { + return fmt.Errorf("failed to write backup file: %v", err) + } + + log.Infof("Backup successfully written to %s", filePath) + return nil +} + +// Backup function that stores current entries with operation and namespace to the shared backup file +func (app *CommonApp) cmnAppCRUDTakeBackup(d *db.DB, ckey string, opcode int, dbMap map[string]map[string]db.Value) error { + var err error + var xfmrTblLst []string + var resultTblLst []string + + d.Opts.DisableCVLCheck = true + + // Step 1: Sort tables by dependency + for tblNm := range dbMap { + xfmrTblLst = append(xfmrTblLst, tblNm) + } + + resultTblLst, err = utils.SortAsPerTblDeps(xfmrTblLst) + if err != nil { + return err + } + + namespace := d.Opts.MDBName + + backupContent, err := loadBackupFile(namespace) + if err != nil { + return err + } + + if backupContent == nil { + backupContent = make(BackupData) + } + + // Step 2: If ckey == "*", backup all keys in the DB + if ckey == "*" { + for _, tblNm := range resultTblLst { + cmnAppTs := &db.TableSpec{Name: tblNm} + tblVal := make(map[string]BackupEntry) + + tbl, err := d.GetTable(cmnAppTs) + if err != nil { + log.Infof("Failed to fetch table %s for backup: %v", tblNm, err) + continue + } + + keys, err := tbl.GetKeys() + if err != nil { + log.Infof("Failed to get keys for table %s: %v", tblNm, err) + continue + } + + for _, key := range keys { + if len(key.Comp) == 0 { + continue + } + keyStr := key.Comp[0] + val, err := tbl.GetEntry(key) + if err != nil { + log.Infof("Failed to get entry for key %v in table %s: %v", key, tblNm, err) + continue + } + if val.IsPopulated() { + tblVal[keyStr] = BackupEntry{ + Operation: opcodeToStr(opcode), + Value: val, + } + } + } + + backupContent[tblNm] = tblVal + } + + return writeBackupToFile(namespace, backupContent) + } + + // Step 3: Backup based on passed dbMap keys + for _, tblNm := range resultTblLst { + tblVal, ok := dbMap[tblNm] + if !ok || len(tblVal) == 0 { + continue + } + + cmnAppTs := &db.TableSpec{Name: tblNm} + ordDbKeyLst := transformer.SortSncTableDbKeys(tblNm, tblVal) + + sort.SliceStable(ordDbKeyLst, func(i, j int) bool { + return i > j + }) + + entryMap := make(map[string]BackupEntry) + + for _, tblKey := range ordDbKeyLst { + keyObj := db.Key{Comp: []string{tblKey}} + oldEntry, err := d.GetEntry(cmnAppTs, keyObj) + if err != nil { + if !(strings.Contains(err.Error(), "Entry does not exist")) { + log.Errorf("Failed to get old entry for key %v: %v", tblKey, err) + continue + } + } + + switch opcode { + case CREATE: + entryMap[tblKey] = BackupEntry{ + Operation: opcodeToStr(opcode), + } + case DELETE: + if oldEntry.IsPopulated() { + entryMap[tblKey] = BackupEntry{ + Operation: opcodeToStr(opcode), + Value: oldEntry, + } + } + case UPDATE, REPLACE, GET: + if oldEntry.IsPopulated() { + entryMap[tblKey] = BackupEntry{ + Operation: opcodeToStr(opcode), + Value: oldEntry, + } + } else { + entryMap[tblKey] = BackupEntry{ + Operation: "CREATE", + } + } + default: + log.Infof("Unhandled opcode %d for key %s", opcode, tblKey) + } + } + + // Merge into existing backupContent + if existingTblMap, found := backupContent[tblNm]; found { + for k, v := range entryMap { + existingTblMap[k] = v + } + } else { + backupContent[tblNm] = entryMap + } + } + + return writeBackupToFile(namespace, backupContent) +} + +// Restore function reads backup file and applies rollback for current namespace only +func (app *CommonApp) RestoreFromBackupFile(d *db.DB) error { + namespace := d.Opts.MDBName + + backupContent, err := loadBackupFile(namespace) + if err != nil { + return err + } + + if len(backupContent) == 0 { + return fmt.Errorf("no backup data found for namespace: %s", namespace) + } + + for tblName, entries := range backupContent { + cmnAppTs := &db.TableSpec{Name: tblName} + + for keyStr, backupEntry := range entries { + keyObj := db.Key{Comp: []string{keyStr}} + op := strings.ToUpper(backupEntry.Operation) + + switch op { + case "CREATE": + log.Infof("Restore rollback CREATE: deleting key %s from table %s", keyStr, tblName) + err = d.DeleteEntry(cmnAppTs, keyObj) + if err != nil { + log.Infof("Failed to delete key %s during restore: %v", keyStr, err) + return err + } + case "DELETE": + log.Infof("Restore rollback DELETE: recreating key %s in table %s", keyStr, tblName) + err = d.SetEntry(cmnAppTs, keyObj, backupEntry.Value) + if err != nil { + log.Infof("Failed to recreate key %s during restore: %v", keyStr, err) + return err + } + case "UPDATE", "REPLACE", "GET": + log.Infof("Restore rollback %s: restoring key %s in table %s", op, keyStr, tblName) + err = d.SetEntry(cmnAppTs, keyObj, backupEntry.Value) + if err != nil { + log.Infof("Failed to restore key %s during restore: %v", keyStr, err) + return err + } + default: + log.Infof("Unknown operation %s for key %s in table %s - skipping", op, keyStr, tblName) + } + } + } + + log.Infof("Restore from backup file completed successfully for namespace %s", namespace) + return nil +} + +func (app *CommonApp) processPreparePhase(d *db.DB, ckey string) error { + var err error + if len(app.cmnAppTableMap) == 0 { + return err + } + + log.Info("Proceeding to perform DB operation") + + // Handle delete first if any available + if originalDeleteMap, ok := app.cmnAppTableMap[DELETE][db.ConfigDB]; ok { + // Deep copy to avoid mutating the original map + backupDeleteMap := make(map[string]map[string]db.Value, len(originalDeleteMap)) + for tblName, tblEntries := range originalDeleteMap { + copiedTblEntries := make(map[string]db.Value, len(tblEntries)) + for key, val := range tblEntries { + copiedTblEntries[key] = val // db.Value is assumed to be a struct (copied by value) + } + backupDeleteMap[tblName] = copiedTblEntries + } + + err := app.cmnAppCRUDTakeBackup(d, ckey, DELETE, backupDeleteMap) + if err != nil { + log.Info("Process delete fail. cmnAppTakeBackup error:", err) + return err + } + } + + // Handle create operation next + if _, ok := app.cmnAppTableMap[CREATE][db.ConfigDB]; ok { + err = app.cmnAppCRUDTakeBackup(d, ckey, CREATE, app.cmnAppTableMap[CREATE][db.ConfigDB]) + if err != nil { + log.Info("Process create fail. cmnAppTakeBackup error:", err) + return err + } + } + // Handle update and replace operation next + if _, ok := app.cmnAppTableMap[UPDATE][db.ConfigDB]; ok { + err = app.cmnAppCRUDTakeBackup(d, ckey, UPDATE, app.cmnAppTableMap[UPDATE][db.ConfigDB]) + if err != nil { + log.Info("Process update fail. cmnAppTakeBackup error:", err) + return err + } + } + if _, ok := app.cmnAppTableMap[REPLACE][db.ConfigDB]; ok { + err = app.cmnAppCRUDTakeBackup(d, ckey, REPLACE, app.cmnAppTableMap[REPLACE][db.ConfigDB]) + if err != nil { + log.Info("Process replace fail. cmnAppTakeBackup error:", err) + return err + } + } + log.Info("Returning from processPreparePhase() - success") + return err +} + +func (app *CommonApp) getNamespace(path string) ([]NamespacePayload, error) { + + jsonString := string((*app).body) + log.Infof("common_app: body: %v", jsonString) + + transformerPayloads, err := transformer.GetNamespace(path, (*app).ygotRoot, (*app).body) + if err != nil { + log.Warning("common_app: transformer.GetNamespace() returned: ", err) + } + + log.Infof("common_app: Transformer NamespacePayload List: %v", transformerPayloads) + + var nsPayloads []NamespacePayload + + if len(transformerPayloads) == 0 { + nsPayloads = append(nsPayloads, NamespacePayload{ + Namespace: "host", + Payloads: []map[string]interface{}{}, + Key: "", + }) + } else { + for _, tp := range transformerPayloads { + nsPayloads = append(nsPayloads, NamespacePayload{ + Namespace: tp.Namespace, + Payloads: tp.Payloads, + Key: tp.Key, + Commited: tp.Commited, + }) + } + } + + return nsPayloads, nil +} + +func (app *CommonApp) rollback(d *db.DB) error { + log.Infof("Rollback action detected, starting restore from backup file for namespace %s", d.Opts.MDBName) + + // Restore all tables/keys for the namespace from backup file + err := app.RestoreFromBackupFile(d) + if err != nil { + log.Errorf("Restore from backup file failed: %v", err) + return err + } + + log.Infof("Rollback completed successfully for namespace %s", d.Opts.MDBName) + return nil +} diff --git a/translib/db/cvl_db_access.go b/translib/db/cvl_db_access.go index 0baf12878..b2c9777f4 100644 --- a/translib/db/cvl_db_access.go +++ b/translib/db/cvl_db_access.go @@ -164,7 +164,7 @@ func (c *cvlDBAccess) Lookup(s ctypes.Search) ctypes.JsonResult { return strResult{"", err} } - v, err := cvl.RunLua( + v, err := cvl.RunLua(c.Db.client, "filter_entries", s.Pattern, strings.Join(s.KeyNames, "|"), @@ -187,7 +187,7 @@ func (c *cvlDBAccess) Count(s ctypes.Search) ctypes.IntResult { return intResult{0, err} } // Advanced key search, with match criteria on has values - v, err := cvl.RunLua( + v, err := cvl.RunLua(c.Db.client, "count_entries", s.Pattern, strings.Join(s.KeyNames, "|"), @@ -507,6 +507,13 @@ func (p *dbAccessPipe) Exec() error { return err } +func (cvl *cvlDBAccess) GetMDBName() string { + if log.V(5) { + log.Infof("cvlDBAccess: GetMDBName: %s", cvl.Db.Opts.MDBName) + } + return cvl.Db.Opts.MDBName +} + func (p *dbAccessPipe) Close() { if log.V(5) { log.Infof("dbAccessPipe: Close: redis pipeliner: %v", p.rp) diff --git a/translib/db/db.go b/translib/db/db.go index 81b65bb5e..517b9d57a 100644 --- a/translib/db/db.go +++ b/translib/db/db.go @@ -102,7 +102,10 @@ Example: package db import ( + "encoding/json" "fmt" + "os" + "path/filepath" "strconv" // "reflect" @@ -117,16 +120,88 @@ import ( "github.com/golang/glog" ) -const ( +var ( DefaultRedisUNIXSocket string = "/var/run/redis/redis.sock" DefaultRedisLocalTCPEP string = "localhost:6379" DefaultRedisRemoteTCPEP string = "127.0.0.1:6379" DefaultRedisUNIXNetwork string = "unix" DefaultRedisTCPNetwork string = "tcp" + DefaultAsicConfFilePath = "/usr/share/sonic/platform/asic.conf" + DefaultGlobalDbFilePath = "/var/run/redis/sonic-db/database_global.json" + NumAsic = 1 + GlobalKeySeperator = "" ) +type DbGlobal struct { + Includes []DbInclude `json:"INCLUDES"` + Version string `json:"VERSION"` + KeySeperator string `json:"KEY_SEPERATOR"` +} + +type DbInclude struct { + Include string `json:"include"` + Namespace string `json:"namespace"` +} + func init() { - dbConfigInit() + initAllDbs() +} + +func initAllDbs() { + if os.Getenv("REDIS_LOCAL_TCP_EP") != "" { + DefaultRedisLocalTCPEP = os.Getenv("REDIS_LOCAL_TCP_EP") + } + + dbConfigPath := "/var/run/redis/sonic-db/database_config.json" + if path, ok := os.LookupEnv("DB_CONFIG_PATH"); ok { + dbConfigPath = path + } + + if path, ok := os.LookupEnv("ASIC_CONFIG_PATH"); ok { + DefaultAsicConfFilePath = path + } + + if path, ok := os.LookupEnv("DB_GLOBAL_CONFIG_PATH"); ok { + DefaultGlobalDbFilePath = path + } + + NumAsic = getNumAsic() + + if !isMultiAsic() { + dbConfigInit(dbConfigPath, "host") + } else { + globalDbInfo := loadGlobalDatabase(DefaultGlobalDbFilePath) + for namespace, path := range globalDbInfo { + dbConfigInit(path, namespace) + } + } +} + +func loadGlobalDatabase(globalDbFilePath string) map[string]string { + var globalDbCfg DbGlobal + + data, err := os.ReadFile(globalDbFilePath) + if err != nil { + assert(err) + } else { + err = json.Unmarshal([]byte(data), &globalDbCfg) + if err != nil { + assert(err) + } + } + + var dbConfigMap = make(map[string]string) + var pwd = filepath.Dir(globalDbFilePath) + "/" + for i := 0; i < len(globalDbCfg.Includes); i++ { + if i == 0 { + dbConfigMap["host"] = pwd + globalDbCfg.Includes[0].Include + } else { + include := globalDbCfg.Includes[i] + dbConfigMap[include.Namespace] = pwd + include.Include + } + } + GlobalKeySeperator = globalDbCfg.KeySeperator + return dbConfigMap } // DBNum type indicates the type of DB (Eg: ConfigDB, ApplDB, ...). @@ -152,17 +227,19 @@ func (dbNo DBNum) String() string { } // ID returns the redis db id for this DBNum -func (dbNo DBNum) ID() int { +func (dbNo DBNum) ID(MDBName string) int { name := getDBInstName(dbNo) if len(name) == 0 { panic("Invalid DBNum " + fmt.Sprintf("%d", dbNo)) } + name = name + "." + MDBName return getDbId(name) } // Options gives parameters for opening the redis client. type Options struct { DBNo DBNum + MDBName string InitIndicator string TableNameSeparator string //Overriden by the DB config file's separator. KeySeparator string //Overriden by the DB config file's separator. @@ -388,7 +465,7 @@ func GetdbNameToIndex(dbName string) DBNum { return dbIndex } -// NewDB is the factory method to create new DB's. +// NewDB for Multi Asic func NewDB(opt Options) (*DB, error) { var e error @@ -510,7 +587,7 @@ func NewDB(opt Options) (*DB, error) { if opt.DBNo == ConfigDB && !opt.IsSession && !opt.IsWriteDisabled && !opt.ConfigDBLazyLock { - if e = ConfigDBTryLock(noSessionToken); e != nil { + if e = ConfigDBTryLock(noSessionToken, opt.MDBName); e != nil { glog.Errorf("NewDB: ConfigDB possibly locked: %s", e) d.client.Close() goto NewDBExit @@ -536,7 +613,6 @@ NewDBExit: if glog.V(3) { glog.Info("NewDB: End: d: ", d, " e: ", e) } - return &d, e } @@ -551,7 +627,7 @@ func (d *DB) DeleteDB() error { // Release the ConfigDB Lock if we placed on in NewDB() if d.configDBLocked { - ConfigDBUnlock(noSessionToken) + ConfigDBUnlock(noSessionToken, d.Opts.MDBName) d.configDBLocked = false } @@ -1086,7 +1162,7 @@ func (d *DB) doWrite(ts *TableSpec, op _txOp, k Key, val interface{}) error { } if d.Opts.DBNo == ConfigDB && !d.Opts.IsSession && !d.configDBLocked { - if e = ConfigDBTryLock(noSessionToken); e != nil { + if e = ConfigDBTryLock(noSessionToken, d.Opts.MDBName); e != nil { glog.Errorf("doWrite: ConfigDB possibly locked: %s", e) goto doWriteExit } @@ -1270,10 +1346,8 @@ func (d *DB) setEntry(ts *TableSpec, key Key, value Value, isCreate bool) error var valueComplement Value = Value{Field: make(map[string]string, len(value.Field))} var valueCurrent Value - if glog.V(3) { - glog.Info("setEntry: Begin: ", d.Name(), ": ts: ", ts, " key: ", key, - " value: ", value, " isCreate: ", isCreate) - } + glog.Info("setEntry: Begin: ", d.Name(), ": ts: ", ts, " key: ", key, + " value: ", value, " isCreate: ", isCreate) if len(value.Field) == 0 { if ts.NoDelete { @@ -1302,9 +1376,7 @@ func (d *DB) setEntry(ts *TableSpec, key Key, value Value, isCreate bool) error } if !isCreate && e == nil { - if glog.V(3) { - glog.Info("setEntry: DoCVL for UPDATE") - } + glog.Info("setEntry: DoCVL for UPDATE") if len(valueComplement.Field) == 0 { e = d.doCVL(ts, []cmn.CVLOperation{cmn.OP_UPDATE}, key, []Value{value}) @@ -1313,9 +1385,7 @@ func (d *DB) setEntry(ts *TableSpec, key Key, value Value, isCreate bool) error key, []Value{value, valueComplement}) } } else { - if glog.V(3) { - glog.Info("setEntry: DoCVL for CREATE") - } + glog.Info("setEntry: DoCVL for CREATE") e = d.doCVL(ts, []cmn.CVLOperation{cmn.OP_CREATE}, key, []Value{value}) } @@ -1725,9 +1795,7 @@ SkipWatch: // CommitTx method is used by infra to commit a check-and-set Transaction. func (d *DB) commitTx() error { - if glog.V(3) { - glog.Info("CommitTx: Begin:") - } + glog.Infof("CommitTx: Begin::%v", d) var e error = nil var tsmap map[TableSpec]bool = make(map[TableSpec]bool, len(d.txCmds)) // UpperBound @@ -1768,10 +1836,12 @@ func (d *DB) commitTx() error { glog.Warning("CommitTx: Do: MULTI e: ", e.Error()) goto CommitTxExit } + glog.Infof("CommitTx:d.txCmds):%v ", d.txCmds) // For each cmd in txCmds // Invoke it for i := 0; i < len(d.txCmds); i++ { + glog.Infof("CommitTx:inside for loop :%v ", i) var args []interface{} diff --git a/translib/db/db_cache.go b/translib/db/db_cache.go index 93687c6db..d3d2ac4cb 100644 --- a/translib/db/db_cache.go +++ b/translib/db/db_cache.go @@ -171,7 +171,8 @@ func (config *DBCacheConfig) handleReconfigureSignal() error { //////////////////////////////////////////////////////////////////////////////// func (config *DBCacheConfig) readFromDB() error { - fields, e := readRedis("TRANSLIB_DB|default") + var e error + fields, e := readRedis("TRANSLIB_DB|default", "host") if e != nil { config.PerConnection = defaultDBCacheConfig.PerConnection @@ -199,7 +200,6 @@ func (config *DBCacheConfig) readFromDB() error { for k, v := range defaultDBCacheConfig.NoCacheMaps { config.NoCacheMaps[k] = v } - } else { for k, v := range fields { switch { diff --git a/translib/db/db_config.go b/translib/db/db_config.go index 29074d101..7874f3494 100644 --- a/translib/db/db_config.go +++ b/translib/db/db_config.go @@ -22,21 +22,18 @@ package db import ( "encoding/json" "fmt" + "github.com/golang/glog" io "io/ioutil" "os" "strconv" - - "github.com/golang/glog" + "strings" ) -var dbConfigMap = make(map[string]interface{}) +var multiDbsConfigMap = make(map[string]map[string]interface{}) -func dbConfigInit() { - dbConfigPath := "/var/run/redis/sonic-db/database_config.json" - if path, ok := os.LookupEnv("DB_CONFIG_PATH"); ok { - dbConfigPath = path - } +func dbConfigInit(dbConfigPath string, MDBName string) { + var dbConfigMap = make(map[string]interface{}) // If the path does not exist, it could be a go lang jenkins test with // an uninitialized/missing DB_CONFIG_PATH. Use the path // ${PWD}/../../../tools/test/database_config.json if it exists @@ -57,13 +54,24 @@ func dbConfigInit() { assert(err) } } + multiDbsConfigMap[MDBName] = dbConfigMap } func assert(msg error) { panic(msg) } -func getDbList() map[string]interface{} { +// Function to split the input string and assign values to dbName and MDBName +func getDBNames(str string) (string, string) { + if strings.Contains(str, ".") { + parts := strings.SplitN(str, ".", 2) + return parts[0], parts[1] + } + return str, "host" +} + +func getDbList(MDBName string) map[string]interface{} { + var dbConfigMap = multiDbsConfigMap[MDBName] dbEntries, ok := dbConfigMap["DATABASES"].(map[string]interface{}) if !ok { assert(fmt.Errorf("DATABASES is invalid key.")) @@ -72,11 +80,14 @@ func getDbList() map[string]interface{} { } func isDbInstPresent(dbName string) bool { - _, ok := getDbList()[dbName] + dbName, MDBName := getDBNames(dbName) + _, ok := getDbList(MDBName)[dbName] return ok } func getDbInst(dbName string) map[string]interface{} { + dbName, MDBName := getDBNames(dbName) + var dbConfigMap = multiDbsConfigMap[MDBName] db, ok := dbConfigMap["DATABASES"].(map[string]interface{})[dbName] if !ok { assert(fmt.Errorf("database name '%v' is not found", dbName)) @@ -93,7 +104,8 @@ func getDbInst(dbName string) map[string]interface{} { } func getDbSeparator(dbName string) string { - dbEntries := getDbList() + dbName, MDBName := getDBNames(dbName) + dbEntries := getDbList(MDBName) separator, ok := dbEntries[dbName].(map[string]interface{})["separator"] if !ok { assert(fmt.Errorf("'separator' is not a valid field")) @@ -102,7 +114,8 @@ func getDbSeparator(dbName string) string { } func getDbId(dbName string) int { - dbEntries := getDbList() + dbName, MDBName := getDBNames(dbName) + dbEntries := getDbList(MDBName) id, ok := dbEntries[dbName].(map[string]interface{})["id"] if !ok { assert(fmt.Errorf("'id' is not a valid field")) diff --git a/translib/db/db_cursor_test.go b/translib/db/db_cursor_test.go index 3885ab241..6186691fb 100644 --- a/translib/db/db_cursor_test.go +++ b/translib/db/db_cursor_test.go @@ -93,6 +93,7 @@ func TestNewScanCursor(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", diff --git a/translib/db/db_cvl_hint_test.go b/translib/db/db_cvl_hint_test.go index 8fd281c8e..8074a035b 100644 --- a/translib/db/db_cvl_hint_test.go +++ b/translib/db/db_cvl_hint_test.go @@ -29,6 +29,7 @@ var hValue = map[string]string{"a": "1", "b": "2"} func newEnableCVLDB(dBNum DBNum) (*DB, error) { d, e := NewDB(Options{ DBNo: dBNum, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", diff --git a/translib/db/db_lock.go b/translib/db/db_lock.go index 071dfd854..a7e4f89fb 100644 --- a/translib/db/db_lock.go +++ b/translib/db/db_lock.go @@ -61,19 +61,19 @@ type LockStruct struct { lockStruct } -func (lt *LockStruct) tryLock() error { +func (lt *LockStruct) tryLock(multiDbName string) error { var err error var client *redis.Client var reply interface{} if (lt == nil) || lt.locked { err = tlerr.TranslibDBNotSupported{} - glog.Errorf("tryLock: %v: %v", lt, err) + glog.Errorf("tryLock:%v: %v: %v", multiDbName, lt, err) return err } // Create The State DB Connection. - if client, err = getStateDB(); err != nil { + if client, err = getStateDB(multiDbName); err != nil { return err } defer client.Close() @@ -81,7 +81,8 @@ func (lt *LockStruct) tryLock() error { // HSETNX: Set Hash Field if Not Exist args := []interface{}{"HSETNX", lockTableKey, lt.Name, lt.comm + ":" + lt.Id} - glog.Info("tryLock: RedisCmd: STATE_DB: ", args) + glog.Infof("tryLock: RedisCmd: STATE_DB: %v, MultiDbName: %v", + args, multiDbName) if reply, err = client.Do(args...).Result(); err == nil { if intReply, ok := reply.(int64); !ok { glog.Errorf("tryLock: Reply %v Not int64: %v Type: %v", @@ -101,7 +102,7 @@ func (lt *LockStruct) tryLock() error { return err } -func (lt *LockStruct) unlock() error { +func (lt *LockStruct) unlock(multiDbName string) error { var err error var client *redis.Client var reply interface{} @@ -113,7 +114,7 @@ func (lt *LockStruct) unlock() error { } // Create The State DB Connection. - if client, err = getStateDB(); err != nil { + if client, err = getStateDB(multiDbName); err != nil { return err } defer client.Close() @@ -124,14 +125,14 @@ func (lt *LockStruct) unlock() error { []string{lt.Name, lt.comm, lt.Id}).Result(); err == nil { if intReply, ok := reply.(int64); !ok { - glog.Errorf("unlock: Reply %v Not int64: %v Type: %v", + glog.Errorf("unlock Reply %v Not int64: %v Type: %v", lt, reply, reflect.TypeOf(reply)) err = tlerr.TranslibDBScriptFail{Description: "Unexpected response"} } else if intReply == 1 { lt.locked = false - glog.Infof("unlock: Unlocked: %s:%s", lt.Name, lt.Id) + glog.Infof("unlock:%v Unlocked: %s", lt.Name, lt.Id) } else { - glog.Info("unlock: Already Unlocked") + glog.Infof("unlock:%v Already Unlocked", multiDbName) err = tlerr.TranslibDBLock{} } } @@ -168,59 +169,86 @@ func (lt *LockStruct) dbLockedError(c *redis.Client) error { return tlerr.TranslibDBLock{Type: lockType} } -var cdbLock *LockStruct +// Define a global map to hold locks for multiple multiDbNames. +var cdbLock map[string]*LockStruct -func ConfigDBTryLock(token string) error { +// Initialize the global map for storing locks +func init() { + cdbLock = make(map[string]*LockStruct) +} + +// ConfigDBTryLock tries to acquire a lock for the given multiDbName. +// It uses a map to store locks for multiple multiDbNames. +func ConfigDBTryLock(token string, multiDbName string) error { var err error - glog.Info("ConfigDBTryLock:") + var ls map[string]*LockStruct // Local lock struct map for this invocation + + glog.Infof("ConfigDBTryLock: mdbname:%v", multiDbName) + if bool(glog.V(3)) || !flag.Parsed() { - dumpStack(7, 13) // Skip the stack frames upto NewDB() + dumpStack(7, 13) } else { dumpStack(9, 10) } - // If len(token) == 0, this is not a configure session. (Eg: exec mode - // configure replace) - if cdbLock != nil { - err = cdbLock.dbLockedError(nil) - } else { - ls := LockStruct{Name: configDBLock, Id: token, - lockStruct: lockStruct{comm: execName}} - for attempts := 0; attempts < tryLockAttempt; attempts++ { - if err = ls.tryLock(); err == nil { - cdbLock = &ls - break - } else if lErr, ok := err.(tlerr.TranslibDBLock); ok && lErr.Type == tlerr.DBLockConfigSession { - break - } else if (attempts + 1) == tryLockAttempt { - break - } - glog.Infof("ConfigDBTryLock: Pausing %d ms", tryLockPause) - time.Sleep(tryLockPause * time.Millisecond) - glog.Infof("ConfigDBTryLock: Retrying Attempt %d", attempts) + // If a lock for the given multiDbName already exists, return an error. + if existingLock, exists := cdbLock[multiDbName]; exists && existingLock != nil { + return existingLock.dbLockedError(nil) + } + + // Create a new LockStruct map if it's nil (this will hold the lock for this session). + if ls == nil { + ls = make(map[string]*LockStruct) + } + + // If the lock for the given multiDbName doesn't exist, create it. + if _, ok := ls[multiDbName]; !ok { + ls[multiDbName] = &LockStruct{Name: "ConfigDBLock", Id: token, lockStruct: lockStruct{comm: execName}} + } + + // Try to acquire the lock for the given multiDbName + for attempts := 0; attempts < tryLockAttempt; attempts++ { + err = ls[multiDbName].tryLock(multiDbName) + + if err == nil { + cdbLock[multiDbName] = ls[multiDbName] + break + } else if lErr, ok := err.(tlerr.TranslibDBLock); ok && lErr.Type == tlerr.DBLockConfigSession { + break + } else if (attempts + 1) == tryLockAttempt { + break } + + glog.Infof("ConfigDBTryLock: Pausing %d ms", tryLockPause) + time.Sleep(tryLockPause * time.Millisecond) + glog.Infof("ConfigDBTryLock: Retrying Attempt %d", attempts) } if err != nil { glog.Error("ConfigDBTryLock: Error", err) } + return err } -func ConfigDBUnlock(token string) error { +func ConfigDBUnlock(token string, multiDBName string) error { var err error - glog.Info("ConfigDBUnlock:") + glog.Infof("ConfigDBUnlock:%v", multiDBName) if bool(glog.V(3)) || !flag.Parsed() { dumpStack(7, 13) // Skip the stack frames upto DeleteDB() } else { dumpStack(9, 10) } - if cdbLock == nil { + if lock, exists := cdbLock[multiDBName]; exists && lock != nil { + // Lock exists, unlock it + err = lock.unlock(multiDBName) + + // Clear the lock from the map + cdbLock[multiDBName] = nil + } else { + // Lock doesn't exist, handle the error err = tlerr.TranslibDBLock{} - } else if cdbLock != nil { - err = cdbLock.unlock() - cdbLock = nil } if err != nil { @@ -233,14 +261,21 @@ func ConfigDBClearLock() error { var err error glog.Info("ConfigDBClearLock:") - err = (&LockStruct{Name: configDBLock, Id: "*", - lockStruct: lockStruct{comm: execName, locked: true}}).unlock() - cdbLock = nil + multiDbNames := GetMultiDbNames() + for _, multiDbName := range multiDbNames { + + err = (&LockStruct{Name: configDBLock, Id: "*", + lockStruct: lockStruct{comm: execName, locked: true}}).unlock(multiDbName) + cdbLock[multiDbName] = nil - // Clearing an absent lock is ok. - if _, ok := err.(tlerr.TranslibDBLock); ok { - glog.Info("ConfigDBClearLock: Lock Absent") - err = nil + // Clearing an absent lock is ok. + if _, ok := err.(tlerr.TranslibDBLock); ok { + glog.Info("ConfigDBClearLock: Lock Absent") + err = nil + } + if err != nil { + break + } } return err } @@ -262,13 +297,13 @@ func dumpStack(begin, end int) { } } -func getStateDB() (*redis.Client, error) { +func getStateDB(multiDbName string) (*redis.Client, error) { var client *redis.Client var err error if client = redis.NewClient(adjustRedisOpts(&Options{ - DBNo: StateDB})); client == nil { + DBNo: StateDB, MDBName: multiDbName})); client == nil { - glog.Error("getStateDB: Could not create redis client: STATE_DB") + glog.Error("getStateDB: Could not create redis client: STATE_DB for:", multiDbName) err = tlerr.TranslibDBCannotOpen{} } return client, err diff --git a/translib/db/db_lock_test.go b/translib/db/db_lock_test.go index 89029e912..1670c1d8f 100644 --- a/translib/db/db_lock_test.go +++ b/translib/db/db_lock_test.go @@ -24,6 +24,7 @@ import ( "strconv" "testing" + "fmt" "github.com/Azure/sonic-mgmt-common/translib/tlerr" ) @@ -31,17 +32,27 @@ var testSTok string = "1001-1" var fTs *TableSpec = &TableSpec{Name: lockTable} var fKey Key = Key{Comp: []string{lockKey}} -var stateDB *DB +var stateDB map[string]*DB -func setupKey(t *testing.T, ts *TableSpec, key Key, val Value) { +func init() { var err error - if stateDB, err = NewDB(Options{DBNo: StateDB}); err != nil { - t.Errorf("setupKey: NewDB(StateDB) fails: %v", err) + stateDB = make(map[string]*DB) + for _, dbName := range GetMultiDbNames() { + if stateDB[dbName], err = NewDB(Options{DBNo: StateDB, MDBName: dbName}); err != nil { + fmt.Errorf("setupKey: NewDB(StateDB) fails: %v", err) + } } - stateDB.DeleteEntry(ts, key) - t.Cleanup(func() { stateDB.DeleteEntry(ts, key); cdbLock = nil }) +} - if err = stateDB.ModEntry(ts, key, val); err != nil { +func setupKey(t *testing.T, ts *TableSpec, key Key, val Value, dbName string) { + var err error + //if stateDB, err = NewDB(Options{DBNo: StateDB, MDBName: hostDBName}); err != nil { + // t.Errorf("setupKey: NewDB(StateDB) fails: %v", err) + //} + stateDB[dbName].DeleteEntry(ts, key) + t.Cleanup(func() { stateDB[dbName].DeleteEntry(ts, key); cdbLock[dbName] = nil }) + + if err = stateDB[dbName].ModEntry(ts, key, val); err != nil { t.Errorf("setupKey: ModEntry() fails: %v", err) } } @@ -60,10 +71,9 @@ func TestLock(t *testing.T) { func testLock(lockToken string, expError tlerr.DBLockType) func(*testing.T) { return func(t *testing.T) { fVal := Value{Field: map[string]string{configDBLock: lockToken}} - setupKey(t, fTs, fKey, fVal) - + setupKey(t, fTs, fKey, fVal, hostDBName) err := (&LockStruct{Name: configDBLock, Id: testSTok, - lockStruct: lockStruct{comm: execName}}).tryLock() + lockStruct: lockStruct{comm: execName}}).tryLock(hostDBName) if e, ok := err.(tlerr.TranslibDBLock); !ok || e.Type != expError { exp := tlerr.TranslibDBLock{Type: expError} @@ -76,52 +86,53 @@ func testLock(lockToken string, expError tlerr.DBLockType) func(*testing.T) { func TestLockUnlock(t *testing.T) { var err error - - // Clean it up. - if err = stateDB.DeleteEntry(fTs, fKey); err != nil { - t.Errorf("DeleteEntry: Expecting nil: Received %v", err) - } - t.Cleanup(func() { stateDB.DeleteEntry(fTs, fKey); cdbLock = nil }) - - // Lock it - ls := &LockStruct{Name: configDBLock, Id: testSTok, - lockStruct: lockStruct{comm: execName}} - err = ls.tryLock() - if err != nil { - t.Errorf("tryLock: Expecting nil: Received %v", err) - } - - // Lock it Again! -- Should fail with Not Supported - err = ls.tryLock() - if _, ok := err.(tlerr.TranslibDBNotSupported); !ok { - t.Errorf("Expecting %v: Received %v", tlerr.TranslibDBNotSupported{}, - err) - } - - // Unlock it. - err = ls.unlock() - if err != nil { - t.Errorf("unlock: Expecting nil: Received %v", err) - } - - // Unlock it Again! -- Should fail with Not Supported - err = ls.unlock() - if _, ok := err.(tlerr.TranslibDBNotSupported); !ok { - t.Errorf("unlock: Expecting %v: Received %v", - tlerr.TranslibDBNotSupported{}, err) - } - - // Lock it Yet Again! -- Should succeed - err = ls.tryLock() - if err != nil { - t.Errorf("tryLock 2: Expecting nil: Received %v", err) - } - - // Let's be nice, and clean it up. - // Unlock it. - err = ls.unlock() - if err != nil { - t.Errorf("unlock: Expecting nil: Received %v", err) + for _, dbName := range GetMultiDbNames() { + t.Run("LockAndUnlock_"+dbName, func(t *testing.T) { + // Clean it up. + if err = stateDB[dbName].DeleteEntry(fTs, fKey); err != nil { + t.Errorf("DeleteEntry: Expecting nil: Received %v", err) + } + t.Cleanup(func() { stateDB[dbName].DeleteEntry(fTs, fKey); cdbLock[dbName] = nil }) + ls := &LockStruct{Name: configDBLock, Id: testSTok, + lockStruct: lockStruct{comm: execName}} + err = ls.tryLock(dbName) + if err != nil { + t.Errorf("tryLock: Expecting nil: Received %v", err) + } + + // Lock it Again! -- Should fail with Not Supported + err = ls.tryLock(dbName) + if _, ok := err.(tlerr.TranslibDBNotSupported); !ok { + t.Errorf("Expecting %v: Received %v", tlerr.TranslibDBNotSupported{}, + err) + } + + // Unlock it. + err = ls.unlock(dbName) + if err != nil { + t.Errorf("unlock: Expecting nil: Received %v", err) + } + + // Unlock it Again! -- Should fail with Not Supported + err = ls.unlock(dbName) + if _, ok := err.(tlerr.TranslibDBNotSupported); !ok { + t.Errorf("unlock: Expecting %v: Received %v", + tlerr.TranslibDBNotSupported{}, err) + } + + // Lock it Yet Again! -- Should succeed + err = ls.tryLock(dbName) + if err != nil { + t.Errorf("tryLock 2: Expecting nil: Received %v", err) + } + + // Let's be nice, and clean it up. + // Unlock it. + err = ls.unlock(dbName) + if err != nil { + t.Errorf("unlock: Expecting nil: Received %v", err) + } + }) } } @@ -130,19 +141,23 @@ func TestLockUnlockNonExisting(t *testing.T) { var err error - // Clean it up. - if err = stateDB.DeleteEntry(fTs, fKey); err != nil { - t.Errorf("DeleteEntry: Expecting nil: Received %v", err) - } - t.Cleanup(func() { stateDB.DeleteEntry(fTs, fKey); cdbLock = nil }) - - // Unlock it. -- Should Fail. - ls := &LockStruct{Name: configDBLock, Id: testSTok, - lockStruct: lockStruct{comm: execName}} - err = ls.unlock() - if _, ok := err.(tlerr.TranslibDBNotSupported); !ok { - t.Errorf("Expecting %v: Received %v", tlerr.TranslibDBNotSupported{}, - err) + for _, dbName := range GetMultiDbNames() { + // Clean it up. + if err = stateDB[dbName].DeleteEntry(fTs, fKey); err != nil { + t.Errorf("DeleteEntry: Expecting nil: Received %v", err) + } + t.Cleanup(func() { stateDB[dbName].DeleteEntry(fTs, fKey); cdbLock[dbName] = nil }) + + t.Run("LockUnlockNonExisting_"+dbName, func(t *testing.T) { + // Unlock it. -- Should Fail. + ls := &LockStruct{Name: configDBLock, Id: testSTok, + lockStruct: lockStruct{comm: execName}} + err = ls.unlock(dbName) + if _, ok := err.(tlerr.TranslibDBNotSupported); !ok { + t.Errorf("Expecting %v: Received %v", tlerr.TranslibDBNotSupported{}, + err) + } + }) } } @@ -151,26 +166,30 @@ func TestLockNotOurLockUnlock(t *testing.T) { var err error - fVal := Value{Field: map[string]string{ - configDBLock: execName + ":" + testSTok + "0"}} - // ^^^ Somebody else's lock - setupKey(t, fTs, fKey, fVal) - - // Unlock it. -- Should Fail. - ls := &LockStruct{Name: configDBLock, Id: testSTok, - lockStruct: lockStruct{comm: execName}} - err = ls.unlock() - if _, ok := err.(tlerr.TranslibDBNotSupported); !ok { - t.Errorf("Expecting %v: Received %v", tlerr.TranslibDBNotSupported{}, - err) - } - - // Unlock it faking locked field in LockStruct{} -- Fail with different err. - ls.locked = true - err = ls.unlock() - if _, ok := err.(tlerr.TranslibDBLock); !ok { - t.Errorf("Expecting %v: Received %v", tlerr.TranslibDBLock{}, - err) + for idx, dbName := range GetMultiDbNames() { + t.Run("LockNotOurLockUnlock_"+dbName, func(t *testing.T) { + fVal := Value{Field: map[string]string{ + configDBLock: execName + ":" + testSTok + strconv.Itoa(idx)}} + // ^^^ Somebody else's lock + setupKey(t, fTs, fKey, fVal, dbName) + + // Unlock it. -- Should Fail. + ls := &LockStruct{Name: configDBLock, Id: testSTok, + lockStruct: lockStruct{comm: execName}} + err = ls.unlock(dbName) + if _, ok := err.(tlerr.TranslibDBNotSupported); !ok { + t.Errorf("Expecting %v: Received %v", tlerr.TranslibDBNotSupported{}, + err) + } + + // Unlock it faking locked field in LockStruct{} -- Fail with different err. + ls.locked = true + err = ls.unlock(dbName) + if _, ok := err.(tlerr.TranslibDBLock); !ok { + t.Errorf("Expecting %v: Received %v", tlerr.TranslibDBLock{}, + err) + } + }) } } @@ -182,26 +201,26 @@ func TestLockClearLock(t *testing.T) { fVal := Value{Field: map[string]string{ configDBLock: execName + ":" + testSTok + "0"}} // ^^^ Somebody else's lock - setupKey(t, fTs, fKey, fVal) + setupKey(t, fTs, fKey, fVal, hostDBName) // Clear it. -- Should Work. ls := &LockStruct{Name: configDBLock, Id: "*", lockStruct: lockStruct{comm: execName, locked: true}} - err = ls.unlock() + err = ls.unlock(hostDBName) if err != nil { t.Errorf("unlock: Expecting nil: Received %v", err) } // Lock it -- Should succeed ls.Id = testSTok - err = ls.tryLock() + err = ls.tryLock(hostDBName) if err != nil { t.Errorf("tryLock: Expecting nil: Received %v", err) } // Let's be nice, and clean it up. // Unlock it. - err = ls.unlock() + err = ls.unlock(hostDBName) if err != nil { t.Errorf("unlock: Expecting nil: Received %v", err) } @@ -212,49 +231,54 @@ func TestLockConfigDB(t *testing.T) { var err error - // Clean it up. - if err = stateDB.DeleteEntry(fTs, fKey); err != nil { - t.Errorf("DeleteEntry: Expecting nil: Received %v", err) - } - t.Cleanup(func() { stateDB.DeleteEntry(fTs, fKey); cdbLock = nil }) - - // Lock it - err = ConfigDBTryLock(testSTok) - if err != nil { - t.Errorf("ConfigDBTryLock: Expecting nil: Received %v", err) - } - - // Lock it Again! -- Should fail with Lock Error - err = ConfigDBTryLock(testSTok) - if _, ok := err.(tlerr.TranslibDBLock); !ok { - t.Errorf("Expecting %v: Received %v", tlerr.TranslibDBLock{}, - err) - } - - // Unlock it. - err = ConfigDBUnlock(testSTok) - if err != nil { - t.Errorf("ConfigDBUnlock: Expecting nil: Received %v", err) - } - - // Unlock it Again! -- Should fail with Lock Error - err = ConfigDBUnlock(testSTok) - if _, ok := err.(tlerr.TranslibDBLock); !ok { - t.Errorf("ConfigDBUnlock: Expecting %v: Received %v", - tlerr.TranslibDBLock{}, err) - } - - // Lock it Yet Again! -- Should succeed - err = ConfigDBTryLock(testSTok) - if err != nil { - t.Errorf("ConfigDBTryLock 2: Expecting nil: Received %v", err) - } - - // Let's be nice, and clean it up. - // Unlock it. - err = ConfigDBUnlock(testSTok) - if err != nil { - t.Errorf("unlock: Expecting nil: Received %v", err) + for _, dbName := range GetMultiDbNames() { + // Clean it up. + if err = stateDB[dbName].DeleteEntry(fTs, fKey); err != nil { + t.Errorf("DeleteEntry: Expecting nil: Received %v", err) + } + t.Cleanup(func() { stateDB[dbName].DeleteEntry(fTs, fKey); cdbLock[dbName] = nil }) + + t.Run("LockConfigDB_"+dbName, func(t *testing.T) { + + // Lock it + err = ConfigDBTryLock(testSTok, dbName) + if err != nil { + t.Errorf("ConfigDBTryLock: Expecting nil: Received %v", err) + } + + // Lock it Again! -- Should fail with Lock Error + err = ConfigDBTryLock(testSTok, dbName) + if _, ok := err.(tlerr.TranslibDBLock); !ok { + t.Errorf("Expecting %v: Received %v", tlerr.TranslibDBLock{}, + err) + } + + // Unlock it. + err = ConfigDBUnlock(testSTok, dbName) + if err != nil { + t.Errorf("ConfigDBUnlock: Expecting nil: Received %v", err) + } + + // Unlock it Again! -- Should fail with Lock Error + err = ConfigDBUnlock(testSTok, dbName) + if _, ok := err.(tlerr.TranslibDBLock); !ok { + t.Errorf("ConfigDBUnlock: Expecting %v: Received %v", + tlerr.TranslibDBLock{}, err) + } + + // Lock it Yet Again! -- Should succeed + err = ConfigDBTryLock(testSTok, dbName) + if err != nil { + t.Errorf("ConfigDBTryLock 2: Expecting nil: Received %v", err) + } + + // Let's be nice, and clean it up. + // Unlock it. + err = ConfigDBUnlock(testSTok, dbName) + if err != nil { + t.Errorf("unlock: Expecting nil: Received %v", err) + } + }) } } @@ -264,28 +288,32 @@ func TestLockConfigDBClearLock(t *testing.T) { var err error - fVal := Value{Field: map[string]string{ - configDBLock: execName + ":" + testSTok + "0"}} - // ^^^ Somebody else's lock - setupKey(t, fTs, fKey, fVal) - - // Clear it. -- Should Work. - err = ConfigDBClearLock() - if err != nil { - t.Errorf("unlock: Expecting nil: Received %v", err) - } - - // Lock it - err = ConfigDBTryLock(testSTok) - if err != nil { - t.Errorf("ConfigDBTryLock: Expecting nil: Received %v", err) - } - - // Let's be nice, and clean it up. - // Unlock it. - err = ConfigDBUnlock(testSTok) - if err != nil { - t.Errorf("unlock: Expecting nil: Received %v", err) + for _, dbName := range GetMultiDbNames() { + t.Run("LockConfigDBClearLock_"+dbName, func(t *testing.T) { + fVal := Value{Field: map[string]string{ + configDBLock: execName + ":" + testSTok + "0"}} + // ^^^ Somebody else's lock + setupKey(t, fTs, fKey, fVal, dbName) + + // Clear it. -- Should Work. + err = ConfigDBClearLock() + if err != nil { + t.Errorf("unlock: Expecting nil: Received %v", err) + } + + // Lock it + err = ConfigDBTryLock(testSTok, dbName) + if err != nil { + t.Errorf("ConfigDBTryLock: Expecting nil: Received %v", err) + } + + // Let's be nice, and clean it up. + // Unlock it. + err = ConfigDBUnlock(testSTok, dbName) + if err != nil { + t.Errorf("unlock: Expecting nil: Received %v", err) + } + }) } } @@ -294,14 +322,13 @@ func TestLockConfigDBClearLock(t *testing.T) { func TestLockConfigDBDeleteEntryFields(t *testing.T) { var err error - // Clean it up. - if err = stateDB.DeleteEntry(fTs, fKey); err != nil { + // Lock it + if err = stateDB[hostDBName].DeleteEntry(fTs, fKey); err != nil { t.Fatalf("DeleteEntry: Expecting nil: Received %v", err) } - t.Cleanup(func() { stateDB.DeleteEntry(fTs, fKey); cdbLock = nil }) + t.Cleanup(func() { stateDB[hostDBName].DeleteEntry(fTs, fKey); cdbLock[hostDBName] = nil }) - // Lock it - err = ConfigDBTryLock(testSTok) + err = ConfigDBTryLock(testSTok, hostDBName) if err != nil { t.Fatalf("ConfigDBTryLock: Expecting nil: Received %v", err) } @@ -317,6 +344,7 @@ func TestLockConfigDBDeleteEntryFields(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", diff --git a/translib/db/db_onchangecache_test.go b/translib/db/db_onchangecache_test.go index da6eb5a31..f3a36eb64 100644 --- a/translib/db/db_onchangecache_test.go +++ b/translib/db/db_onchangecache_test.go @@ -41,6 +41,7 @@ func TestOnChangeCacheReg(t *testing.T) { t.Run("occDisable", func(t *testing.T) { d := newTestDB(t, Options{ DBNo: ConfigDB, + MDBName: hostDBName, IsWriteDisabled: true, }) if err := d.RegisterTableForOnChangeCaching(ts); err == nil { @@ -54,6 +55,7 @@ func TestOnChangeCacheReg(t *testing.T) { t.Run("occEnable", func(t *testing.T) { d := newTestDB(t, Options{ DBNo: ConfigDB, + MDBName: hostDBName, IsWriteDisabled: true, IsOnChangeEnabled: true, }) @@ -71,6 +73,7 @@ func TestOnChangeCacheReg(t *testing.T) { t.Run("writeEnable", func(t *testing.T) { _, err := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, IsOnChangeEnabled: true, }) if err == nil { @@ -81,9 +84,9 @@ func TestOnChangeCacheReg(t *testing.T) { func TestOnChangeCache(t *testing.T) { // OnChange cache enabled db - d := newTestDB(t, Options{DBNo: ConfigDB, IsWriteDisabled: true, IsOnChangeEnabled: true}) + d := newTestDB(t, Options{DBNo: ConfigDB, MDBName: hostDBName, IsWriteDisabled: true, IsOnChangeEnabled: true}) // Writale db to write test keys - dw := newTestDB(t, Options{DBNo: ConfigDB, DisableCVLCheck: true}) + dw := newTestDB(t, Options{DBNo: ConfigDB, MDBName: hostDBName, DisableCVLCheck: true}) tsA := &TableSpec{Name: "TESTOCC_A"} tsB := &TableSpec{Name: "TESTOCC_B"} diff --git a/translib/db/db_opts_to_test.go b/translib/db/db_opts_to_test.go index e78a85952..79680ce0c 100644 --- a/translib/db/db_opts_to_test.go +++ b/translib/db/db_opts_to_test.go @@ -48,6 +48,7 @@ func TestDefaultTimeout(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -114,6 +115,7 @@ func blockLUAScript(wg *sync.WaitGroup, secs int, t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", diff --git a/translib/db/db_redis_opts.go b/translib/db/db_redis_opts.go index 023fd6072..989d7fd12 100644 --- a/translib/db/db_redis_opts.go +++ b/translib/db/db_redis_opts.go @@ -78,7 +78,7 @@ func setGoRedisOpts(optsString string) { // options, values passed via db Options, and TRANSLIB_DB|default settings. // Additionally it also adjusts the passed dbOpts for separator. func adjustRedisOpts(dbOpt *Options) *redis.Options { - dbRedisOptsConfig.reconfigure() + dbRedisOptsConfig.reconfigure(dbOpt.MDBName) mutexRedisOptsConfig.Lock() redisOpts := dbRedisOptsConfig.opts mutexRedisOptsConfig.Unlock() @@ -89,6 +89,8 @@ func adjustRedisOpts(dbOpt *Options) *redis.Options { dbId := int(dbOpt.DBNo) dbPassword := "" if dbInstName := getDBInstName(dbOpt.DBNo); dbInstName != "" { + // Appending the namespace along with DBName + dbInstName = dbInstName + "." + dbOpt.MDBName if isDbInstPresent(dbInstName) { if dbSock = getDbSock(dbInstName); dbSock != "" { dbNetwork = DefaultRedisUNIXNetwork @@ -152,7 +154,7 @@ func init() { // Configure DB Redis Opts // //////////////////////////////////////////////////////////////////////////////// -func (config *_DBRedisOptsConfig) reconfigure() error { +func (config *_DBRedisOptsConfig) reconfigure(multiDbName string) error { mutexRedisOptsConfig.Lock() // Handle command line options after they are parsed. @@ -173,7 +175,7 @@ func (config *_DBRedisOptsConfig) reconfigure() error { if doReconfigure { glog.Infof("_DBRedisOptsConfig:reconfigure: Handling signal.") var readDBRedisOptsConfig _DBRedisOptsConfig - readDBRedisOptsConfig.readFromDB() + readDBRedisOptsConfig.readFromDB(multiDbName) mutexRedisOptsConfig.Lock() if !reflect.DeepEqual(*config, readDBRedisOptsConfig) { @@ -196,8 +198,8 @@ func (config *_DBRedisOptsConfig) handleReconfigureSignal() error { // Read DB Redis Options Configuration // //////////////////////////////////////////////////////////////////////////////// -func (config *_DBRedisOptsConfig) readFromDB() error { - fields, e := readRedis("TRANSLIB_DB|default") +func (config *_DBRedisOptsConfig) readFromDB(multiDbName string) error { + fields, e := readRedis("TRANSLIB_DB|default", multiDbName) if e == nil { if optsString, ok := fields["go_redis_opts"]; ok { // Parse optsString into config.opts diff --git a/translib/db/db_redis_opts_test.go b/translib/db/db_redis_opts_test.go index 865917b66..31a6f707a 100644 --- a/translib/db/db_redis_opts_test.go +++ b/translib/db/db_redis_opts_test.go @@ -20,6 +20,7 @@ package db import ( + "fmt" "reflect" "testing" "time" @@ -45,6 +46,74 @@ func TestReadFromDBRedisOpts(t *testing.T) { } +func TestAdjustRedisOpts(t *testing.T) { + for _, dbName := range GetMultiDbNames() { + adjustValue := adjustRedisOpts(&Options{ + DBNo: ConfigDB, + MDBName: dbName, + InitIndicator: "", + TableNameSeparator: "|", + KeySeparator: "|", + DisableCVLCheck: true, + }) + /* + adjustDbValues for host = &{unix /var/run/redis/redis.sock 4 0 0s 0 + s 0s 10s 11s 1 0 0s 0s 0s 0s false } + */ + t.Run("AdjustRedisOpts of "+dbName, func(t *testing.T) { + switch dbName { + case "host": + t.Run("HostConnection", func(t *testing.T) { + //Redis + if adjustValue.Addr != "/var/run/redis/redis.sock" { + t.Error("GetDbSock fails in host connection") + } + }) + case "asic0": + t.Run("Asic0Connection", func(t *testing.T) { + if adjustValue.Addr != "/var/run/redis0/redis.sock" { + t.Error("GetDbSock fails in asic0 connection") + } + }) + case "asic1": + t.Run("Asic1Connection", func(t *testing.T) { + if adjustValue.Addr != "/var/run/redis1/redis.sock" { + t.Error("GetDbSock fails in asic1 connection") + } + }) + case "asic2": + t.Run("Asic2Connection", func(t *testing.T) { + if adjustValue.Addr != "/var/run/redis2/redis.sock" { + t.Error("GetDbSock fails in asic2 connection") + } + }) + case "asic3": + t.Run("Asic3Connection", func(t *testing.T) { + if adjustValue.Addr != "/var/run/redis3/redis.sock" { + t.Error("GetDbSock fails in asic3 connection") + } + }) + default: + t.Errorf("Unexpected database name: %s", dbName) + } + + }) + fmt.Printf("adjustDbValues for %s = %v adjustVale = %v\n", dbName, adjustValue, adjustValue.Addr) + } +} + +func TestReadRedis(t *testing.T) { + //FEATURE|gnmi + for _, dbName := range GetMultiDbNames() { + readData, _ := readRedis("FEATURE|gnmi", dbName) + if _, ok := readData["auto_restart"]; ok { + fmt.Printf("Data is present in %s\n", dbName) + } else { + fmt.Printf("Data is not present in %s\n", dbName) + } + //fmt.Printf("readredis Values for %s = %v and err = %v\n", dbName, readData, err) + } +} func compareRedisOptsString2Struct(t *testing.T, optsS string, opts *redis.Options) { setGoRedisOpts(optsS) if !reflect.DeepEqual(dbRedisOptsConfig.opts, *opts) { @@ -56,6 +125,7 @@ func compareRedisOptsString2Struct(t *testing.T, optsS string, opts *redis.Optio func compareRedisOptsDBRead2Struct(t *testing.T, optsS string, opts *redis.Options) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -89,7 +159,7 @@ func compareRedisOptsDBRead2Struct(t *testing.T, optsS string, opts *redis.Optio t.Logf("TestReadFromDBRedisOpts: handleReconfigureSignal()") dbRedisOptsConfig.handleReconfigureSignal() - dbRedisOptsConfig.reconfigure() + dbRedisOptsConfig.reconfigure(hostDBName) if !reflect.DeepEqual(dbRedisOptsConfig.opts, *opts) { t.Errorf("reconfigure() mismatch (%s) != %+v", optsS, opts) t.Errorf("New dbRedisOptsConfig.opts: %+v", dbRedisOptsConfig.opts) diff --git a/translib/db/db_redis_pipe_test.go b/translib/db/db_redis_pipe_test.go index 5d399b3a9..f5c229c80 100644 --- a/translib/db/db_redis_pipe_test.go +++ b/translib/db/db_redis_pipe_test.go @@ -36,6 +36,7 @@ import ( func newDB(dBNum DBNum) (*DB, error) { d, e := NewDB(Options{ DBNo: dBNum, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", diff --git a/translib/db/db_rpcdb_test.go b/translib/db/db_rpcdb_test.go index b107b44fe..cfb2df4b6 100644 --- a/translib/db/db_rpcdb_test.go +++ b/translib/db/db_rpcdb_test.go @@ -61,7 +61,7 @@ func getChannelName() { } func openPubSubRpcDB(t *testing.T, nm string) *DB { - d, e := PubSubRpcDB(Options{DBNo: LogLevelDB}, nm) + d, e := PubSubRpcDB(Options{DBNo: LogLevelDB, MDBName: hostDBName}, nm) if (d == nil) || (e != nil) { t.Fatalf("PubSubRpcDB() fails e = %v", e) diff --git a/translib/db/db_savepoint_test.go b/translib/db/db_savepoint_test.go index 161b4650c..2c798d0b6 100644 --- a/translib/db/db_savepoint_test.go +++ b/translib/db/db_savepoint_test.go @@ -98,6 +98,7 @@ func runSP(t *testing.T, tc *spTC) { ccd, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -209,6 +210,7 @@ func TestSPDeclareSP(t *testing.T) { ccd, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", diff --git a/translib/db/db_stats.go b/translib/db/db_stats.go index 47a5c41a7..3a26db7c5 100644 --- a/translib/db/db_stats.go +++ b/translib/db/db_stats.go @@ -492,7 +492,7 @@ func (config *DBStatsConfig) handleReconfigureSignal() error { //////////////////////////////////////////////////////////////////////////////// func (config *DBStatsConfig) readFromDB() error { - fields, e := readRedis("TRANSLIB_DB|default") + fields, e := readRedis("TRANSLIB_DB|default", "host") if e != nil { config.TimeStats = defaultDBStatsConfig.TimeStats config.TableStats = defaultDBStatsConfig.TableStats @@ -522,12 +522,15 @@ func (config *DBStatsConfig) readFromDB() error { // Utility Function to read Redis DB // //////////////////////////////////////////////////////////////////////////////// -func readRedis(key string) (map[string]string, error) { +func readRedis(key string, multiDbName string) (map[string]string, error) { ipAddr := DefaultRedisLocalTCPEP dbId := int(ConfigDB) dbPassword := "" if dbInstName := getDBInstName(ConfigDB); dbInstName != "" { + // Appending the namespace along with DBName + dbInstName = dbInstName + "." + multiDbName + if isDbInstPresent(dbInstName) { ipAddr = getDbTcpAddr(dbInstName) dbId = getDbId(dbInstName) diff --git a/translib/db/db_subscribe_test.go b/translib/db/db_subscribe_test.go index be2a83429..b1a2b54d6 100644 --- a/translib/db/db_subscribe_test.go +++ b/translib/db/db_subscribe_test.go @@ -45,10 +45,12 @@ var recvCCClosed bool var recvCCNotif bool var recvRCNotif bool var unknownCCNotif bool +var hostDBName string = "host" func newCCDB(dBNum DBNum) (*DB, error) { d, e := NewDB(Options{ DBNo: dBNum, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -79,7 +81,7 @@ func cleanupSub(t *testing.T, d *DB, deleteDB bool) { d.DeleteEntry(sTs, d.redis2key(sTs, sK)) } -func subHdlr(d *DB, skey *SKey, key *Key, event SEvent) error { +func subHdlr(d *DB, skey *SKey, key *Key, event SEvent, dbName string) error { fmt.Println("subHdlr: d: ", d, " skey: ", *skey, " key: ", *key, " event: ", event) switch event { @@ -156,6 +158,7 @@ func TestSubscribeHFunc(t *testing.T) { subD, e := SubscribeDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -315,6 +318,7 @@ func TestSubscribeHFuncSA(t *testing.T) { subD, e := SubscribeDBSA(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -440,6 +444,7 @@ func TestSubscribeNoCCNotif2HFuncSA(t *testing.T) { subD, e := SubscribeDBSA(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", diff --git a/translib/db/db_table_pattern_test.go b/translib/db/db_table_pattern_test.go index 175d6a73d..7ab38c1c4 100644 --- a/translib/db/db_table_pattern_test.go +++ b/translib/db/db_table_pattern_test.go @@ -124,6 +124,7 @@ func TestGetTablePatternCompOrigEmpty(t *testing.T) { func TestGetTablePattern_txCache(t *testing.T) { d := newTestDB(t, Options{ DBNo: ConfigDB, + MDBName: hostDBName, DisableCVLCheck: true, }) setupTestData(t, d.client, map[string]map[string]interface{}{ diff --git a/translib/db/db_test.go b/translib/db/db_test.go index 17d10316d..df71499ce 100644 --- a/translib/db/db_test.go +++ b/translib/db/db_test.go @@ -116,6 +116,7 @@ var dbOnC *DB func newReadOnlyDB(dBNum DBNum) (*DB, error) { d, e := NewDB(Options{ DBNo: dBNum, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -128,6 +129,7 @@ func newReadOnlyDB(dBNum DBNum) (*DB, error) { func newOnCDB(dBNum DBNum) (*DB, error) { d, e := NewDB(Options{ DBNo: dBNum, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -226,29 +228,6 @@ func TestMain(m *testing.M) { /* -1. Create, and close a DB connection. (NewDB(), DeleteDB()) - -*/ - -func TestNewDB(t *testing.T) { - - d, e := NewDB(Options{ - DBNo: ConfigDB, - InitIndicator: "", - TableNameSeparator: "|", - KeySeparator: "|", - DisableCVLCheck: true, - }) - - if d == nil { - t.Errorf("NewDB() fails e = %v", e) - } else if e = d.DeleteDB(); e != nil { - t.Errorf("DeleteDB() fails e = %v", e) - } -} - -/* - 2. Get an entry (GetEntry()) 3. Set an entry without Transaction (SetEntry()) 4. Delete an entry without Transaction (DeleteEntry()) @@ -263,6 +242,7 @@ func TestNoTransaction(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -329,6 +309,7 @@ func TestTable(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -513,6 +494,7 @@ func TestTransactionCacheWithDBContentKeysPattern(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -610,6 +592,7 @@ func TestTransactionCacheMultiKeysPattern(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -707,6 +690,7 @@ func TestTransactionCacheWithDBContentKeys(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -783,6 +767,7 @@ func TestTransactionCacheWithDBContentDel(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -857,6 +842,7 @@ func TestTransactionCacheWithDBContentDelFields(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -938,6 +924,7 @@ func TestTransactionCacheWithDBContentMod(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -1018,6 +1005,7 @@ func TestTransactionCacheWithDBContentSet(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -1085,12 +1073,152 @@ func TestTransactionCacheWithDBContentSet(t *testing.T) { } } +func TestNewDB(t *testing.T) { + //NewDB create a connection in multiple DBs function test + dbname := []string{"host", "asic0", "asic1", "asic2", "asic3"} + //dbname := GetMultiDbNames() + //mdb := make(map[string]*redis.Client) + mdb := make(map[string]string) + for _, name := range dbname { + d, e := NewDB(Options{ + DBNo: ConfigDB, + MDBName: name, + InitIndicator: "", + TableNameSeparator: "|", + KeySeparator: "|", + DisableCVLCheck: true, + }) + if d == nil { + t.Errorf("NewDB() fails e = %v", e) + } + mdb[name] = ClientToString(d.client) + if e = d.DeleteDB(); e != nil { + t.Errorf("DeleteDB() fails e = %v", e) + } + } + fmt.Println("TestNewDB executing....", mdb) + for dbName, _ := range mdb { + fmt.Printf("dbName type dbName = %T mdb[dbName] = %T, value of %s is mdb[dbname] = %v\n", dbName, mdb[dbName], dbname, mdb[dbName]) + t.Run("Connection_"+dbName, func(t *testing.T) { + switch dbName { + case "host": + t.Run("HostConnection", func(t *testing.T) { + //Redis + if mdb[dbName] != "Redis" { + t.Error("NewDB() fails in host connection") + } + }) + case "asic0": + t.Run("Asic0Connection", func(t *testing.T) { + if mdb[dbName] != "Redis" { + t.Error("NewDB() fails in asic0 connection") + } + }) + case "asic1": + t.Run("Asic1Connection", func(t *testing.T) { + if mdb[dbName] != "Redis" { + t.Error("NewDB() fails in asic1 connection") + } + }) + case "asic2": + t.Run("Asic2Connection", func(t *testing.T) { + if mdb[dbName] != "Redis" { + t.Error("NewDB() fails in asic2 connection") + } + }) + case "asic3": + t.Run("Asic3Connection", func(t *testing.T) { + if mdb[dbName] != "Redis" { + t.Error("NewDB() fails in asic3 connection") + } + }) + default: + t.Errorf("Unexpected database name: %s", dbName) + } + }) + } +} + +func TestGetNumAsic(t *testing.T) { + AsicNum := getNumAsic() + if AsicNum != 4 { + t.Errorf("GetNumAsic is less than 4 and AsicNum value is %v", AsicNum) + } + fmt.Printf("GetNumAsic is executing... AsicNum=%d\n", AsicNum) //has to remove this print +} + +func TestGetMultiDbNames(t *testing.T) { + multiDbNames := GetMultiDbNames() + t.Run("Mutli Database name host", func(t *testing.T) { + if multiDbNames[0] != "host" { + t.Error("Error in GetMultiDbNames") + } + }) + fmt.Printf("GetMultiDbNames is executing...mutiDbNames=%v\n", multiDbNames) //has to remove this print +} + +func TestInitAllDbs(t *testing.T) { + initAllDbs() +} + +func TestLoadGlobalDatabase(t *testing.T) { + globalDatabase := loadGlobalDatabase("/var/run/redis/sonic-db/database_global.json") + for _, dbName := range GetMultiDbNames() { + t.Run("Loading global database on "+dbName, func(t *testing.T) { + fmt.Printf("Loading global database on %s and value of %v and type is %T", dbName, globalDatabase[dbName], globalDatabase[dbName]) + switch dbName { + case "host": + t.Run("Host Database", func(t *testing.T) { + if globalDatabase[dbName] != "/var/run/redis/sonic-db/../../redis/sonic-db/database_config.json" { + t.Errorf("Error in loading host database %s", dbName) + } + }) + case "asic0": + t.Run("Asic0 Database", func(t *testing.T) { + if globalDatabase[dbName] != "/var/run/redis/sonic-db/../../redis0/sonic-db/database_config.json" { + t.Errorf("Error in loading asic0 database %s", dbName) + } + }) + case "asic1": + t.Run("Asic1 Database", func(t *testing.T) { + if globalDatabase[dbName] != "/var/run/redis/sonic-db/../../redis1/sonic-db/database_config.json" { + t.Errorf("Error in loading asic1 database %s", dbName) + } + }) + case "asic2": + t.Run("Asic2 Database", func(t *testing.T) { + if globalDatabase[dbName] != "/var/run/redis/sonic-db/../../redis2/sonic-db/database_config.json" { + t.Errorf("Error in loading asic2 database %s", dbName) + } + }) + case "asic3": + t.Run("Asic3 Database", func(t *testing.T) { + if globalDatabase[dbName] != "/var/run/redis/sonic-db/../../redis3/sonic-db/database_config.json" { + t.Errorf("Error in loading asic3 database %s", dbName) + } + }) + default: + t.Errorf("Unexpected database name: %s", dbName) + } + }) + } +} + +func ClientToString(client *redis.Client) string { + options := client.Options() + addr := options.Addr + db := options.DB + + return fmt.Sprintf("Redis<%s db:%d>", addr, db) +} + func testTransactionCache(t *testing.T, transRun TransRun) { var pid int = os.Getpid() d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -1364,6 +1492,7 @@ func testTransaction(t *testing.T, transRun TransRun) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -1472,6 +1601,7 @@ func testTransaction(t *testing.T, transRun TransRun) { case TransRunFailWatchKeys, TransRunFailTable: d2, e2 := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -1526,6 +1656,7 @@ func TestMap(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -1570,6 +1701,7 @@ func TestSubscribe(t *testing.T) { d, e := NewDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", @@ -1598,13 +1730,14 @@ func TestSubscribe(t *testing.T) { s, e := SubscribeDB(Options{ DBNo: ConfigDB, + MDBName: hostDBName, InitIndicator: "", TableNameSeparator: "|", KeySeparator: "|", DisableCVLCheck: true, }, skeys, func(s *DB, skey *SKey, key *Key, - event SEvent) error { + event SEvent, dbName string) error { switch event { case SEventHSet: hSetCalled = true diff --git a/translib/db/subscribe.go b/translib/db/subscribe.go index 19147c052..be8c522bc 100644 --- a/translib/db/subscribe.go +++ b/translib/db/subscribe.go @@ -93,7 +93,7 @@ func init() { } // HFunc gives the name of the table, and other per-table customizations. -type HFunc func(*DB, *SKey, *Key, SEvent) error +type HFunc func(*DB, *SKey, *Key, SEvent, string) error // SubscribeDB is the factory method to create a subscription to the DB. // The returned instance can only be used for Subscription. @@ -125,11 +125,6 @@ func iSubscribeDB(opt Options, skeys []*SKey, handler interface{}) (*DB, error) return nil, tlerr.TranslibDBNotSupported{} } - if glog.V(3) { - glog.Info("SubscribeDB: Begin: opt: ", opt, - " skeys: ", skeys, " handler: ", handler) - } - patterns := make([]string, 0, len(skeys)) patMap := make(map[string]([]int), len(skeys)) var s string @@ -142,6 +137,7 @@ func iSubscribeDB(opt Options, skeys []*SKey, handler interface{}) (*DB, error) opt.IsSubscribeDB = true // NewDB + d, e := NewDB(opt) if d.client == nil { @@ -215,7 +211,7 @@ func iSubscribeDB(opt Options, skeys []*SKey, handler interface{}) (*DB, error) if isSA { hFuncSA(d, RunningConfigNotif, "", skey, &key, sevent) } else { - hFunc(d, skey, &key, sevent) + hFunc(d, skey, &key, sevent, opt.MDBName) } } } @@ -226,11 +222,10 @@ func iSubscribeDB(opt Options, skeys []*SKey, handler interface{}) (*DB, error) if !d.sCIP { sEvent = SEventErr } - glog.Info("SubscribeDB: SEventClose|Err: ", sEvent) if isSA { hFuncSA(d, RunningConfigNotif, "", &SKey{}, &Key{}, sEvent) } else { - hFunc(d, &SKey{}, &Key{}, sEvent) + hFunc(d, &SKey{}, &Key{}, sEvent, opt.MDBName) } }() @@ -300,7 +295,7 @@ func (d *DB) key2redisChannel(ts *TableSpec, key Key) string { glog.Info("key2redisChannel: ", *ts, " key: "+key.String()) } - dbId := strconv.Itoa(d.Opts.DBNo.ID()) + dbId := strconv.Itoa(d.Opts.DBNo.ID(d.Opts.MDBName)) return "__keyspace@" + dbId + "__:" + d.key2redis(ts, key) } diff --git a/translib/lldp_app.go b/translib/lldp_app.go index 15511716f..5a36bfeb1 100644 --- a/translib/lldp_app.go +++ b/translib/lldp_app.go @@ -434,3 +434,26 @@ func (app *lldpApp) getRemoteSysCap(capb string, ifname string, setCap bool) { } } } + +func (app *lldpApp) getNamespace(path string) ([]NamespacePayload, error) { + + var nameSpaceList []NamespacePayload + + nameSpaceList = append(nameSpaceList, NamespacePayload{ + Namespace: "host", + Payloads: []map[string]interface{}{}, + Key: "", + }) + + log.Infof("LldpApp:getNamespace: nameSpaceList:%v ", nameSpaceList) + + return nameSpaceList, nil +} + +func (app *lldpApp) processPreparePhase(d *db.DB, ckey string) error { + return nil +} + +func (app *lldpApp) rollback(d *db.DB) error { + return nil +} diff --git a/translib/pfm_app.go b/translib/pfm_app.go index f2dab02a3..2fa5dd506 100644 --- a/translib/pfm_app.go +++ b/translib/pfm_app.go @@ -40,7 +40,7 @@ type PlatformApp struct { func init() { log.Info("Init called for Platform module") - err := register("/openconfig-platform:components", + err := register("/openconfig-platform:components/component[name=System Eeprom]", &appInfo{appType: reflect.TypeOf(PlatformApp{}), ygotRootType: reflect.TypeOf(ocbinds.OpenconfigPlatform_Components{}), isNative: false}) @@ -437,9 +437,13 @@ func (app *PlatformApp) doGetSysEeprom() error { var err error pf_cpts := app.getAppRootObject() - targetUriPath, _ := getYangPathFromUri(app.path.Path) + xpath := app.path.Path + targetUriPath, _ := getYangPathFromUri(xpath) + + log.Infof("EEPROM targetUriPath:%v", targetUriPath) + switch targetUriPath { - case "/openconfig-platform:components": + case "/openconfig-platform:component": pf_comp, _ := pf_cpts.NewComponent("System Eeprom") ygot.BuildEmptyTree(pf_comp) err = app.getSysEepromFromDb(pf_comp.State, true) @@ -497,3 +501,79 @@ func (app *PlatformApp) doGetSysEeprom() error { } return err } + +/* +func getPlatformRootObj(s *ygot.GoStruct) *ocbinds.OpenconfigPlatform_Components { + deviceObj := (*s).(*ocbinds.Device) + return deviceObj.Components +} + +func (app *PlatformApp) getNamespace(path string) ([]string, error) { + var nameSpaceList []string + var err error + log.Infof("Platformapp:getNamespace: path:%v ", path) + + if (*app).ygotRoot != nil { + + // Helper function to process entities and add their MDB names + addDBNames := func(entities interface{}) error { + switch e := entities.(type) { + case map[string]*ocbinds.OpenconfigPlatform_Components_Component: + for key := range e { + log.Info("pfm_app: keys ", key) + dbName := db.GetMDBNameFromEntity(key) + if err != nil { + return err + } + if !contains(nameSpaceList, dbName) { + nameSpaceList = append(nameSpaceList, dbName) + } + } + default: + return fmt.Errorf("unsupported entity type") + } + return nil + } + + if strings.Contains(path, "component") { + + pf := getPlatformRootObj((*app).ygotRoot) + if pf.Component != nil { + addDBNames(pf.Component) + } + } + } + + if len(nameSpaceList) == 0 { + // For Get requests without key in xpath * is returned. + log.Infof("No specific key found, using '*' to include all DBs.") + nameSpaceList = append(nameSpaceList, "*") + } + + log.Infof("pfm_app: nameSpaceList:%v ", nameSpaceList) + + return nameSpaceList, nil +} */ + +func (app *PlatformApp) getNamespace(path string) ([]NamespacePayload, error) { + + var nameSpaceList []NamespacePayload + + nameSpaceList = append(nameSpaceList, NamespacePayload{ + Namespace: "host", + Payloads: []map[string]interface{}{}, + Key: "", + }) + + log.Infof("PlatformApp:getNamespace: nameSpaceList:%v ", nameSpaceList) + + return nameSpaceList, nil +} + +func (app *PlatformApp) processPreparePhase(d *db.DB, ckey string) error { + return nil +} + +func (app *PlatformApp) rollback(d *db.DB) error { + return nil +} diff --git a/translib/pfm_app_test.go b/translib/pfm_app_test.go index 0ad27bb36..e16e64a12 100644 --- a/translib/pfm_app_test.go +++ b/translib/pfm_app_test.go @@ -62,7 +62,7 @@ func init() { // This will test GET on /openconfig-platform:components func Test_PfmApp_TopLevelPath(t *testing.T) { - url := "/openconfig-platform:components" + url := "/openconfig-platform:components/component[name=System Eeprom]" t.Run("Default_Response_Top_Level", processGetRequest(url, bulkPfmShowDefaultResponse, false)) @@ -119,6 +119,7 @@ func createPfmFactoryDb() error { func getStateDB() *db.DB { stateDb, _ := db.NewDB(db.Options{ DBNo: db.StateDB, + MDBName: "host", InitIndicator: "STATE_DB_INITIALIZED", TableNameSeparator: "|", KeySeparator: "|", @@ -130,6 +131,6 @@ func getStateDB() *db.DB { /***************************************************************************/ /////////// JSON Data for Tests /////////////// /***************************************************************************/ -var bulkPfmShowDefaultResponse string = "{\"openconfig-platform:components\":{\"component\":[{\"name\":\"System Eeprom\",\"state\":{\"empty\":false,\"location\":\"Slot 1\",\"name\":\"System Eeprom\",\"oper-status\":\"openconfig-platform-types:ACTIVE\",\"removable\":false}}]}}" +var bulkPfmShowDefaultResponse string = "{\"openconfig-platform:component\":[{\"name\":\"System Eeprom\",\"state\":{\"empty\":false,\"location\":\"Slot 1\",\"name\":\"System Eeprom\",\"oper-status\":\"openconfig-platform-types:ACTIVE\",\"removable\":false}}]}" -var bulkPfmShowAllJsonResponse string = "{\"openconfig-platform:components\":{\"component\":[{\"name\":\"System Eeprom\",\"state\":{\"description\":\"" + TEST_PLATFORM_NAME + "\",\"empty\":false,\"id\":\"" + TEST_PRODUCT_NAME + "\",\"location\":\"Slot 1\",\"mfg-name\":\"" + TEST_MANUF_NAME + "\",\"name\":\"System Eeprom\",\"oper-status\":\"openconfig-platform-types:ACTIVE\",\"part-no\":\"" + TEST_PART_NUMBER + "\",\"removable\":false,\"serial-no\":\"" + TEST_SERVICE_TAG + "\"}}]}}" +var bulkPfmShowAllJsonResponse string = "{\"openconfig-platform:component\":[{\"name\":\"System Eeprom\",\"state\":{\"description\":\"" + TEST_PLATFORM_NAME + "\",\"empty\":false,\"id\":\"" + TEST_PRODUCT_NAME + "\",\"location\":\"Slot 1\",\"mfg-name\":\"" + TEST_MANUF_NAME + "\",\"name\":\"System Eeprom\",\"oper-status\":\"openconfig-platform-types:ACTIVE\",\"part-no\":\"" + TEST_PART_NUMBER + "\",\"removable\":false,\"serial-no\":\"" + TEST_SERVICE_TAG + "\"}}]}" diff --git a/translib/subscribe.go b/translib/subscribe.go index 302570188..d63e00bfb 100644 --- a/translib/subscribe.go +++ b/translib/subscribe.go @@ -146,8 +146,8 @@ type subscribeInfo struct { termDone bool // Terminate message has been sent q *queue.PriorityQueue stop chan struct{} - sDBs []*db.DB //Subscription DB should be used only for keyspace notification unsubscription - dbs [db.MaxDB]*db.DB //used to perform get operations + sDBs []*db.DB //Subscription DB should be used only for keyspace notification unsubscription + dbs map[string][db.MaxDB]*db.DB //used to perform get operations } // notificationGroup is the grouping of notificationInfo by the key pattern. @@ -167,44 +167,84 @@ func init() { cleanupMap = make(map[*db.DB]*subscribeInfo) } +// Function to get APP module based on path and fetch the multi DB Names +func fetchDbNames(path string, clientVer Version) ([]string, error) { + var nameSpaces []string + + app, _, err := getAppModule(path, clientVer) + if err != nil { + return nil, err + } + + namespacePayloads, err := (*app).getNamespace(path) + + if err != nil { + return nil, err + } + + // Fetching the DBNames to iterate if getNamespace returned * + // if keys is not present in xpath of GetRequest. + if len(namespacePayloads) == 1 && namespacePayloads[0].Namespace == "*" { + nameSpaces = db.GetMultiDbNames() + } else { + nameSpaces = append(nameSpaces, namespacePayloads[0].Namespace) //Specfic key Get operation. + } + + return nameSpaces, err +} + // Subscribe - Subscribes to the paths requested and sends notifications when the data changes in DB func Subscribe(req SubscribeRequest) error { sid := subscribeContextId(req.Session) paths := req.Paths log.Infof("[%v] Subscribe: paths = %v", sid, paths) - dbs, err := getAllDbs(withWriteDisable, withOnChange) + mdb, err := getAllMdbs(withWriteDisable, withOnChange) if err != nil { return err } - sInfo := &subscribeInfo{ - id: sid, - q: req.Q, - stop: req.Stop, - dbs: dbs, - } - - sCtx := subscribeContext{ - id: sid, - sInfo: sInfo, - dbs: dbs, - version: req.ClientVersion, - session: req.Session, - recurse: true, - } - for _, path := range paths { - err = sCtx.translateAndAddPath(path, OnChange) - if err != nil { - closeAllDbs(dbs[:]) + + dbNames, err := fetchDbNames(path, req.ClientVersion) + log.Infof("Subscribe:fetchDbNames returned:%v", dbNames) + if dbNames == nil { + log.Infof("fetchDbNames returned:%v", err) return err } - } + for _, dbName := range dbNames { + + sInfo := &subscribeInfo{ + id: sid, + q: req.Q, + stop: req.Stop, + dbs: mdb, + } - // Start db subscription and exit. DB objects will be - // closed automatically when the subscription ends. - err = sCtx.startSubscribe() + sCtx := subscribeContext{ + id: sid, + sInfo: sInfo, + dbs: mdb[dbName], + version: req.ClientVersion, + session: req.Session, + recurse: true, + mdbName: dbName, + } + + err = sCtx.translateAndAddPath(path, OnChange) + if err != nil { + closeAllMdbs(mdb) + return err + } + // Start db subscription and exit. DB objects will be + // closed automatically when the subscription ends. + err = sCtx.startSubscribe() + if err != nil { + closeAllMdbs(mdb) + return err + } + } + } return err } @@ -218,45 +258,57 @@ func Subscribe(req SubscribeRequest) error { // Client should be authorized to perform "subscribe" operation. func Stream(req SubscribeRequest) error { sid := subscribeContextId(req.Session) + var sInfo *subscribeInfo log.Infof("[%v] Stream: paths = %v", sid, req.Paths) - dbs, err := getAllDbs(withWriteDisable) + mdb, err := getAllMdbs(withWriteDisable) if err != nil { return err } - defer closeAllDbs(dbs[:]) - - sc := subscribeContext{ - id: sid, - dbs: dbs, - version: req.ClientVersion, - session: req.Session, - } + defer closeAllMdbs(mdb) for _, path := range req.Paths { - err := sc.translateAndAddPath(path, Sample) - if err != nil { + dbNames, err := fetchDbNames(path, req.ClientVersion) + if dbNames == nil { + log.Infof("fetchDbNames returned:%v", err) return err } - } - sInfo := &subscribeInfo{ - id: sid, - q: req.Q, - dbs: dbs, - } + for _, dbName := range dbNames { - for _, nInfo := range sc.tgtInfos { - err = sendInitialUpdate(sInfo, nInfo) - if err != nil { - return err + sc := subscribeContext{ + id: sid, + dbs: mdb[dbName], + version: req.ClientVersion, + session: req.Session, + } + + err = sc.translateAndAddPath(path, Sample) + if err != nil { + return err + } + sInfo = &subscribeInfo{ + id: sid, + q: req.Q, + dbs: mdb, + } + + for _, nInfo := range sc.tgtInfos { + err = sendInitialUpdate(sInfo, nInfo, dbName) + if err != nil { + return err + } + } } } // Push a SyncComplete message at the end - sInfo.syncDone = true - sendSyncNotification(sInfo, false) + if sInfo != nil { + sInfo.syncDone = true + sendSyncNotification(sInfo, false) + } + return nil } @@ -272,48 +324,58 @@ func IsSubscribeSupported(req IsSubscribeRequest) ([]*IsSubscribeResponse, error log.Infof("[%v] IsSubscribeSupported: paths = %v", reqID, paths) - dbs, err := getAllDbs(withWriteDisable) + mdb, err := getAllMdbs(withWriteDisable) if err != nil { return resp, err } - defer closeAllDbs(dbs[:]) + defer closeAllMdbs(mdb) - sc := subscribeContext{ - id: reqID, - dbs: dbs, - version: req.ClientVersion, - session: req.Session, - recurse: true, - } - - for i, p := range paths { - trInfo, errApp := sc.translateSubscribe(p.Path, p.Mode) - if errApp != nil { - resp[i].Err = errApp - err = errApp - continue + for i, p := range req.Paths { + dbNames, err := fetchDbNames(p.Path, req.ClientVersion) + log.Infof("fetchDbNames returned:%v", dbNames) + if dbNames == nil { + log.Infof("fetchDbNames returned:%v", err) + return resp, err } - // Split target_defined request into separate on_change and sample - // sub-requests if required. - if p.Mode == TargetDefined { - for _, xInfo := range trInfo.segregateSampleSubpaths() { - xr := newIsSubscribeResponse(p.ID, xInfo.path) - xr.IsSubPath = true - resp = append(resp, xr) - collectNotificationPreferences(xInfo.response.ntfAppInfoTrgt, xr) - collectNotificationPreferences(xInfo.response.ntfAppInfoTrgtChlds, xr) - xInfo.saveToSession() + for _, dbName := range dbNames { + + sc := subscribeContext{ + id: reqID, + dbs: mdb[dbName], + version: req.ClientVersion, + session: req.Session, + recurse: true, } - } - r := resp[i] - collectNotificationPreferences(trInfo.response.ntfAppInfoTrgt, r) - collectNotificationPreferences(trInfo.response.ntfAppInfoTrgtChlds, r) - trInfo.saveToSession() - } + trInfo, errApp := sc.translateSubscribe(p.Path, p.Mode) + if errApp != nil { + resp[i].Err = errApp + err = errApp + continue + } + + // Split target_defined request into separate on_change and sample + // sub-requests if required. + if p.Mode == TargetDefined { + for _, xInfo := range trInfo.segregateSampleSubpaths() { + xr := newIsSubscribeResponse(p.ID, xInfo.path) + xr.IsSubPath = true + resp = append(resp, xr) + collectNotificationPreferences(xInfo.response.ntfAppInfoTrgt, xr) + collectNotificationPreferences(xInfo.response.ntfAppInfoTrgtChlds, xr) + xInfo.saveToSession() + } + } + + r := resp[i] + collectNotificationPreferences(trInfo.response.ntfAppInfoTrgt, r) + collectNotificationPreferences(trInfo.response.ntfAppInfoTrgtChlds, r) + trInfo.saveToSession() + } + } log.Infof("[%v] IsSubscribeSupported: returning %d IsSubscribeResponse; err=%v", reqID, len(resp), err) if log.V(5) { for i, r := range resp { @@ -364,7 +426,7 @@ func collectNotificationPreferences(nAppInfos []*notificationAppInfo, resp *IsSu func startDBSubscribe(opt db.Options, nGroups map[db.TableSpec]*notificationGroup, sInfo *subscribeInfo) error { var sKeyList []*db.SKey - d := sInfo.dbs[int(opt.DBNo)] + d := sInfo.dbs[opt.MDBName][int(opt.DBNo)] for tSpec, nGroup := range nGroups { skeys := nGroup.toSKeys() @@ -378,6 +440,7 @@ func startDBSubscribe(opt db.Options, nGroups map[db.TableSpec]*notificationGrou sKeyList = append(sKeyList, skeys...) + log.Info("Calling RegisterTableForOnChangeCaching..") d.RegisterTableForOnChangeCaching(&tSpec) } @@ -394,6 +457,7 @@ func startDBSubscribe(opt db.Options, nGroups map[db.TableSpec]*notificationGrou type subscribeContext struct { id string // context id dbs [db.MaxDB]*db.DB + mdbName string version Version session *SubscribeSession sInfo *subscribeInfo @@ -439,6 +503,7 @@ func (sc *subscribeContext) translateAndAddPath(path string, mode NotificationTy // Group nInfo by table and key pattern for OnChange. // Required for registering db subscriptions. if mode == OnChange { + log.Infof("Mode: ON CHANGE") if sc.dbNInfos == nil { sc.dbNInfos = make(map[db.DBNum]map[db.TableSpec]*notificationGroup) } @@ -455,6 +520,7 @@ func (sc *subscribeContext) translateAndAddPath(path string, mode NotificationTy func (sc *subscribeContext) startSubscribe() error { var err error + log.Info("In startSubscribe") sMutex.Lock() defer sMutex.Unlock() @@ -465,6 +531,7 @@ func (sc *subscribeContext) startSubscribe() error { for dbno, nGroups := range sc.dbNInfos { opt := getDBOptions(dbno, withWriteDisable) + opt.MDBName = sc.mdbName err = startDBSubscribe(opt, nGroups, sInfo) if err != nil { @@ -475,7 +542,7 @@ func (sc *subscribeContext) startSubscribe() error { } for _, nInfo := range sc.tgtInfos { - err := sendInitialUpdate(sInfo, nInfo) + err := sendInitialUpdate(sInfo, nInfo, sc.mdbName) if err != nil { log.Warningf("[%v] init sync failed -- %v", sInfo.id, err) cleanup(sInfo.stop) @@ -935,7 +1002,16 @@ func cleanup(stop chan struct{}) { } sInfo.sDBs = nil - closeAllDbs(sInfo.dbs[:]) + for _, dbName := range db.GetMultiDbNames() { + if dbArray, exists := sInfo.dbs[dbName]; exists { + dbSlice := dbArray[:] + + // Close all databases in the slice + closeAllDbs(dbSlice) + } else { + log.Warningf("DB name not found in sInfo.dbs: %s", dbName) + } + } delete(stopMap, stop) } diff --git a/translib/subscribe_notify.go b/translib/subscribe_notify.go index b967cbfa8..96ffc14d0 100644 --- a/translib/subscribe_notify.go +++ b/translib/subscribe_notify.go @@ -50,9 +50,10 @@ type notificationEvent struct { // Meta info for processSubscribe calls forceProcessSub bool appCache map[*appInfo]appInterface + mdbName string } -func notificationHandler(d *db.DB, sKey *db.SKey, key *db.Key, event db.SEvent) error { +func notificationHandler(d *db.DB, sKey *db.SKey, key *db.Key, event db.SEvent, dbName string) error { nid := fmt.Sprintf("n%d", dbNotificationCounter.Next()) log.Infof("[%v] notificationHandler: d=%v, table=%v, kayPattern=%v, key=%v, event=%v", nid, dbInfo(d), tableInfo(sKey.Ts), keyInfo(sKey.Key), keyInfo(key), event) @@ -64,10 +65,11 @@ func notificationHandler(d *db.DB, sKey *db.SKey, key *db.Key, event db.SEvent) case db.SEventHSet, db.SEventHDel, db.SEventDel: if nGrup, ok := sKey.Opaque.(*notificationGroup); ok { n := notificationEvent{ - id: nid, - event: event, - key: key, - nGrup: nGrup, + id: nid, + event: event, + key: key, + nGrup: nGrup, + mdbName: dbName, } n.process() } else { @@ -95,10 +97,11 @@ func notificationHandler(d *db.DB, sKey *db.SKey, key *db.Key, event db.SEvent) // 1. Scan all keys for the table // 2. Map each key to yang path // 3. Get value for each path and send the notification message -func sendInitialUpdate(sInfo *subscribeInfo, nInfo *notificationInfo) error { +func sendInitialUpdate(sInfo *subscribeInfo, nInfo *notificationInfo, dbName string) error { ne := notificationEvent{ - id: sInfo.id, - sInfo: sInfo, + id: sInfo.id, + sInfo: sInfo, + mdbName: dbName, } pathStr := path.String(nInfo.path) @@ -122,7 +125,7 @@ func sendInitialUpdate(sInfo *subscribeInfo, nInfo *notificationInfo) error { // DB path.. iterate over keys and generate notification for each. - d := sInfo.dbs[int(nInfo.dbno)] + d := sInfo.dbs[dbName][int(nInfo.dbno)] scanType := db.KeyScanType if len(nInfo.fldScanPatt) > 0 { scanType = db.FieldScanType @@ -325,17 +328,19 @@ func (ne *notificationEvent) process() { // DiffAndMergeOnChangeCache Compare modified entry with cached entry and // return modified fields. Also update the cache with changes. func (ne *notificationEvent) DiffAndMergeOnChangeCache() (*apis.EntryDiff, error) { + log.Infof("In DiffAndMergeOnChangeCache:") var nInfo *notificationInfo for _, n := range ne.nGrup.nInfos { nInfo = n[0] // Pick any one nInfo from notificationGroup to read dbno and table spec break } + if nInfo == nil { return nil, nil } ts := nInfo.table - d := nInfo.sInfo.dbs[nInfo.dbno] // FIXME do not assume all nInfos belong to same sInfo + d := nInfo.sInfo.dbs[ne.mdbName][nInfo.dbno] // FIXME do not assume all nInfos belong to same sInfo var oldValue, newValue db.Value var err error @@ -482,10 +487,6 @@ func (ne *notificationEvent) createYangPathInfos(nInfo *notificationInfo, fields leafName: leaf, deleted: isDelete, }) - // If nInfo is for a leaf path, do not add multiple updates. - if nInfo.flags.Has(niLeafPath) { - return yInfos - } continue } // DB field mapped to multiple leaf nodes -- a comma separated value @@ -508,10 +509,10 @@ func (ne *notificationEvent) invokeAppHandler(nInfo *notificationInfo, entryDiff log.V(2).Infof("[%s] invoking custom handler: %v", ne.id, nInfo.handler) nc := apis.NotificationContext{ Path: path.Clone(nInfo.path), - Db: ne.sInfo.dbs[int(nInfo.dbno)], + Db: ne.sInfo.dbs[ne.mdbName][int(nInfo.dbno)], Table: nInfo.table, Key: ne.key, - AllDb: ne.sInfo.dbs, + AllDb: ne.sInfo.dbs[ne.mdbName], EntryDiff: *entryDiff, Opaque: nInfo.opaque, } @@ -537,7 +538,7 @@ func (ne *notificationEvent) getValue(nInfo *notificationInfo, path string) (ygo var payload ygot.ValidatedGoStruct app := ne.getApp(nInfo) appInfo := nInfo.appInfo - dbs := ne.sInfo.dbs + dbs := ne.sInfo.dbs[ne.mdbName] err := appInitialize(&app, appInfo, path, nil, &appOptions{}, GET) @@ -582,7 +583,7 @@ func (ne *notificationEvent) processSubscribe(nInfo *notificationInfo, subpath s table: nInfo.table, key: ne.key, entry: ne.entry, - dbs: ne.sInfo.dbs, + dbs: ne.sInfo.dbs[ne.mdbName], opaque: nInfo.opaque, path: path.Clone(inPath), } diff --git a/translib/subscribe_test.go b/translib/subscribe_test.go index 01162655e..2d6e8084b 100644 --- a/translib/subscribe_test.go +++ b/translib/subscribe_test.go @@ -27,24 +27,25 @@ import ( "github.com/Azure/sonic-mgmt-common/translib/db" "github.com/Azure/sonic-mgmt-common/translib/ocbinds" + "github.com/Workiva/go-datastructures/queue" "github.com/openconfig/ygot/ygot" ) var ( - roDBs [db.MaxDB]*db.DB + roDBs map[string][db.MaxDB]*db.DB ) -func getReadOnlyDB() [db.MaxDB]*db.DB { - if roDBs[0] == nil { - roDBs, _ = getAllDbs(withWriteDisable) +func getReadOnlyDB() map[string][db.MaxDB]*db.DB { + if roDBs == nil { + roDBs, _ = getAllMdbs(withWriteDisable) addCleanupFunc("roDBs", closeAllTestDB) } return roDBs } func closeAllTestDB() error { - if roDBs[0] != nil { - closeAllDbs(roDBs[:]) + if roDBs != nil { + closeAllMdbs(roDBs) } return nil } @@ -151,6 +152,58 @@ func Benchmark_clearListKeys(b *testing.B) { } } +func TestStream(t *testing.T) { + req := SubscribeRequest{} + + req.Paths = []string{"/openconfig-optical-amplifier:optical-amplifier/amplifiers/amplifier"} + req.Q = queue.NewPriorityQueue(0, false) + req.Stop = make(chan struct{}) + req.User = UserRoles{} + req.AuthEnabled = false + req.ClientVersion = Version{Major: 0, Minor: 0, Patch: 0} + req.Session = &SubscribeSession{ + ID: "s1", + callCounter: 1, + translatedPathCache: translatedPathCache{ + pathData: make(map[string]*translatedSubData), + }, + } + + req.Session.translatedPathCache.pathData["/openconfig-optical-amplifier:optical-amplifier/amplifiers/amplifier"] = &translatedSubData{ + targetInfos: nil, + childInfos: nil, + } + + err := Stream(req) + if err != nil { + t.Errorf("Error in Stream %v", err) + } + +} + +func TestIsSubscribeSupported(t *testing.T) { + req := IsSubscribeRequest{} + req.Paths = []IsSubscribePath{{ID: 0, Path: "/openconfig-optical-amplifier:optical-amplifier/amplifiers/amplifier", Mode: Sample}} + req.User = UserRoles{} + req.AuthEnabled = false + req.ClientVersion = Version{Major: 0, Minor: 0, Patch: 0} + req.Session = &SubscribeSession{ + ID: "s1", + callCounter: 1, + translatedPathCache: translatedPathCache{ + pathData: make(map[string]*translatedSubData), + }, + } + + resp, err := IsSubscribeSupported(req) + for _, r := range resp { + fmt.Printf("IsSubscribeSupport resp %v", r.IsSubPath) + } + if err != nil { + t.Errorf("Error in IsSubscribeSupport %v", err) + } +} + /////////////////// // Messages is a utility to collect list of @@ -197,9 +250,10 @@ func testTranslateSubscribeForMode(t *testing.T, path string, mode NotificationT path: path, mode: mode, } + dbs := getReadOnlyDB() sc := subscribeContext{ id: fmt.Sprintf("test%d", subscribeCounter.Next()), - dbs: getReadOnlyDB(), + dbs: dbs["host"], recurse: true, } pInfo, err := sc.translateSubscribe(path, mode) diff --git a/translib/sys_app.go b/translib/sys_app.go index ccc48a3ae..a445a4329 100644 --- a/translib/sys_app.go +++ b/translib/sys_app.go @@ -52,7 +52,7 @@ type dbEntry struct { func init() { log.Info("SysApp: Init called for System module") - err := register("/openconfig-system:system", + err := register("/openconfig-system:system/processes", &appInfo{appType: reflect.TypeOf(SysApp{}), ygotRootType: reflect.TypeOf(ocbinds.OpenconfigSystem_System{}), isNative: false}) @@ -351,3 +351,26 @@ func (app *SysApp) processAction(dbs [db.MaxDB]*db.DB) (ActionResponse, error) { return resp, err } + +func (app *SysApp) getNamespace(path string) ([]NamespacePayload, error) { + + var nameSpaceList []NamespacePayload + + nameSpaceList = append(nameSpaceList, NamespacePayload{ + Namespace: "host", + Payloads: []map[string]interface{}{}, + Key: "", + }) + + log.Infof("SysApp:getNamespace: nameSpaceList:%v ", nameSpaceList) + + return nameSpaceList, nil +} + +func (app *SysApp) processPreparePhase(d *db.DB, ckey string) error { + return nil +} + +func (app *SysApp) rollback(d *db.DB) error { + return nil +} diff --git a/translib/transformer/interfaces_openconfig_test.go b/translib/transformer/interfaces_openconfig_test.go index ee2a92a4e..698378f52 100644 --- a/translib/transformer/interfaces_openconfig_test.go +++ b/translib/transformer/interfaces_openconfig_test.go @@ -61,9 +61,9 @@ func Test_openconfig_interfaces(t *testing.T) { time.Sleep(1 * time.Second) cleanuptbl := map[string]interface{}{"PORT_TABLE": map[string]interface{}{"Ethernet0": ""}} - unloadDB(db.ApplDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, cleanuptbl) pre_req_map := map[string]interface{}{"PORT_TABLE": map[string]interface{}{"Ethernet0": map[string]interface{}{"admin_status": "up", "mtu": "9000"}}} - loadDB(db.ApplDB, pre_req_map) + loadDB(hostDBName, db.ApplDB, pre_req_map) t.Log("\n\n--- Verify PATCH interface leaf nodes ---") url = "/openconfig-interfaces:interfaces/interface[name=Ethernet0]/state" @@ -119,9 +119,9 @@ func Test_openconfig_interfaces(t *testing.T) { time.Sleep(1 * time.Second) cleanuptbl = map[string]interface{}{"PORT_TABLE": map[string]interface{}{"Ethernet0": ""}} - unloadDB(db.ApplDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, cleanuptbl) pre_req_map = map[string]interface{}{"PORT_TABLE": map[string]interface{}{"Ethernet0": map[string]interface{}{"admin_status": "up", "mtu": "9100"}}} - loadDB(db.ApplDB, pre_req_map) + loadDB(hostDBName, db.ApplDB, pre_req_map) t.Log("\n\n--- Verify PATCH interface ---") url = "/openconfig-interfaces:interfaces/interface[name=Ethernet0]/state" @@ -129,7 +129,7 @@ func Test_openconfig_interfaces(t *testing.T) { t.Run("Test GET on interface state", processGetRequest(url, nil, expected_get_json, false)) time.Sleep(1 * time.Second) - unloadDB(db.ApplDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, cleanuptbl) } func Test_openconfig_ethernet(t *testing.T) { @@ -148,9 +148,9 @@ func Test_openconfig_ethernet(t *testing.T) { time.Sleep(1 * time.Second) cleanuptbl := map[string]interface{}{"PORT_TABLE": map[string]interface{}{"Ethernet0": ""}} - unloadDB(db.ApplDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, cleanuptbl) pre_req_map := map[string]interface{}{"PORT_TABLE": map[string]interface{}{"Ethernet0": map[string]interface{}{"admin_status": "up", "autoneg": "on", "mtu": "9100", "speed": "40000", "counters": map[string]interface{}{"in-broadcast-pkts": "0", "in-discards": "0", "in-errors": "0", "in-multicast-pkts": "0", "in-octets": "0", "in-pkts": "0", "in-unicast-pkts": "0", "out-broadcast-pkts": "0", "out-discards": "0", "out-errors": "0", "out-multicast-pkts": "0", "out-octets": "0", "out-pkts": "0", "out-unicast-pkts": "0"}}}} - loadDB(db.ApplDB, pre_req_map) + loadDB(hostDBName, db.ApplDB, pre_req_map) t.Log("\n\n--- Verify PATCH ethernet ---") url = "/openconfig-interfaces:interfaces/interface[name=Ethernet0]/openconfig-if-ethernet:ethernet/config" diff --git a/translib/transformer/sflow_openconfig_test.go b/translib/transformer/sflow_openconfig_test.go index 5b5ca8136..52d3f9da2 100644 --- a/translib/transformer/sflow_openconfig_test.go +++ b/translib/transformer/sflow_openconfig_test.go @@ -38,37 +38,37 @@ func Test_node_on_openconfig_sflow(t *testing.T) { url_body_json = "{ \"openconfig-sampling-sflow:enabled\": true, \"openconfig-sampling-sflow:polling-interval\": 100, \"openconfig-sampling-sflow:agent\": \"Ethernet0\"}" expected_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet0", "polling_interval": "100"}}} cleanuptbl = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) time.Sleep(1 * time.Second) t.Run("Test set on sflow node", processSetRequest(url, url_body_json, "POST", false, nil)) time.Sleep(1 * time.Second) - t.Run("Verify set on sflow node", verifyDbResult(rclient, "SFLOW|global", expected_map, false)) + t.Run("Verify set on sflow node", verifyDbResult(rclient[hostDBName], "SFLOW|global", expected_map, false)) time.Sleep(1 * time.Second) - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Set on sflow node ++++++++++++") t.Log("\n\n+++++++++++++ Performing Delete on sflow node ++++++++++++") pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet4", "polling_interval": "200"}}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) time.Sleep(1 * time.Second) url = "/openconfig-sampling-sflow:sampling/sflow/config" expected_err := errors.New("DELETE not supported on attribute") t.Run("Test delete on sflow node", processDeleteRequest(url, true, expected_err)) time.Sleep(1 * time.Second) cleanuptbl = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Delete on sflow node ++++++++++++") t.Log("\n\n+++++++++++++ Performing Get on Sflow node ++++++++++++") pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet8", "polling_interval": "300"}}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) expected_get_json := "{\"openconfig-sampling-sflow:state\":{\"agent\":\"Ethernet8\",\"enabled\":true,\"polling-interval\":300}}" url = "/openconfig-sampling-sflow:sampling/sflow/state" t.Run("Test get on sflow node", processGetRequest(url, nil, expected_get_json, false)) time.Sleep(1 * time.Second) - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("\n\n+++++++++++++ Done Performing Get on Sflow node ++++++++++++") t.Log("\n\n+++++++++++++ Performing Put/Replace on sflow leaf node ++++++++++++") @@ -77,15 +77,15 @@ func Test_node_on_openconfig_sflow(t *testing.T) { pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet0", "polling_interval": "100"}}} expected_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet0", "polling_interval": "300"}}} cleanuptbl = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) time.Sleep(1 * time.Second) url = "/openconfig-sampling-sflow:sampling/sflow/config/polling-interval" url_body_json = "{ \"openconfig-sampling-sflow:polling-interval\": 300}" t.Run("Update polling-interval on sflow node", processSetRequest(url, url_body_json, "PUT", false, nil)) time.Sleep(1 * time.Second) - t.Run("Verify polling-interval on sflow node", verifyDbResult(rclient, "SFLOW|global", expected_map, false)) + t.Run("Verify polling-interval on sflow node", verifyDbResult(rclient[hostDBName], "SFLOW|global", expected_map, false)) time.Sleep(1 * time.Second) - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Put/Replace on sflow leaf node ++++++++++++") @@ -95,15 +95,15 @@ func Test_node_on_openconfig_sflow(t *testing.T) { pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet0", "polling_interval": "100"}}} expected_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet4", "polling_interval": "100"}}} cleanuptbl = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) time.Sleep(1 * time.Second) url = "/openconfig-sampling-sflow:sampling/sflow/config/agent" url_body_json = "{ \"openconfig-sampling-sflow:agent\": \"Ethernet4\"}" t.Run("Update Agent on sflow node", processSetRequest(url, url_body_json, "PATCH", false, nil)) time.Sleep(1 * time.Second) - t.Run("Verify Agent on sflow node", verifyDbResult(rclient, "SFLOW|global", expected_map, false)) + t.Run("Verify Agent on sflow node", verifyDbResult(rclient[hostDBName], "SFLOW|global", expected_map, false)) time.Sleep(1 * time.Second) - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Patch on sflow leaf node ++++++++++++") } @@ -122,8 +122,8 @@ func Test_node_openconfig_sflow_collector(t *testing.T) { cleanuptbl = map[string]interface{}{"SFLOW_COLLECTOR": map[string]interface{}{"1.1.1.1_6343_default": ""}} t.Run("Test set on collector node for sflow", processSetRequest(url, url_body_json, "POST", false, nil)) time.Sleep(1 * time.Second) - t.Run("Verify set on collector node for sflow", verifyDbResult(rclient, "SFLOW_COLLECTOR|1.1.1.1_6343_default", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) + t.Run("Verify set on collector node for sflow", verifyDbResult(rclient[hostDBName], "SFLOW_COLLECTOR|1.1.1.1_6343_default", expected_map, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Set on Collector ++++++++++++") @@ -133,14 +133,14 @@ func Test_node_openconfig_sflow_collector(t *testing.T) { "collector_port": "4444", "collector_vrf": "default"}}} cleanuptbl = map[string]interface{}{"SFLOW_COLLECTOR": map[string]interface{}{"2.2.2.2_4444_default": ""}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) time.Sleep(1 * time.Second) url = "/openconfig-sampling-sflow:sampling/sflow/collectors/collector[address=2.2.2.2][port=4444][network-instance=default]" t.Run("Test delete on collector for sflow", processDeleteRequest(url, false)) time.Sleep(1 * time.Second) delete_expected := make(map[string]interface{}) - t.Run("Verify delete on collector node for sflow", verifyDbResult(rclient, "SFLOW_COLLECTOR|2.2.2.2_4444_default", delete_expected, false)) - unloadDB(db.ConfigDB, cleanuptbl) + t.Run("Verify delete on collector node for sflow", verifyDbResult(rclient[hostDBName], "SFLOW_COLLECTOR|2.2.2.2_4444_default", delete_expected, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Delete on Collector ++++++++++++") @@ -149,13 +149,13 @@ func Test_node_openconfig_sflow_collector(t *testing.T) { "collector_ip": "3.3.3.3", "collector_port": "6666", "collector_vrf": "default"}}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) expected_get_json := "{ \"openconfig-sampling-sflow:collectors\":{\"collector\":[{\"address\":\"3.3.3.3\",\"config\":{\"address\":\"3.3.3.3\",\"network-instance\":\"default\",\"port\":6666},\"network-instance\":\"default\",\"port\":6666,\"state\":{\"address\":\"3.3.3.3\",\"network-instance\":\"default\",\"port\":6666}}]}}" url = "/openconfig-sampling-sflow:sampling/sflow/collectors" t.Run("Test get on collector node for sflow", processGetRequest(url, nil, expected_get_json, false)) time.Sleep(1 * time.Second) cleanuptbl = map[string]interface{}{"SFLOW_COLLECTOR": map[string]interface{}{"3.3.3.3_6666_default": ""}} - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("\n\n+++++++++++++ Done Performing Get on Collector ++++++++++++") } @@ -168,15 +168,15 @@ func Test_node_openconfig_sflow_interface(t *testing.T) { url = "/openconfig-sampling-sflow:sampling/sflow/interfaces" url_body_json = "{ \"openconfig-sampling-sflow:interface\": [ { \"name\": \"Ethernet0\", \"config\": { \"name\": \"Ethernet0\", \"enabled\": true, \"sampling-rate\": 10000 } } ]}" pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet0", "polling_interval": "100"}}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) expected_map = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": map[string]interface{}{ "admin_state": "up", "sample_rate": "10000"}}} cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": ""}} t.Run("Test set on sflow interface", processSetRequest(url, url_body_json, "POST", false, nil)) time.Sleep(2 * time.Second) - t.Run("Verify set on sflow interface", verifyDbResult(rclient, "SFLOW_SESSION|Ethernet0", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) + t.Run("Verify set on sflow interface", verifyDbResult(rclient[hostDBName], "SFLOW_SESSION|Ethernet0", expected_map, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(2 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Set on Sflow interface ++++++++++++") @@ -188,16 +188,16 @@ func Test_node_openconfig_sflow_interface(t *testing.T) { "admin_state": "down", "sample_rate": "20000"}}} cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet4": ""}} - loadDB(db.ConfigDB, pre_req_map) - loadDB(db.ApplDB, non_pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ApplDB, non_pre_req_map) time.Sleep(2 * time.Second) url = "/openconfig-sampling-sflow:sampling/sflow/interfaces/interface[name=Ethernet4]" t.Run("Test delete on sflow interface", processDeleteRequest(url, false)) time.Sleep(2 * time.Second) delete_expected := make(map[string]interface{}) - t.Run("Verify delete on sflow interface", verifyDbResult(rclient, "SFLOW_SESSION|Ethernet4", delete_expected, false)) - unloadDB(db.ConfigDB, cleanuptbl) - unloadDB(db.ApplDB, non_pre_req_map) + t.Run("Verify delete on sflow interface", verifyDbResult(rclient[hostDBName], "SFLOW_SESSION|Ethernet4", delete_expected, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, non_pre_req_map) time.Sleep(2 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Delete on Sflow Interface ++++++++++++") @@ -208,15 +208,15 @@ func Test_node_openconfig_sflow_interface(t *testing.T) { non_pre_req_map = map[string]interface{}{"SFLOW_SESSION_TABLE": map[string]interface{}{"Ethernet8": map[string]interface{}{ "admin_state": "up", "sample_rate": "30000"}}} - loadDB(db.ConfigDB, pre_req_map) - loadDB(db.ApplDB, non_pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ApplDB, non_pre_req_map) expected_get_json := "{\"openconfig-sampling-sflow:state\":{\"enabled\":true,\"name\":\"Ethernet8\",\"sampling-rate\":30000}}" url = "/openconfig-sampling-sflow:sampling/sflow/interfaces/interface[name=Ethernet8]/state" t.Run("Test get on sflow interface", processGetRequest(url, nil, expected_get_json, false)) time.Sleep(2 * time.Second) cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet8": ""}} - unloadDB(db.ConfigDB, cleanuptbl) - unloadDB(db.ApplDB, non_pre_req_map) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, non_pre_req_map) t.Log("\n\n+++++++++++++ Done Performing Get on SFlow Interface ++++++++++++") t.Log("\n\n+++++++++++++ Performing Put/Replace on Sflow Interface ++++++++++++") @@ -230,15 +230,15 @@ func Test_node_openconfig_sflow_interface(t *testing.T) { "admin_state": "down", "sample_rate": "10000"}}} cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": ""}} - loadDB(db.ConfigDB, pre_req_map) - loadDB(db.ApplDB, non_pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ApplDB, non_pre_req_map) url = "/openconfig-sampling-sflow:sampling/sflow/interfaces/interface[name=Ethernet0]/config/enabled" url_body_json = "{ \"openconfig-sampling-sflow:enabled\": false}" t.Run("Update admin-state for sflow interface", processSetRequest(url, url_body_json, "PUT", false, nil)) time.Sleep(2 * time.Second) - t.Run("Verify admin-state for sflow interface", verifyDbResult(rclient, "SFLOW_SESSION|Ethernet0", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) - unloadDB(db.ApplDB, non_pre_req_map) + t.Run("Verify admin-state for sflow interface", verifyDbResult(rclient[hostDBName], "SFLOW_SESSION|Ethernet0", expected_map, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, non_pre_req_map) time.Sleep(2 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Put/Replace on Sflow interface ++++++++++++") @@ -253,17 +253,17 @@ func Test_node_openconfig_sflow_interface(t *testing.T) { "admin_state": "up", "sample_rate": "20000"}}} cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": ""}} - loadDB(db.ConfigDB, pre_req_map) - loadDB(db.ApplDB, non_pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ApplDB, non_pre_req_map) cleanuptbl_sflow = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} url = "/openconfig-sampling-sflow:sampling/sflow/interfaces/interface[name=Ethernet0]/config/sampling-rate" url_body_json = "{ \"openconfig-sampling-sflow:sampling-rate\": 20000}" t.Run("Update sampling-rate on sflow interface", processSetRequest(url, url_body_json, "PATCH", false, nil)) time.Sleep(2 * time.Second) - t.Run("Verify sampling-rate on sflow interface", verifyDbResult(rclient, "SFLOW_SESSION|Ethernet0", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) - unloadDB(db.ConfigDB, cleanuptbl_sflow) - unloadDB(db.ApplDB, non_pre_req_map) + t.Run("Verify sampling-rate on sflow interface", verifyDbResult(rclient[hostDBName], "SFLOW_SESSION|Ethernet0", expected_map, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl_sflow) + unloadDB(hostDBName, db.ApplDB, non_pre_req_map) time.Sleep(2 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Patch on Sflow interface ++++++++++++") diff --git a/translib/transformer/subscribe_req_xlate.go b/translib/transformer/subscribe_req_xlate.go index 27ab34136..7bce9310e 100644 --- a/translib/transformer/subscribe_req_xlate.go +++ b/translib/transformer/subscribe_req_xlate.go @@ -1785,7 +1785,7 @@ func (reqXlator *subscribeReqXlator) collectChldYgXPathInfo(ygEntry *yang.Entry, } chldNode = ygXpNode.addChildNode(rltvChldUriPath, chYgXpathInfo, childYgPath) } else { - if childYgEntry.IsList() && !isVirtualTbl { + if *chYgXpathInfo.tableName == "" && childYgEntry.IsList() && !isVirtualTbl { if log.V(dbLgLvl) { log.Warning(reqXlator.subReq.reqLogId, "No table related information for the LIST yang node path: ", childYgPath) } diff --git a/translib/transformer/subscribe_resp_xlate.go b/translib/transformer/subscribe_resp_xlate.go index a731405f9..15ffb2edb 100644 --- a/translib/transformer/subscribe_resp_xlate.go +++ b/translib/transformer/subscribe_resp_xlate.go @@ -368,12 +368,10 @@ func (dbYgXlateInfo *DbYgXlateInfo) handleDbToYangKeyXlate() error { return fmt.Errorf("%v : Error: %v - in handleDbToYangKeyXlate; table name: %v", dbYgXlateInfo.xlateReq.reqLogId, err, *dbYgXlateInfo.ygXpathInfo.tableName) } - if len(tblLst) == 0 { - return fmt.Errorf("%v handleDbToYangKeyXlate: Error: No tables are returned by the table "+ - "transformer: for the path: %v", dbYgXlateInfo.xlateReq.reqLogId, dbYgXlateInfo.uriPath) + if len(tblLst) != 0 { + dbYgXlateInfo.tableName = tblLst[0] } // taking the first table, since number of keys should be same between the tables returned by table transformer - dbYgXlateInfo.tableName = tblLst[0] if log.V(dbLgLvl) { log.Info(dbYgXlateInfo.xlateReq.reqLogId, "handleDbToYangKeyXlate: Found table from the table transformer: table name: ", dbYgXlateInfo.tableName) } @@ -385,9 +383,18 @@ func (dbYgXlateInfo *DbYgXlateInfo) handleDbToYangKeyXlate() error { "; tableName: " + dbYgXlateInfo.tableName, Path: dbYgXlateInfo.uriPath} } if len(dbTableKeyComp) > 0 { - dbYgXlateInfo.dbKey = dbTableKeyComp[0] - for idx := 1; idx < len(dbTableKeyComp); idx++ { - dbYgXlateInfo.dbKey = dbYgXlateInfo.dbKey + dbKeyRslvr.delim + dbTableKeyComp[idx] + // For COUNTER-DB key is appended with other params like below + // [ATTENUATOR-1-2-1_OutputPowerTotal 15_pm_current], which + // needs to striped and assigned only the actual key value to + // dbYgXlateInfo.dbKey. + if dbYgXlateInfo.xlateReq.dbNum == 2 && len(dbTableKeyComp) > 0 { + Key := strings.Split(dbTableKeyComp[0], "_") + dbYgXlateInfo.dbKey = Key[0] + } else { + dbYgXlateInfo.dbKey = dbTableKeyComp[0] + for idx := 1; idx < len(dbTableKeyComp); idx++ { + dbYgXlateInfo.dbKey = dbYgXlateInfo.dbKey + dbKeyRslvr.delim + dbTableKeyComp[idx] + } } } return dbYgXlateInfo.handleDbToYangKeyXfmr() @@ -437,19 +444,21 @@ func (dbYgXlateInfo *DbYgXlateInfo) handleTableXfmrCallback() ([]string, error) ygotObj := rootIntf.(ygot.GoStruct) inParams := formXfmrInputRequest(dbs[ygXpathInfo.dbIndex], dbs, currDbNum, &ygotObj, uriPath, uriPath, SUBSCRIBE, "", &dbDataMap, nil, nil, txCache) - tblList, tblXfmrErr := xfmrTblHandlerFunc(*ygXpathInfo.xfmrTbl, inParams, xfmrDbTblKeyCache) - if tblXfmrErr != nil { - log.Warningf("%v handleTableXfmrCallback: table transformer callback returns"+ - " error: %v for the callback %v", dbYgXlateInfo.xlateReq.reqLogId, tblXfmrErr, *ygXpathInfo.xfmrTbl) - } else if inParams.isVirtualTbl != nil && *inParams.isVirtualTbl { - if log.V(dbLgLvl) { - log.Info(dbYgXlateInfo.xlateReq.reqLogId, "handleTableXfmrCallback: virtualTbl is SET to TRUE for this table transformer callback: ", *ygXpathInfo.xfmrTbl) - } - } else { - if log.V(dbLgLvl) { - log.Infof(dbYgXlateInfo.xlateReq.reqLogId+"handleTableXfmrCallback: table list %v returned by table transformer callback: %v ", tblList, *ygXpathInfo.xfmrTbl) + if ygXpathInfo.xfmrTbl != nil { + tblList, tblXfmrErr := xfmrTblHandlerFunc(*ygXpathInfo.xfmrTbl, inParams, xfmrDbTblKeyCache) + if tblXfmrErr != nil { + log.Warningf("%v handleTableXfmrCallback: table transformer callback returns"+ + " error: %v for the callback %v", dbYgXlateInfo.xlateReq.reqLogId, tblXfmrErr, *ygXpathInfo.xfmrTbl) + } else if inParams.isVirtualTbl != nil && *inParams.isVirtualTbl { + if log.V(dbLgLvl) { + log.Info(dbYgXlateInfo.xlateReq.reqLogId, "handleTableXfmrCallback: virtualTbl is SET to TRUE for this table transformer callback: ", *ygXpathInfo.xfmrTbl) + } + } else { + if log.V(dbLgLvl) { + log.Infof(dbYgXlateInfo.xlateReq.reqLogId+"handleTableXfmrCallback: table list %v returned by table transformer callback: %v ", tblList, *ygXpathInfo.xfmrTbl) + } + return tblList, nil } - return tblList, nil } return nil, nil diff --git a/translib/transformer/test/openconfig-test-xfmr-annot.yang b/translib/transformer/test/openconfig-test-xfmr-annot.yang index dd04f6c00..259ab76c5 100644 --- a/translib/transformer/test/openconfig-test-xfmr-annot.yang +++ b/translib/transformer/test/openconfig-test-xfmr-annot.yang @@ -13,6 +13,7 @@ module openconfig-test-xfmr-annot { deviate add { sonic-ext:pre-transformer "test_pre_xfmr"; sonic-ext:post-transformer "test_post_xfmr"; + sonic-ext:get-namespace "test_get_namespace_xfmr"; } } diff --git a/translib/transformer/test/sonic-test-xfmr-annot.yang b/translib/transformer/test/sonic-test-xfmr-annot.yang index 50dd5a60f..31a1034e6 100644 --- a/translib/transformer/test/sonic-test-xfmr-annot.yang +++ b/translib/transformer/test/sonic-test-xfmr-annot.yang @@ -7,11 +7,56 @@ module sonic-test-xfmr-annot { import sonic-test-xfmr { prefix sonic-test-xfmr; } + deviation /sonic-test-xfmr:sonic-test-xfmr { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_SENSOR_MODE_TABLE/sonic-test-xfmr:TEST_SENSOR_MODE_TABLE_LIST { deviate add { - sonic-ext:key-transformer "test_sensor_mode_key_xfmr"; + sonic-ext:get-namespace "test_get_namespace_xfmr"; + sonic-ext:key-transformer "test_sensor_mode_key_xfmr"; } } + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_SENSOR_A_TABLE/sonic-test-xfmr:TEST_SENSOR_A_TABLE_LIST { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } + + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_SENSOR_GROUP/sonic-test-xfmr:TEST_SENSOR_GROUP_LIST { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } + + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_INTERFACE_MODE_TABLE/sonic-test-xfmr:TEST_INTERFACE_MODE_TABLE_LIST { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } + + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_SENSOR_GLOBAL + { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } + + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_CABLE_LENGTH/sonic-test-xfmr:TEST_CABLE_LENGTH_LIST + { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } + + deviation /sonic-test-xfmr:sonic-test-xfmr/sonic-test-xfmr:TEST_SENSOR_MODE_TABLE/sonic-test-xfmr:TEST_SENSOR_MODE_TABLE_LIST + { + deviate add { + sonic-ext:get-namespace "test_get_namespace_xfmr"; + } + } } diff --git a/translib/transformer/testxfmryang_test.go b/translib/transformer/testxfmryang_test.go index 9b79b5127..2cb608326 100644 --- a/translib/transformer/testxfmryang_test.go +++ b/translib/transformer/testxfmryang_test.go @@ -25,66 +25,60 @@ import ( "testing" "time" - "github.com/Azure/sonic-mgmt-common/cvl" "github.com/Azure/sonic-mgmt-common/translib/db" "github.com/Azure/sonic-mgmt-common/translib/tlerr" ) -type verifyDbResultData struct { - test string - db_key string - db_result map[string]interface{} -} - func Test_node_exercising_subtree_xfmr_and_virtual_table(t *testing.T) { - var pre_req_map, expected_map, cleanuptbl map[string]interface{} + var /*pre_req_map, */ expected_map, cleanuptbl map[string]interface{} var url, url_body_json string t.Log("\n\n+++++++++++++ Performing Set on Yang Node Exercising Subtree-Xfmr and Virtual Table ++++++++++++") url = "/openconfig-test-xfmr:test-xfmr/interfaces" - url_body_json = "{\"openconfig-test-xfmr:interface\": [ { \"id\": \"Eth_0\", \"config\": { \"id\": \"Eth_0\" }, \"ingress-test-sets\": { \"ingress-test-set\": [ { \"set-name\": \"TestSet_01\", \"type\": \"TEST_SET_IPV4\", \"config\": { \"set-name\": \"TestSet_01\", \"type\": \"TEST_SET_IPV4\" } } ] } } ]}" + url_body_json = "{ \"openconfig-test-xfmr:interface\": [ { \"id\": \"Eth_0\", \"config\": { \"id\": \"Eth_0\" }, \"ingress-test-sets\": { \"ingress-test-set\": [ { \"set-name\": \"TestSet_01\", \"type\": \"TEST_SET_IPV4\", \"config\": { \"set-name\": \"TestSet_01\", \"type\": \"TEST_SET_IPV4\" } } ] } } ]}" expected_map = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_01_TEST_SET_IPV4": map[string]interface{}{"ports@": "Eth_0", "type": "IPV4"}}} cleanuptbl = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_01_TEST_SET_IPV4": ""}} t.Run("Test set on node exercising subtree-xfmr and virtual table.", processSetRequest(url, url_body_json, "POST", false, nil)) time.Sleep(1 * time.Second) - t.Run("Verify set on node exercising subtree-xfmr and virtual table.", verifyDbResult(rclient, "TEST_SET_TABLE|TestSet_01_TEST_SET_IPV4", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) + t.Run("Verify set on node exercising subtree-xfmr and virtual table.", verifyDbResult(rclient[hostDBName], "TEST_SET_TABLE|TestSet_01_TEST_SET_IPV4", expected_map, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Set on Yang Node Exercising Subtree-Xfmr and Virtual Table ++++++++++++") - t.Log("\n\n+++++++++++++ Performing Delete on Yang Node Exercising Subtree-Xfmr and Virtual Table ++++++++++++") - pre_req_map = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_01_TEST_SET_IPV4": map[string]interface{}{ - "ports@": "Eth_0,Eth_1,Eth_3"}, - "TestSet_02_TEST_SET_IPV4": map[string]interface{}{ - "ports@": "Eth_1,Eth_4"}}} - cleanuptbl = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_01_TEST_SET_IPV4": "", "TestSet_02_TEST_SET_IPV4": ""}} - loadDB(db.ConfigDB, pre_req_map) - time.Sleep(1 * time.Second) - url = "/openconfig-test-xfmr:test-xfmr/interfaces/interface[id=Eth_1]" - t.Run("Test delete on node exercising subtree-xfmr and virtual table.", processDeleteRequest(url, false)) - time.Sleep(1 * time.Second) - expected_map = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_01_TEST_SET_IPV4": map[string]interface{}{ - "ports@": "Eth_0,Eth_3"}}} - t.Run("Verify delete on node exercising subtree-xfmr and virtual table (TestSet_01).", verifyDbResult(rclient, "TEST_SET_TABLE|TestSet_01_TEST_SET_IPV4", expected_map, false)) - expected_map = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_02_TEST_SET_IPV4": map[string]interface{}{ - "ports@": "Eth_4"}}} - t.Run("Verify delete on node exercising subtree-xfmr and virtual table (TestSet_02).", verifyDbResult(rclient, "TEST_SET_TABLE|TestSet_02_TEST_SET_IPV4", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) - time.Sleep(1 * time.Second) - t.Log("\n\n+++++++++++++ Done Performing Delete on Yang Node Exercising Subtree-Xfmr and Virtual Table ++++++++++++") - - t.Log("\n\n+++++++++++++ Performing Get on Yang Node Exercising Subtree-Xfmr and Virtual Table ++++++++++++") - pre_req_map = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_03_TEST_SET_IPV6": map[string]interface{}{ - "ports@": "Eth_1"}}} - - loadDB(db.ConfigDB, pre_req_map) - expected_get_json := "{\"openconfig-test-xfmr:ingress-test-set\":[{\"config\":{\"set-name\":\"TestSet_03\",\"type\":\"openconfig-test-xfmr:TEST_SET_IPV6\"},\"set-name\":\"TestSet_03\",\"state\":{\"set-name\":\"TestSet_03\",\"type\":\"openconfig-test-xfmr:TEST_SET_IPV6\"},\"type\":\"openconfig-test-xfmr:TEST_SET_IPV6\"}]}" - url = "/openconfig-test-xfmr:test-xfmr/interfaces/interface[id=Eth_1]/ingress-test-sets/ingress-test-set[set-name=TestSet_03][type=TEST_SET_IPV6]" - t.Run("Test get on node exercising subtree-xfmr and virtual table.", processGetRequest(url, nil, expected_get_json, false)) - cleanuptbl = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_03_TEST_SET_IPV6": ""}} - unloadDB(db.ConfigDB, cleanuptbl) - t.Log("\n\n+++++++++++++ Done Performing Get on Yang Node Exercising Subtree-Xfmr and Virtual Table ++++++++++++") - + /* + t.Log("\n\n+++++++++++++ Performing Delete on Yang Node Exercising Subtree-Xfmr and Virtual Table ++++++++++++") + pre_req_map = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_01_TEST_SET_IPV4": map[string]interface{}{ + "ports@": "Eth_0,Eth_1,Eth_3"}, + "TestSet_02_TEST_SET_IPV4": map[string]interface{}{ + "ports@": "Eth_1,Eth_4"}}} + cleanuptbl = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_01_TEST_SET_IPV4": "", "TestSet_02_TEST_SET_IPV4": ""}} + loadDB(hostDBName, db.ConfigDB, pre_req_map) + time.Sleep(1 * time.Second) + url = "/openconfig-test-xfmr:test-xfmr/interfaces/interface[id=Eth_1]" + t.Run("Test delete on node exercising subtree-xfmr and virtual table.", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + expected_map = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_01_TEST_SET_IPV4": map[string]interface{}{ + "ports@": "Eth_0,Eth_3"}}} + t.Run("Verify delete on node exercising subtree-xfmr and virtual table (TestSet_01).", verifyDbResult(rclient[hostDBName], "TEST_SET_TABLE|TestSet_01_TEST_SET_IPV4", expected_map, false)) + expected_map = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_02_TEST_SET_IPV4": map[string]interface{}{ + "ports@": "Eth_4"}}} + t.Run("Verify delete on node exercising subtree-xfmr and virtual table (TestSet_02).", verifyDbResult(rclient[hostDBName], "TEST_SET_TABLE|TestSet_02_TEST_SET_IPV4", expected_map, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Delete on Yang Node Exercising Subtree-Xfmr and Virtual Table ++++++++++++") + + t.Log("\n\n+++++++++++++ Performing Get on Yang Node Exercising Subtree-Xfmr and Virtual Table ++++++++++++") + pre_req_map = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_03_TEST_SET_IPV6": map[string]interface{}{ + "ports@": "Eth_1"}}} + + loadDB(hostDBName, db.ConfigDB, pre_req_map) + expected_get_json := "{\"openconfig-test-xfmr:ingress-test-set\":[{\"config\":{\"set-name\":\"TestSet_03\",\"type\":\"openconfig-test-xfmr:TEST_SET_IPV6\"},\"set-name\":\"TestSet_03\",\"state\":{\"set-name\":\"TestSet_03\",\"type\":\"openconfig-test-xfmr:TEST_SET_IPV6\"},\"type\":\"openconfig-test-xfmr:TEST_SET_IPV6\"}]}" + url = "/openconfig-test-xfmr:test-xfmr/interfaces/interface[id=Eth_1]/ingress-test-sets/ingress-test-set[set-name=TestSet_03][type=TEST_SET_IPV6]" + t.Run("Test get on node exercising subtree-xfmr and virtual table.", processGetRequest(url, nil, expected_get_json, false)) + cleanuptbl = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_03_TEST_SET_IPV6": ""}} + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + t.Log("\n\n+++++++++++++ Done Performing Get on Yang Node Exercising Subtree-Xfmr and Virtual Table ++++++++++++") + */ } func Test_node_exercising_tableName_key_and_field_xfmr(t *testing.T) { @@ -98,8 +92,8 @@ func Test_node_exercising_tableName_key_and_field_xfmr(t *testing.T) { cleanuptbl = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_01_TEST_SET_IPV4": ""}} t.Run("Test set on node exercising Table-Name, Key-Xfmr and Field-Xfmr", processSetRequest(url, url_body_json, "POST", false, nil)) time.Sleep(1 * time.Second) - t.Run("Verify set on node exercising Table-Name, Key-Xfmr and Field-Xfmr", verifyDbResult(rclient, "TEST_SET_TABLE|TestSet_01_TEST_SET_IPV4", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) + t.Run("Verify set on node exercising Table-Name, Key-Xfmr and Field-Xfmr", verifyDbResult(rclient[hostDBName], "TEST_SET_TABLE|TestSet_01_TEST_SET_IPV4", expected_map, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Set on Yang Node Exercising Table-Name, Key-Xfmr and Field-Xfmr ++++++++++++") @@ -109,7 +103,7 @@ func Test_node_exercising_tableName_key_and_field_xfmr(t *testing.T) { "description": "Description : TestSet_01_description", "ports@": "Eth_0"}}} cleanuptbl = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_01_TEST_SET_IPV4": ""}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) time.Sleep(1 * time.Second) url = "/openconfig-test-xfmr:test-xfmr/test-sets/test-set[name=TestSet_01][type=TEST_SET_IPV4]/config/description" t.Run("Test delete on node exercising Table-Name, Key-Xfmr and Field-Xfmr", processDeleteRequest(url, false)) @@ -117,8 +111,8 @@ func Test_node_exercising_tableName_key_and_field_xfmr(t *testing.T) { expected_map = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_01_TEST_SET_IPV4": map[string]interface{}{ "type": "IPV4", "ports@": "Eth_0"}}} - t.Run("Verify delete on node exercising Table-Name, Key-Xfmr and Field-Xfmr", verifyDbResult(rclient, "TEST_SET_TABLE|TestSet_01_TEST_SET_IPV4", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) + t.Run("Verify delete on node exercising Table-Name, Key-Xfmr and Field-Xfmr", verifyDbResult(rclient[hostDBName], "TEST_SET_TABLE|TestSet_01_TEST_SET_IPV4", expected_map, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Delete on Yang Node Exercising Subtree-Xfmr and Virtual Table ++++++++++++") @@ -128,23 +122,26 @@ func Test_node_exercising_tableName_key_and_field_xfmr(t *testing.T) { "description": "Description : TestSet_03Description", "ports@": "Eth_3"}}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) expected_get_json := "{\"openconfig-test-xfmr:test-sets\":{\"test-set\":[{\"config\":{\"description\":\"TestSet_03Description\",\"name\":\"TestSet_03\",\"type\":\"openconfig-test-xfmr:TEST_SET_IPV6\"},\"name\":\"TestSet_03\",\"state\":{\"description\":\"TestSet_03Description\",\"name\":\"TestSet_03\",\"type\":\"openconfig-test-xfmr:TEST_SET_IPV6\"},\"type\":\"openconfig-test-xfmr:TEST_SET_IPV6\"}]}}" url = "/openconfig-test-xfmr:test-xfmr/test-sets" t.Run("Test get on node exercising Table-Name, Key-Xfmr and Field-Xfmr.", processGetRequest(url, nil, expected_get_json, false)) time.Sleep(1 * time.Second) cleanuptbl = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_03_TEST_SET_IPV6": ""}} - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("\n\n+++++++++++++ Done Performing Get on Yang Node Exercising Table-Name, Key-Xfmr and Field-Xfmr++++++++++++") } func Test_node_exercising_pre_xfmr_node(t *testing.T) { t.Log("\n\n+++++++++++++ Performing set on node exercising pre-xfmr ++++++++++++") - expected_err := tlerr.NotSupportedError{Format: "REPLACE not supported at this node."} - url := "/openconfig-test-xfmr:test-xfmr" - url_body_json := "{\"openconfig-test-xfmr:test-xfmr\":{ \"test-sets\": { \"test-set\": [ { \"name\": \"TestSet_03\", \"type\": \"TEST_SET_IPV4\", \"config\": { \"name\": \"TestSet_03\", \"type\": \"TEST_SET_IPV4\", \"description\": \"testSet_03 description\" } } ] }}}" + err_str := "REPLACE not supported at this node." + expected_err := tlerr.NotSupportedError{Format: err_str} + //expected_err := tlerr.NotSupported("REPLACE not supported at this node.") + url := "/openconfig-test-xfmr:test-xfmr/test-sets" + url_body_json := "{ \"openconfig-test-xfmr:test-sets\": { \"test-set\": [ { \"name\": \"TestSet_03\", \"type\": \"TEST_SET_IPV4\", \"config\": { \"name\": \"TestSet_03\", \"type\": \"TEST_SET_IPV4\", \"description\": \"testSet_03 description\" } } ] }}" t.Run("Test set on node exercising pre-xfmr.", processSetRequest(url, url_body_json, "PUT", true, expected_err)) t.Log("\n\n+++++++++++++ Done Performing set on node exercising pre-xfmr ++++++++++++") + } func Test_node_with_child_tableXfmr_keyXfmr_fieldNameXfmrs_nonConfigDB_data(t *testing.T) { @@ -155,7 +152,7 @@ func Test_node_with_child_tableXfmr_keyXfmr_fieldNameXfmrs_nonConfigDB_data(t *t t.Log("++++++++++++++ Test_set_on_node_with_child_table_key_field_xfmrs +++++++++++++") // Setup - Prerequisite - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) // Payload post_payload := "{\"openconfig-test-xfmr:test-sensor-group\":[ { \"id\" : \"test_group_1\", \"config\": { \"id\": \"test_group_1\", \"group-colors\": [ \"red,blue,green\" ] }, \"test-sensor-types\": { \"test-sensor-type\": [ { \"type\": \"sensora_testA\", \"config\": { \"type\": \"sensora_testA\", \"exclude-filter\": \"filterB\" } } ] } } ]}" @@ -164,11 +161,11 @@ func Test_node_with_child_tableXfmr_keyXfmr_fieldNameXfmrs_nonConfigDB_data(t *t t.Run("Set on Node having child table and field transformer mapping", processSetRequest(url, post_payload, "POST", false)) time.Sleep(1 * time.Second) - t.Run("Verify set on node with child table and field transformer", verifyDbResult(rclient, "TEST_SENSOR_GROUP|test_group_1", post_sensor_group_expected, false)) - t.Run("Verify set on node with child table and field transformer", verifyDbResult(rclient, "TEST_SENSOR_A_TABLE|test_group_1|sensor_type_a_testA", post_sensor_table_expected, false)) + t.Run("Verify set on node with child table and field transformer", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|test_group_1", post_sensor_group_expected, false)) + t.Run("Verify set on node with child table and field transformer", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_A_TABLE|test_group_1|sensor_type_a_testA", post_sensor_table_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_get_on_node_with_table_key_field_xfmrs_nonConfigDB_data +++++++++++++") @@ -178,338 +175,58 @@ func Test_node_with_child_tableXfmr_keyXfmr_fieldNameXfmrs_nonConfigDB_data(t *t url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=test_group_1]" // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) - loadDB(db.CountersDB, nonconfig_prereq) + loadDB(hostDBName, db.ConfigDB, prereq) + loadDB(hostDBName, db.CountersDB, nonconfig_prereq) get_expected := "{\"openconfig-test-xfmr:test-sensor-group\":[{\"config\":{\"color-hold-time\":10,\"group-colors\":[\"red\",\"blue\",\"green\"],\"id\":\"test_group_1\"},\"id\":\"test_group_1\",\"state\":{\"color-hold-time\":10,\"counters\":{\"frame-in\":12345,\"frame-out\":678910},\"group-colors\":[\"red\",\"blue\",\"green\"],\"id\":\"test_group_1\"},\"test-sensor-types\":{\"test-sensor-type\":[{\"config\":{\"exclude-filter\":\"filterB\",\"type\":\"sensora_testA\"},\"state\":{\"exclude-filter\":\"filterB\",\"type\":\"sensora_testA\"},\"type\":\"sensora_testA\"}]}}]}" t.Run("Verify_get_on_node_with_child_table_key_field_xfmrs", processGetRequest(url, nil, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) - unloadDB(db.CountersDB, nonconfig_prereq) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.CountersDB, nonconfig_prereq) t.Log("++++++++++++++ Test_delete_on_node_with_child_table_key_field_xfmrs +++++++++++++") url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups" // Setup - Prerequisite - None - unloadDB(db.ConfigDB, cleanuptbl) - loadDB(db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + loadDB(hostDBName, db.ConfigDB, prereq) delete_expected := make(map[string]interface{}) t.Run("Delete on node with child table, key and field xfmrs", processDeleteRequest(url, false)) time.Sleep(1 * time.Second) - t.Run("Verify delete on node with child table, key and field xfmrs", verifyDbResult(rclient, "TEST_SENSOR_GROUP|test_group_1", delete_expected, false)) - t.Run("Verify delete on node with child table, key and field xfmrs", verifyDbResult(rclient, "TEST_SENSOR_A_TABLE|test_group_1|sensor_type_a_testA", delete_expected, false)) - - // Teardown - unloadDB(db.ConfigDB, cleanuptbl) -} - -func Test_node_exercising_tableXfmr_virtual_table_and_validate_handler(t *testing.T) { - /* verify if replace at a higher level yang node happens correctly when replacing nodes having table-xfmr, virtual-table and validate handler annotation in child yang hierachy */ - prereq_ni_instance := map[string]interface{}{"TEST_VRF": map[string]interface{}{"default": map[string]interface{}{"enabled": "true"}, - "Vrf_01": map[string]interface{}{"enabled": "false"}, "Vrf_02": map[string]interface{}{"enabled": "false", "description": "Vrf_02 descrip"}, - "Vrf_03": map[string]interface{}{"enabled": "true"}}} - prereq_bgp := map[string]interface{}{"TEST_BGP_NETWORK_CFG": map[string]interface{}{"Vrf_01|22": map[string]interface{}{"backdoor": "true", "policy-name": "abcd"}, - "Vrf_01|33": map[string]interface{}{"backdoor": "false", "policy-name": "xyzefgh"}, - "Vrf_02|101": map[string]interface{}{"backdoor": "false"}}} - prereq_ospfv2_router := map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true", "write-multiplier": "2"}, - "Vrf_02": map[string]interface{}{"enabled": "true"}, - "Vrf_03": map[string]interface{}{"write-multiplier": "5"}}} - prereq_ospfv2_router_distribution := map[string]interface{}{"TEST_OSPFV2_ROUTER_DISTRIBUTION": map[string]interface{}{"Vrf_01|66": map[string]interface{}{"priority": "3"}, - "Vrf_01|98": map[string]interface{}{"priority": "56", "table-id": "4"}, "Vrf_03|79": map[string]interface{}{"priority": "7", "table-id": "74"}}} - - cleanuptbl := map[string]interface{}{"TEST_VRF": map[string]interface{}{"default": "", "Vrf_01": "", "Vrf_02": "", "Vrf_03": ""}, - "TEST_BGP_NETWORK_CFG": map[string]interface{}{"Vrf_01|22": "", "Vrf_01|33": "", "Vrf_02|101": "", "Vrf_02|55": ""}, - "TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": "", "Vrf_02": "", "Vrf_03": ""}, - "TEST_OSPFV2_ROUTER_DISTRIBUTION": map[string]interface{}{"Vrf_01|66": "", "Vrf_01|98": "", "Vrf_02|81": "", "Vrf_03|79": ""}} - - //Setup - loadDB(db.ConfigDB, prereq_ni_instance) - loadDB(db.ConfigDB, prereq_bgp) - loadDB(db.ConfigDB, prereq_ospfv2_router) - loadDB(db.ConfigDB, prereq_ospfv2_router_distribution) - - t.Log("+++++++++++++++++ Test replace at high level in yang hierachy involing table-xfmr, virtual-table and validate handler annotations +++++++++++++++") - url := "/openconfig-test-xfmr:test-xfmr/test-ni-instances/test-ni-instance" - //TODOswag - url_body_json := "{\"openconfig-test-xfmr:test-ni-instance\":[{\"ni-name\":\"default\"," + - "\"config\":{\"ni-name\":\"default\",\"enabled\":true}},{\"ni-name\":\"vrf-02" + - "\",\"config\":{\"ni-name\":\"vrf-02\",\"enabled\":true},\"test-protocols\":" + - "{\"test-protocol\":[{\"name\":\"ospfv2\",\"config\":{\"name\":\"ospfv2\"}," + - "\"ospfv2\":{\"global\":{\"config\":{\"enabled\":true}," + - "\"route-distribution-lists\":{\"route-distribution-list\":[{\"distribution" + - "-id\":81,\"config\":{\"distribution-id\":81,\"priority\":9,\"table-id\":67}" + - "}]}}}}]}},{\"ni-name\":\"vrf-01\",\"config\":{\"ni-name\":\"vrf-01\",\"enab" + - "led\":true,\"description\":\"01 descrip\"},\"test-protocols\":{\"test-pro" + - "tocol\":[{\"name\":\"bgp\",\"config\":{\"name\":\"bgp\"},\"bgp\":{\"network-cf" + - "gs\":{\"network-cfg\":[{\"network-id\":22,\"config\":{\"network-id\":22,\"poli" + - "cy-name\":\"defgh\",\"backdoor\":false}},{\"network-id\":33,\"config\":{\"netw" + - "ork-id\":33,\"policy-name\":\"fgh\"}}]}}},{\"name\":\"ospfv2\",\"config\":{" + - "\"name\":\"ospfv2\"},\"ospfv2\":{\"global\":{\"config\":{\"enabled\":true,\"w" + - "rite-multiplier\":3},\"route-distribution-lists\":{\"route-distribution-list" + - "\":[{\"distribution-id\":66,\"config\":{\"distribution-id\":66,\"priorit" + - "y\":6}}]}}}}]}}]}" - - empty_expected := map[string]interface{}{} - expected_ni_instance_default := map[string]interface{}{"TEST_VRF": map[string]interface{}{"default": map[string]interface{}{"enabled": "true"}}} - expected_ni_instance_vrf_01 := map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true", "description": "01 descrip"}}} - expected_ni_instance_vrf_02 := map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_02": map[string]interface{}{"enabled": "true"}}} - expected_bgp_vrf_01_22 := map[string]interface{}{"TEST_BGP_NETWORK_CFG": map[string]interface{}{"Vrf_01|22": map[string]interface{}{"backdoor": "false", "policy-name": "defgh"}}} - expected_bgp_vrf_01_33 := map[string]interface{}{"TEST_BGP_NETWORK_CFG": map[string]interface{}{"Vrf_01|33": map[string]interface{}{"policy-name": "fgh"}}} - expected_ospfv2_router_vrf_01 := map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true", "write-multiplier": "3"}}} - expected_ospfv2_router_vrf_02 := map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_02": map[string]interface{}{"enabled": "true"}}} - expected_ospfv2_router_distribution_vrf_01_66 := map[string]interface{}{"TEST_OSPFV2_ROUTER_DISTRIBUTION": map[string]interface{}{"Vrf_01|66": map[string]interface{}{"priority": "6"}}} - expected_ospfv2_router_distribution_vrf_02_81 := map[string]interface{}{"TEST_OSPFV2_ROUTER_DISTRIBUTION": map[string]interface{}{"Vrf_02|81": map[string]interface{}{"priority": "9", "table-id": "67"}}} - t.Run("Replace at high level in yang hierachy involing table-xfmr, virtual-table and validate handler annotations.", processSetRequest(url, url_body_json, "PUT", false)) - time.Sleep(1 * time.Second) - verifyDbResultArray := [15]verifyDbResultData{ - {test: "Verify default ni-instance in request payload is present in db with data matching payload.", db_key: "TEST_VRF|default", db_result: expected_ni_instance_default}, - {test: "Verify vrf_01 ni-instance in request payload is present in db with data matching payload.", db_key: "TEST_VRF|Vrf_01", db_result: expected_ni_instance_vrf_01}, - {test: "Verify vrf_02 ni-instance in request payload is present in db with data matching payload.", db_key: "TEST_VRF|Vrf_02", db_result: expected_ni_instance_vrf_02}, - {test: "Verify vrf_03 ni-instance absent in request payload is deleted from db.", db_key: "TEST_VRF|Vrf_03", db_result: empty_expected}, - {test: "Verify bgp instance(vrf-01|22) assocaited with ni-instance in request is present in db with data matching payload.", db_key: "TEST_BGP_NETWORK_CFG|Vrf_01|22", db_result: expected_bgp_vrf_01_22}, - {test: "Verify bgp instance(vrf-01|33) assocaited with ni-instance in request is present in db with data matching payload.", db_key: "TEST_BGP_NETWORK_CFG|Vrf_01|33", db_result: expected_bgp_vrf_01_33}, - {test: "Verify bgp instance(vrf-02|101) absent in request payload is deleted from db.", db_key: "TEST_BGP_NETWORK_CFG|Vrf_02|101", db_result: empty_expected}, - {test: "Verify ospfv2 global/router(vrf-01) assocaited with ni-instance in request is present in db with data matching payload.", db_key: "TEST_OSPFV2_ROUTER|Vrf_01", db_result: expected_ospfv2_router_vrf_01}, - {test: "Verify ospfv2 global/router(vrf-02) assocaited with ni-instance in request is present in db with data matching payload.", db_key: "TEST_OSPFV2_ROUTER|Vrf_02", db_result: expected_ospfv2_router_vrf_02}, - {test: "Verify ospfv2 global/router(vrf-03) absent in request payload is deleted from db.", db_key: "TEST_OSPFV2_ROUTER|Vrf_03", db_result: empty_expected}, - {test: "Verify ospfv2 router distribution(vrf-01|66) assocaited with ni-instance in request is present in db with data matching payload.", db_key: "TEST_OSPFV2_ROUTER_DISTRIBUTION|Vrf_01|66", db_result: expected_ospfv2_router_distribution_vrf_01_66}, - {test: "Verify ospfv2 router distribution(vrf-01|98) absent in request payload is deleted from db.", db_key: "TEST_OSPFV2_ROUTER_DISTRIBUTION|Vrf_01|98", db_result: empty_expected}, - {test: "Verify ospfv2 router distribution(vrf-02|81) assocaited with ni-instance in request is created in db with data matching payload.", db_key: "TEST_OSPFV2_ROUTER_DISTRIBUTION|Vrf_02|81", db_result: expected_ospfv2_router_distribution_vrf_02_81}, - {test: "Verify ospfv2 router distribution(vrf-03|79) absent in request payload is deleted from db.", db_key: "TEST_OSPFV2_ROUTER_DSTRIBUTION|Vrf_03|79", db_result: empty_expected}, - } - time.Sleep(1 * time.Second) - for _, data := range verifyDbResultArray { - t.Run(data.test, verifyDbResult(rclient, data.db_key, data.db_result, false)) - } - //Tear down - unloadDB(db.ConfigDB, cleanuptbl) - - /* verify if get like traversal happens correctly when deleting a node having table-xfmr, virtual-table and validate handler annotation in child yang hierachy */ - t.Log("+++++++++++++++++ Test delete in yang hierachy involing table-xfmr, virtual-table and validate handler annotations +++++++++++++++") - //Setup - loadDB(db.ConfigDB, prereq_ni_instance) - loadDB(db.ConfigDB, prereq_bgp) - loadDB(db.ConfigDB, prereq_ospfv2_router) - loadDB(db.ConfigDB, prereq_ospfv2_router_distribution) - url = "/openconfig-test-xfmr:test-xfmr/test-ni-instances/test-ni-instance[ni-name=vrf-01]/test-protocols" - expected_ni_instance_vrf_01 = map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "false"}}} - expected_ni_instance_default = map[string]interface{}{"TEST_VRF": map[string]interface{}{"default": map[string]interface{}{"enabled": "true"}}} - expected_ni_instance_vrf_02 = map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_02": map[string]interface{}{"enabled": "false", "description": "Vrf_02 descrip"}}} - expected_ni_instance_vrf_03 := map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_03": map[string]interface{}{"enabled": "true"}}} - expected_bgp := map[string]interface{}{"TEST_BGP_NETWORK_CFG": map[string]interface{}{"Vrf_02|101": map[string]interface{}{"backdoor": "false"}}} - expected_ospfv2_router_vrf_02 = map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_02": map[string]interface{}{"enabled": "true"}}} - expected_ospfv2_router_vrf_03 := map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_03": map[string]interface{}{"write-multiplier": "5"}}} - expected_ospfv2_router_distribution := map[string]interface{}{"TEST_OSPFV2_ROUTER_DISTRIBUTION": map[string]interface{}{"Vrf_03|79": map[string]interface{}{"priority": "7", "table-id": "74"}}} - t.Run("Delete in yang hierachy involing table-xfmr, virtual-table and validate handler annotations.", processDeleteRequest(url, false)) - time.Sleep(1 * time.Second) - verifyDbResultList := [13]verifyDbResultData{ - {test: "Verify ni-instance in request URL(vrf-01) is not deleted from db since URL points to child node.", db_key: "TEST_VRF|Vrf_01", db_result: expected_ni_instance_vrf_01}, - {test: "Verify default ni-instance not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_VRF|default", db_result: expected_ni_instance_default}, - {test: "Verify Vrf_02 ni-instance not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_VRF|Vrf_02", db_result: expected_ni_instance_vrf_02}, - {test: "Verify Vrf_03 ni-instance not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_VRF|Vrf_03", db_result: expected_ni_instance_vrf_03}, - {test: "Verify delete of bgp instance(vrf-01|22) assocaited with ni-instance in request URL is deleted from db.", db_key: "TEST_BGP_NETWORK_CFG|Vrf_01|22", db_result: empty_expected}, - {test: "Verify delete of bgp instance(vrf-01|33) assocaited with ni-instance in request URL is deleted from db.", db_key: "TEST_BGP_NETWORK_CFG|Vrf_01|33", db_result: empty_expected}, - {test: "Verify bgp instance(vrf-02|101) not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_BGP_NETWORK_CFG|Vrf_02|101", db_result: expected_bgp}, - {test: "Verify ospfv2-global/router instance(vrf-01) assocaited with ni-instance in request URL is deleted from db.", db_key: "TEST_OSPFV2_ROUTER|Vrf_01", db_result: empty_expected}, - {test: "Verify ospfv2-global/router instance(vrf-02) not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_OSPFV2_ROUTER|Vrf_02", - db_result: expected_ospfv2_router_vrf_02}, - {test: "Verify ospfv2-global/router instance(vrf-03) not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_OSPFV2_ROUTER|Vrf_03", - db_result: expected_ospfv2_router_vrf_03}, - {test: "Verify ospfv2-router-distribution instance(vrf-01|66) assocaited with ni-instance in request URL is deleted from db.", db_key: "TEST_OSPFV2_ROUTER_DISTRIBUTION|Vrf_01|66", - db_result: empty_expected}, - {test: "Verify ospfv2-router-distribution instance(vrf-01|98) assocaited with ni-instance in request URL is deleted from db.", db_key: "TEST_OSPFV2_ROUTER_DISTRIBUTION|Vrf_01|98", - db_result: empty_expected}, - {test: "Verify ospfv2-router-distribution instance(vrf-03|79) not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_OSPFV2_ROUTER_DISTRIBUTION|Vrf_03|79", - db_result: expected_ospfv2_router_distribution}, - } - for _, data := range verifyDbResultList { - t.Run(data.test, verifyDbResult(rclient, data.db_key, data.db_result, false)) - } - // Teardown - unloadDB(db.ConfigDB, cleanuptbl) -} - -func Test_node_exercising_non_table_owner_annotation(t *testing.T) { - prereq := map[string]interface{}{"DEVICE_ZONE_METADATA": map[string]interface{}{"local-zonehost": map[string]interface{}{"metric": "2", "hold-interval": "97", - "hwsku": "testhwsku", "deployment-id": "834"}}} - cleanuptbl := map[string]interface{}{"DEVICE_ZONE_METADATA": map[string]interface{}{"local-zonehost": ""}} - expected_map := map[string]interface{}{"DEVICE_ZONE_METADATA": map[string]interface{}{"local-zonehost": map[string]interface{}{"metric": "32", "hwsku": "testhwsku", "deployment-id": "834"}}} - url := "/openconfig-test-xfmr:test-xfmr/test-sets/system-zone-device-data/config" - url_body_json := "{\"openconfig-test-xfmr:config\":{\"metric\":32}}" - t.Log("++++++++++++++ Test_replace_on_node_exercising_non_table_owner_annotation +++++++++++++") - // Setup - loadDB(db.ConfigDB, prereq) - t.Run("Replace on node exercising non table owner annotation.", processSetRequest(url, url_body_json, "PUT", false, nil)) - time.Sleep(1 * time.Second) - t.Run("Verify replace on node exercising non table owner annotation.", verifyDbResult(rclient, "DEVICE_ZONE_METADATA|local-zonehost", expected_map, false)) - t.Log("++++++++++++++ Test_delete_on_node_exercising_non_table_owner_annotation +++++++++++++") - //TearDown - unloadDB(db.ConfigDB, cleanuptbl) - - t.Log("++++++++++++++ Test_delete_on_node_exercising_non_table_owner_annotation +++++++++++++") - url = "/openconfig-test-xfmr:test-xfmr/test-sets/system-zone-device-data" - expected_map = map[string]interface{}{"DEVICE_ZONE_METADATA": map[string]interface{}{"local-zonehost": map[string]interface{}{"hwsku": "testhwsku", "deployment-id": "834"}}} - // Setup - loadDB(db.ConfigDB, prereq) - t.Run("Delete on node exercising non table owner annotation.", processDeleteRequest(url, false)) - time.Sleep(1 * time.Second) - t.Run("Verify delete on node exercising non table owner annotation.", verifyDbResult(rclient, "DEVICE_ZONE_METADATA|local-zonehost", expected_map, false)) - // TearDown - unloadDB(db.ConfigDB, cleanuptbl) -} - -func Test_node_exercising_subset_of_fields_in_mapped_table(t *testing.T) { - prereq_ni_instance := map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true"}}} - prereq_ospfv2_router := map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true", "write-multiplier": "2", - "initial-delay": "40", "max-delay": "100"}}} - cleanuptbl := map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_01": ""}, - "TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": ""}} - expected_ospfv2_router := map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true", "write-multiplier": "2", - "initial-delay": "50"}}} - url := "/openconfig-test-xfmr:test-xfmr/test-ni-instances/test-ni-instance[ni-name=vrf-01]/test-protocols/test-protocol[name=ospfv2]/ospfv2/global/timers/config" - url_body_json := "{\"openconfig-test-xfmr:config\":{\"initial-delay\":50}}" - // Setup - loadDB(db.ConfigDB, prereq_ni_instance) - loadDB(db.ConfigDB, prereq_ospfv2_router) - t.Log("++++++++++++++ Test_replace_on_node_exercising_subset_of_fields_in_mapped_table +++++++++++++") - t.Run("Replace on node exercising subset of fields in mapped table.", processSetRequest(url, url_body_json, "PUT", false, nil)) - time.Sleep(1 * time.Second) - t.Run("Verify replace on node exercising subset of fields in mapped table.", verifyDbResult(rclient, "TEST_OSPFV2_ROUTER|Vrf_01", expected_ospfv2_router, false)) - //TearDown - unloadDB(db.ConfigDB, cleanuptbl) - - t.Log("++++++++++++++ Test_delete_on_node_exercising_subset_of_fields_in_mapped_table +++++++++++++") - expected_ospfv2_router = map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true", "write-multiplier": "2"}}} - // Setup - loadDB(db.ConfigDB, prereq_ni_instance) - loadDB(db.ConfigDB, prereq_ospfv2_router) - t.Run("Delete on node exercising subset of fields in mapped table.", processDeleteRequest(url, false)) - time.Sleep(1 * time.Second) - t.Run("Verify delete on node exercising subset of fields in mapped table.", verifyDbResult(rclient, "TEST_OSPFV2_ROUTER|Vrf_01", expected_ospfv2_router, false)) - // TearDown - unloadDB(db.ConfigDB, cleanuptbl) -} - -func test_node_exercising_db_parent_child_nonkey_leafref_relationship(t *testing.T) { - /* oc yang hierarchy parent node's db table mapping has nonkey leafref db child relationship to a - node's db table mapping in the child hierachy & siblings yang nodes having similar relationship */ - prereq := map[string]interface{}{"TEST_NTP": map[string]interface{}{"global": map[string]interface{}{"trusted-key@": "65", "auth-enabled": "true"}}, - "TEST_NTP_AUTHENTICATION_KEY": map[string]interface{}{"65": map[string]interface{}{"key-type": "MD5", "key-value": "0x635352e91dd9ddf2ed9542db848d3b31"}}, - "TEST_NTP_SERVER": map[string]interface{}{"24": map[string]interface{}{"key-id": "65", "min-poll": "3"}}} - cleanuptbl := map[string]interface{}{"TEST_NTP": map[string]interface{}{"global": ""}, "TEST_NTP_AUTHENTICATION_KEY": map[string]interface{}{"68": "", "65": ""}, - "TEST_NTP_SERVER": map[string]interface{}{"24": ""}} - empty_expected := make(map[string]interface{}) - expected_test_ntp := map[string]interface{}{"TEST_NTP": map[string]interface{}{"global": map[string]interface{}{"auth-enabled": "false"}}} - expected_test_ntp_keys := map[string]interface{}{"TEST_NTP_AUTHENTICATION_KEY": map[string]interface{}{"68": map[string]interface{}{"key-type": "MD5", - "key-value": "0x635352e91dd9ddf2ed9542db848d3b31"}}} - - // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) - t.Log("++++++++++++++ Test_replace_on_node_exercising_db_parent_child_nonkey_leafref_relationship_error_case +++++++++++++") - url := "/openconfig-test-xfmr:test-xfmr/test-ntp/test-ntp-keys" - url_body_json := "{\"openconfig-test-xfmr:test-ntp-keys\":{\"test-ntp-key\":[{\"key-id\":67,\"config\":{\"key-id\":67,\"key-type\":\"TEST_NTP_AUTH_MD5\"," + - "\"key-value\":\"0x635352e91dd9ddf2ed9542db848d3b31\"}}]}}" - experr := tlerr.TranslibCVLFailure{Code: 1002, CVLErrorInfo: cvl.CVLErrorInfo{ErrCode: 1002, CVLErrDetails: "Config Validation Semantic Error", - Msg: "Validation failed for Delete operation, given instance is in use", ConstraintErrMsg: "Validation failed for Delete operation, given instance is in use", - TableName: "TEST_NTP_AUTHENTICATION_KEY", Keys: []string{"65"}, Field: "", Value: "", ErrAppTag: ""}} - t.Run("Test replace of child yang node having parent-child non-key leafref relationship with parent yang node(error-case).", processSetRequest(url, url_body_json, - "PUT", true, experr)) - - t.Log("++++++++++++++ Test_replace_on_node_exercising_db_parent_child_nonkey_leafref_relationship +++++++++++++") - t.Run("Test replace on node exersising db parent child nonkey leafref relationship and containing siblings with same relationship.", processSetRequest(url, url_body_json, - "PUT", false)) - url = "/openconfig-test-xfmr:test-xfmr/test-ntp" - url_body_json = "{\"openconfig-test-xfmr:test-ntp\":{\"config\":{\"enable-ntp-auth\": false}, \"test-ntp-keys\":{\"test-ntp-key\":[{\"key-id\":68,\"config\":{\"key-id\":68, \"key-type\":\"TEST_NTP_AUTH_MD5\"," + - " \"key-value\":\"0x635352e91dd9ddf2ed9542db848d3b31\"}}]}}}" - time.Sleep(1 * time.Second) - verifyDbResultArray := [4]verifyDbResultData{ - {test: "Verify replace of yang node having parent-child non-key leafref relationship with sibling yang node matches to request payload.(test-ntp-server|24)", - db_key: "TEST_NTP_SERVER|24", db_result: empty_expected}, - {test: "Verify replace of yang node having parent-child non-key leafref relationship with child yang node matches to request payload.(test-ntp|global)", - db_key: "TEST_NTP|global", db_result: expected_test_ntp}, - {test: "Verify replace of child yang node having parent-child non-key leafref relationship with parent yang node matches to request payload.(test-ntp-key|65)", - db_key: "TEST_NTP_AUTHENTICATION_KEY|65", db_result: empty_expected}, - {test: "Verify replace of child yang node having parent-child non-key leafref relationship with parent yang node matches to request payload.(test-ntp-key|68)", - db_key: "TEST_NTP_AUTHENTICATION_KEY|68", db_result: expected_test_ntp_keys}, - } - for _, data := range verifyDbResultArray { - t.Run(data.test, verifyDbResult(rclient, data.db_key, data.db_result, false)) - } - // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + t.Run("Verify delete on node with child table, key and field xfmrs", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|test_group_1", delete_expected, false)) + t.Run("Verify delete on node with child table, key and field xfmrs", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_A_TABLE|test_group_1|sensor_type_a_testA", delete_expected, false)) - t.Log("++++++++++++++ Test_delete_on_node_exercising_db_parent_child_nonkey_leafref_relationship +++++++++++++") - url = "/openconfig-test-xfmr:test-xfmr/test-ntp/test-ntp-keys" - experr = tlerr.TranslibCVLFailure{Code: 1002, CVLErrorInfo: cvl.CVLErrorInfo{ErrCode: 1002, CVLErrDetails: "Config Validation Semantic Error", - Msg: "Validation failed for Delete operation, given instance is in use", ConstraintErrMsg: "Validation failed for Delete operation, given instance is in use", - TableName: "TEST_NTP_AUTHENTICATION_KEY", Keys: []string{"65"}, Field: "", Value: "", ErrAppTag: ""}} - // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) - url = "/openconfig-test-xfmr:test-xfmr/test-ntp/test-ntp-keys" - t.Run("Test delete of child yang node having parent-child non-key leafref relationship with parent yang node(error-case).", processDeleteRequest(url, true, experr)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) } -func Test_leaf_node(t *testing.T) { +func Test_delete_on_node_with_default_value(t *testing.T) { - /* Test delete on leaf node that has a yang default */ cleanuptbl := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"test_group_1": ""}} url := "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=test_group_1]/config/color-hold-time" prereq := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"test_group_1": map[string]interface{}{"colors@": "red,blue,green", "color-hold-time": "30"}}} - t.Log("++++++++++++++ Test_delete_on_leaf_node_with_default_value_when_mapped_instance_exists_in_db +++++++++++++") - // Setup - unloadDB(db.ConfigDB, cleanuptbl) - loadDB(db.ConfigDB, prereq) + t.Log("++++++++++++++ Test_delete_on_node_with_default_value +++++++++++++") + + // Setup - Prerequisite - None + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + loadDB(hostDBName, db.ConfigDB, prereq) + + // Payload del_sensor_group_expected := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"test_group_1": map[string]interface{}{"colors@": "red,blue,green", "color-hold-time": "10"}}} - t.Run("Delete on leaf node having default value when mapped instance exists in db.", processDeleteRequest(url, false)) - time.Sleep(1 * time.Second) - t.Run("Verify delete on leaf node with default value resets to default", verifyDbResult(rclient, "TEST_SENSOR_GROUP|test_group_1", del_sensor_group_expected, false)) - // Teardown - unloadDB(db.ConfigDB, cleanuptbl) - - t.Log("++++++++++++++ Test_delete_on_leaf_node_with_default_value_when_mapped_instance_does_not_exist_db +++++++++++++") //table mapping to container - cleanuptbl = map[string]interface{}{"TRANSPORT_ZONE": map[string]interface{}{"transport-host": ""}} - empty_expected := make(map[string]interface{}) - // Setup - unloadDB(db.ConfigDB, cleanuptbl) - url = "/openconfig-test-xfmr:test-xfmr/test-sets/transport-zone" - t.Run("Delete on leaf node having default value when mapped instance doesn't exists in db and is annotated to a container.", processDeleteRequest(url, false)) - time.Sleep(1 * time.Second) - t.Run("Verify delete on leaf node with default value doesn't reset to default creating an instance in DB when mapped instance is annotated to a container.", - verifyDbResult(rclient, "TRANSPORT_ZONE|transport-host", empty_expected, false)) - t.Log("++++++++++++++ Test_delete_on_leaf_node_without_default_value +++++++++++++") - cleanuptbl = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": ""}} - prereq = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "testdescription"}}} - expected_map := map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode"}}} - url = "/openconfig-test-xfmr:test-xfmr/global-sensor/description" - //Setup - loadDB(db.ConfigDB, prereq) - t.Run("Delete on leaf node without default value", processDeleteRequest(url, false)) + t.Run("Delete on node having default value", processDeleteRequest(url, false)) time.Sleep(1 * time.Second) - t.Run("Verify delete on leaf node without default value", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", expected_map, false)) - // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + t.Run("Verify delete on node with default value", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|test_group_1", del_sensor_group_expected, false)) - t.Log("++++++++++++++ Test_replace_targeted_on_leaf_node_updates_its_value +++++++++++++") - //Setup - loadDB(db.ConfigDB, prereq) - url = "/openconfig-test-xfmr:test-xfmr/global-sensor/description" - url_body_json := "{ \"openconfig-test-xfmr:description\": \"NewTestDescription\"}" - expected_map = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "NewTestDescription"}}} - t.Run("Replace targeted on leaf node updates its value", processSetRequest(url, url_body_json, "PUT", false, nil)) - time.Sleep(1 * time.Second) - t.Run("Verify replace targeted on leaf node updates its value.", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", expected_map, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) } func Test_post_xfmr(t *testing.T) { @@ -521,8 +238,8 @@ func Test_post_xfmr(t *testing.T) { t.Log("++++++++++++++ Test_post_xfmr +++++++++++++") // Setup - Prerequisite - unloadDB(db.ConfigDB, cleanuptbl) - loadDB(db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + loadDB(hostDBName, db.ConfigDB, prereq) patch_payload := "{ \"openconfig-test-xfmr:color-hold-time\": 50}" patch_expected := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"test_group_1": map[string]interface{}{"colors@": "red,blue,green", "color-hold-time": "50"}}} @@ -530,10 +247,10 @@ func Test_post_xfmr(t *testing.T) { t.Run("Test_post_xfmr", processSetRequest(url, patch_payload, "PATCH", false)) time.Sleep(1 * time.Second) - t.Run("Verify Test_post_xfmr", verifyDbResult(rclient, "TEST_SENSOR_GROUP|test_group_1", patch_expected, false)) - t.Run("Verify Test_post_xfmr", verifyDbResult(rclient, "TEST_SENSOR_A_TABLE|test_group_1|sensor_type_a_post50", post_expected, false)) + t.Run("Verify Test_post_xfmr", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|test_group_1", patch_expected, false)) + t.Run("Verify Test_post_xfmr", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_A_TABLE|test_group_1|sensor_type_a_post50", post_expected, false)) - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) } func Test_sonic_yang_node_operations(t *testing.T) { @@ -545,8 +262,8 @@ func Test_sonic_yang_node_operations(t *testing.T) { t.Log("++++++++++++++ Test_set_on_sonic_table_yang_node +++++++++++++") // Setup - Prerequisite - unloadDB(db.ConfigDB, cleanuptbl) - loadDB(db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + loadDB(hostDBName, db.ConfigDB, prereq) // Payload post_payload := "{ \"sonic-test-xfmr:TEST_SENSOR_A_TABLE_LIST\": [ { \"id\": \"sensor_id_123\", \"type\": \"sensor_type_a_123\", \"exclude_filter\": \"filter_123\", \"description_a\": \"description test field for sensor A table\" } ]}" @@ -554,10 +271,10 @@ func Test_sonic_yang_node_operations(t *testing.T) { t.Run("Set on sonic table yang node", processSetRequest(url, post_payload, "POST", false)) time.Sleep(1 * time.Second) - t.Run("Verify set on sonic table yang node", verifyDbResult(rclient, "TEST_SENSOR_A_TABLE|sensor_id_123|sensor_type_a_123", post_sensor_table_expected, false)) + t.Run("Verify set on sonic table yang node", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_A_TABLE|sensor_id_123|sensor_type_a_123", post_sensor_table_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_delete_on_sonic_module +++++++++++++") @@ -567,20 +284,20 @@ func Test_sonic_yang_node_operations(t *testing.T) { prereq = map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"test_group_1": map[string]interface{}{"colors@": "red,blue,green", "color-hold-time": "30"}}, "TEST_SENSOR_A_TABLE": map[string]interface{}{"test_group_1|sensor_type_a_testA": map[string]interface{}{"test_group_1|sensor_type_a_testA": map[string]interface{}{"exclude_filter": "filter_filterB"}}}, "TEST_SENSOR_B_TABLE": map[string]interface{}{"test_group_1|sensor_type_b_testB": map[string]interface{}{"exclude_filter": "filter_filterB"}}, "TEST_SET_TABLE": map[string]interface{}{"quert_TEST_SET_IPV4": map[string]interface{}{"type": "IPV4"}}} // Setup - Prerequisite - unloadDB(db.ConfigDB, cleanuptbl) - loadDB(db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + loadDB(hostDBName, db.ConfigDB, prereq) delete_expected := make(map[string]interface{}) t.Run("Delete on sonic module", processDeleteRequest(url, false)) time.Sleep(1 * time.Second) - t.Run("Verify delete on sonic module table1", verifyDbResult(rclient, "TEST_SENSOR_GROUP|test_group_1", delete_expected, false)) - t.Run("Verify delete on sonic module table2", verifyDbResult(rclient, "TEST_SENSOR_A_TABLE|test_group_1|sensor_type_a_testA", delete_expected, false)) - t.Run("Verify delete on sonic module table3", verifyDbResult(rclient, "TEST_SENSOR_B_TABLE|test_group_1|sensor_type_b_testB", delete_expected, false)) - t.Run("Verify delete on sonic module table4", verifyDbResult(rclient, "TEST_SET_TABLE|quert_TEST_SET_IPV4", delete_expected, false)) + t.Run("Verify delete on sonic module table1", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|test_group_1", delete_expected, false)) + t.Run("Verify delete on sonic module table2", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_A_TABLE|test_group_1|sensor_type_a_testA", delete_expected, false)) + t.Run("Verify delete on sonic module table3", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_B_TABLE|test_group_1|sensor_type_b_testB", delete_expected, false)) + t.Run("Verify delete on sonic module table4", verifyDbResult(rclient[hostDBName], "TEST_SET_TABLE|quert_TEST_SET_IPV4", delete_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_get_on_sonic_table_with_key_xfmr +++++++++++++") @@ -589,13 +306,13 @@ func Test_sonic_yang_node_operations(t *testing.T) { url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_SENSOR_MODE_TABLE" // Setup - Prerequisite - loadDB(db.CountersDB, prereq) + loadDB(hostDBName, db.CountersDB, prereq) get_expected := "{\"sonic-test-xfmr:TEST_SENSOR_MODE_TABLE\":{\"TEST_SENSOR_MODE_TABLE_LIST\":[{\"description\":\"Test sensor mode\",\"id\":3543,\"mode\":\"mode:testsensor123\"}]}}" t.Run("Get on Sonic table with key xfmr", processGetRequest(url, nil, get_expected, false)) // Teardown - unloadDB(db.CountersDB, cleanuptbl) + unloadDB(hostDBName, db.CountersDB, cleanuptbl) } func Test_leaflist_node(t *testing.T) { @@ -608,12 +325,12 @@ func Test_leaflist_node(t *testing.T) { "colors@": "red,green"}}} expected_map = map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_01": map[string]interface{}{"colors@": "red,green,black"}}} cleanuptbl = map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_01": ""}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) time.Sleep(1 * time.Second) t.Run("Test patch on leaf-list.", processSetRequest(url, url_body_json, "PATCH", false, nil)) time.Sleep(1 * time.Second) - t.Run("Verify patch on leaf-list.", verifyDbResult(rclient, "TEST_SENSOR_GROUP|sensor_group_01", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) + t.Run("Verify patch on leaf-list.", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|sensor_group_01", expected_map, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Patch/Update on Yang leaf-list Node demonstrating leaf-list contents merge ++++++++++++") @@ -624,34 +341,14 @@ func Test_leaflist_node(t *testing.T) { "colors@": "red,green"}}} expected_map = map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_01": map[string]interface{}{"colors@": "blue,yellow"}}} cleanuptbl = map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_01": ""}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) time.Sleep(1 * time.Second) t.Run("Test replace on leaf-list.", processSetRequest(url, url_body_json, "PUT", false, nil)) time.Sleep(1 * time.Second) - t.Run("Verify replace on leaf-list.", verifyDbResult(rclient, "TEST_SENSOR_GROUP|sensor_group_01", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) + t.Run("Verify replace on leaf-list.", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|sensor_group_01", expected_map, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Put/Replace on Yang leaf-list Node demonstrating leaf-list contents swap ++++++++++++") - - t.Log("\n\n+++++++++++++ Performing Delete on Yang leaf-list Node - demonstrating specific leaf-list instance deletion & complete leaf-list deletion ++++++++++++++") - url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=sensor_group_01]/config/group-colors[group-colors=blue]" - pre_req_map = map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_01": map[string]interface{}{ - "colors@": "red,blue,green", "color-hold-time": "30"}}} - expected_map = map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_01": map[string]interface{}{"colors@": "red,green", "color-hold-time": "30"}}} - cleanuptbl = map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_01": ""}} - loadDB(db.ConfigDB, pre_req_map) - time.Sleep(1 * time.Second) - t.Run("Test specific leaf-list instance deletion.", processDeleteRequest(url, false)) - time.Sleep(1 * time.Second) - t.Run("Verify specific leaf-list instance deletion.", verifyDbResult(rclient, "TEST_SENSOR_GROUP|sensor_group_01", expected_map, false)) - time.Sleep(1 * time.Second) - url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=sensor_group_01]/config/group-colors" - expected_map = map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_01": map[string]interface{}{"color-hold-time": "30"}}} - t.Run("Test complete leaf-list attribute deletion.", processDeleteRequest(url, false)) - time.Sleep(1 * time.Second) - t.Run("Verify complete leaf-list attribute deletion.", verifyDbResult(rclient, "TEST_SENSOR_GROUP|sensor_group_01", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) - t.Log("\n\n+++++++++++++ Performing Delete on Yang leaf-list Node instance demonstrating specific leaf-list instance deletion ++++++++++++") } func Test_node_exercising_singleton_container_and_keyname_mapping(t *testing.T) { @@ -663,12 +360,12 @@ func Test_node_exercising_singleton_container_and_keyname_mapping(t *testing.T) url_body_json = "{ \"openconfig-test-xfmr:mode\": \"testmode\", \"openconfig-test-xfmr:description\": \"testdescription\"}" expected_map = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "testdescription"}}} cleanuptbl = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": ""}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) time.Sleep(1 * time.Second) t.Run("Test set on yang node exercising mapping to sonic singleton conatiner and key-name.", processSetRequest(url, url_body_json, "POST", false, nil)) time.Sleep(1 * time.Second) - t.Run("Verify set on yang node exercising mapping to sonic-yang singleton conatiner and key-name.", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) + t.Run("Verify set on yang node exercising mapping to sonic-yang singleton conatiner and key-name.", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", expected_map, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Set on Yang Node Exercising Mapping to Sonic-Yang Singleton Container and Key-name ++++++++++++") @@ -676,15 +373,15 @@ func Test_node_exercising_singleton_container_and_keyname_mapping(t *testing.T) pre_req_map = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{ "mode": "testmode", "description": "testdescription"}}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) time.Sleep(1 * time.Second) url = "/openconfig-test-xfmr:test-xfmr/global-sensor/description" t.Run("Test delete on node exercising mapping to sonic-yang singleton conatiner and key-name.", processDeleteRequest(url, false)) time.Sleep(1 * time.Second) expected_map = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{ "mode": "testmode"}}} - t.Run("Verify delete on node exercising mapping to sonic-yang singleton conatiner and key-name.", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) + t.Run("Verify delete on node exercising mapping to sonic-yang singleton conatiner and key-name.", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", expected_map, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Delete on Yang Node Exercising Mapping to Sonic-Yang Singleton Container and Key-name ++++++++++++") @@ -692,12 +389,12 @@ func Test_node_exercising_singleton_container_and_keyname_mapping(t *testing.T) pre_req_map = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{ "mode": "testmode", "description": "testdescription"}}} - loadDB(db.ConfigDB, pre_req_map) + loadDB(hostDBName, db.ConfigDB, pre_req_map) expected_get_json := "{\"openconfig-test-xfmr:global-sensor\": {\"description\": \"testdescription\",\"mode\": \"testmode\"}}" url = "/openconfig-test-xfmr:test-xfmr/global-sensor" t.Run("Test get on node exercising mapping to sonic-yang singleton conatiner and key-name.", processGetRequest(url, nil, expected_get_json, false)) time.Sleep(1 * time.Second) - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("\n\n+++++++++++++ Done Performing Get on Yang Node Exercising mapping to sonic-yang singleton conatiner and key-name ++++++++++++") } @@ -708,22 +405,22 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { t.Log("++++++++++++++ Test_create_on_sonic_singleton_container_yang_node +++++++++++++") url := "/sonic-test-xfmr:sonic-test-xfmr/TEST_SENSOR_GLOBAL" // Setup - Prerequisite - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) // Payload post_payload := "{ \"sonic-test-xfmr:global_sensor\": { \"mode\": \"testmode\", \"description\": \"testdescp\" }}" post_sensor_global_expected := map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "testdescp", "reset_time": 5}}} t.Run("Create on singleton sonic table yang node", processSetRequest(url, post_payload, "POST", false)) time.Sleep(1 * time.Second) - t.Run("Verify Create on singleton sonic table yang node", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", post_sensor_global_expected, false)) + t.Run("Verify Create on singleton sonic table yang node", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", post_sensor_global_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_create_on_sonic_node_having_singleton_container_sibling_list +++++++++++++") url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_SENSOR_GLOBAL" // Setup - Prerequisite - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) // Payload post_payload = "{ \"sonic-test-xfmr:global_sensor\": { \"mode\": \"testmode\", \"description\": \"testdescp\" }, \"sonic-test-xfmr:TEST_SENSOR_GLOBAL_LIST\": [{\"device_name\": \"test_device\", \"device_id\": 32,\"device_status\": \"ON\"}]}" post_sensor_global_expected = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "testdescp", "reset_time": 5}}} @@ -731,10 +428,10 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { t.Run("Create on sonic table yang node having singleton container and sibling list", processSetRequest(url, post_payload, "POST", false)) time.Sleep(1 * time.Second) - t.Run("Verify Create on sonic table yang node with singleton container and sibling list", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|test_device|32", post_sensor_device_expected, false)) + t.Run("Verify Create on sonic table yang node with singleton container and sibling list", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|test_device|32", post_sensor_device_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_patch_on_sonic_singleton_container_node +++++++++++++") @@ -743,7 +440,7 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_SENSOR_GLOBAL/global_sensor" // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) // Payload patch_payload := "{ \"sonic-test-xfmr:global_sensor\": { \"mode\": \"testmode\", \"description\": \"test description\", \"reset_time\": 20 }}" patch_sensor_global_expected := map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "test description", "reset_time": 20}}} @@ -751,11 +448,11 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { t.Run("Patch on singleton sonic container yang node", processSetRequest(url, patch_payload, "PATCH", false)) time.Sleep(1 * time.Second) - t.Run("Verify patch on singleton sonic container yang node", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", patch_sensor_global_expected, false)) - t.Run("Verify patch on singleton sonic container yang node", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor_timer", patch_sensor_timer_expected, false)) + t.Run("Verify patch on singleton sonic container yang node", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", patch_sensor_global_expected, false)) + t.Run("Verify patch on singleton sonic container yang node", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor_timer", patch_sensor_timer_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_create_and_modify_on_sonic_sibling_singleton_container_yang_node +++++++++++++") @@ -763,7 +460,7 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_SENSOR_GLOBAL" // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) // Payload patch_payload = "{\"sonic-test-xfmr:TEST_SENSOR_GLOBAL\":{\"global_sensor\": {\"mode\": \"testmode\", \"description\": \"test description for testmode\", \"reset_time\": 25 }, \"sonic-test-xfmr:global_sensor_timer\": { \"timer_mode\": \"sample\", \"timer_description\": \"test sample timer mode\" }}}" patch_sensor_global_expected = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "test description for testmode", "reset_time": 25}}} @@ -771,11 +468,11 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { t.Run("Create and modify on sibling singleton containers sonic yang node", processSetRequest(url, patch_payload, "PATCH", false)) time.Sleep(1 * time.Second) - t.Run("Verify Create and modify on sibling singleton containers in sonic yang table node", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", patch_sensor_global_expected, false)) - t.Run("Verify Create and modify on sibling singleton containers in sonic yang table node", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor_timer", patch_sensor_timer_expected, false)) + t.Run("Verify Create and modify on sibling singleton containers in sonic yang table node", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", patch_sensor_global_expected, false)) + t.Run("Verify Create and modify on sibling singleton containers in sonic yang table node", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor_timer", patch_sensor_timer_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_patch_on_sonic_yang_with_singleton_container_sibling_list +++++++++++++") @@ -784,7 +481,7 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_SENSOR_GLOBAL" // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) // Payload patch_payload = "{\"sonic-test-xfmr:TEST_SENSOR_GLOBAL\":{ \"global_sensor\": { \"mode\": \"testmode\", \"description\": \"testdescp\" }, \"TEST_SENSOR_GLOBAL_LIST\": [{\"device_name\": \"test_device\",\"device_id\": 32, \"device_status\": \"OFF\"}]}}" @@ -794,12 +491,12 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { t.Run("Patch on sonic node having singleton container and sibling list yang nodes", processSetRequest(url, patch_payload, "PATCH", false)) time.Sleep(1 * time.Second) - t.Run("Verify patch on sonic yang node with sibling list and singleton container", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", patch_sensor_global_expected, false)) - t.Run("Verify patch on sonic yang node with sibling list and singleton container", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor_timer", patch_sensor_timer_expected, false)) - t.Run("Verify patch on sonic yang node with sibling list and singleton container", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|test_device|32", patch_sensor_device_expected, false)) + t.Run("Verify patch on sonic yang node with sibling list and singleton container", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", patch_sensor_global_expected, false)) + t.Run("Verify patch on sonic yang node with sibling list and singleton container", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor_timer", patch_sensor_timer_expected, false)) + t.Run("Verify patch on sonic yang node with sibling list and singleton container", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|test_device|32", patch_sensor_device_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_replace_on_sonic_singleton_container_leaf +++++++++++++") @@ -807,7 +504,7 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { prereq = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "test description"}}} // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) // Payload put_payload := "{ \"sonic-test-xfmr:mode\": \"test_mode_1\"}" @@ -815,10 +512,10 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { t.Run("Put on singleton sonic yang leaf node", processSetRequest(url, put_payload, "PUT", false)) time.Sleep(1 * time.Second) - t.Run("Verify put on singleton sonic yang leaf node", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", put_sensor_global_expected, false)) + t.Run("Verify put on singleton sonic yang leaf node", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", put_sensor_global_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_replace_on_sonic_sibling_singleton_container_yang_node +++++++++++++") @@ -826,7 +523,7 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_SENSOR_GLOBAL" // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) // Payload put_payload = "{\"sonic-test-xfmr:TEST_SENSOR_GLOBAL\":{\"global_sensor\": {\"mode\": \"testmode\", \"description\": \"test description for testmode\"}, \"sonic-test-xfmr:global_sensor_timer\": { \"timer_mode\": \"sample\", \"timer_description\": \"test sample timer mode\" },\"TEST_SENSOR_GLOBAL_LIST\": [{\"device_name\": \"test_device\",\"device_id\": 32, \"device_status\": \"OFF\"}]}}" put_sensor_global_expected = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "test description for testmode", "reset_time": 5}}} @@ -835,12 +532,12 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { t.Run("Create and replace on sibling singleton containers sonic yang node", processSetRequest(url, put_payload, "PUT", false)) time.Sleep(1 * time.Second) - t.Run("Verify Create and replace on sibling singleton containers in sonic yang table node", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", put_sensor_global_expected, false)) - t.Run("Verify Create and replace on sibling singleton containers in sonic yang table node", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor_timer", put_sensor_timer_expected, false)) - t.Run("Verify replace on sibling singleton containers to list in sonic yang table node", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|test_device|32", put_sensor_device_expected, false)) + t.Run("Verify Create and replace on sibling singleton containers in sonic yang table node", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", put_sensor_global_expected, false)) + t.Run("Verify Create and replace on sibling singleton containers in sonic yang table node", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor_timer", put_sensor_timer_expected, false)) + t.Run("Verify replace on sibling singleton containers to list in sonic yang table node", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|test_device|32", put_sensor_device_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_replace_on_sonic_list_instance_sibling_to_singleton_container +++++++++++++") @@ -848,7 +545,7 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { prereq = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "test description"}}} // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) // Payload put_payload = "{\"sonic-test-xfmr:TEST_SENSOR_GLOBAL_LIST\": [{\"device_name\": \"test_device\",\"device_id\": 32, \"device_status\": \"OFF\"}]}" @@ -856,26 +553,26 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { t.Run("Put on sonic yang node list, sibling to singleton container", processSetRequest(url, put_payload, "PUT", false)) time.Sleep(1 * time.Second) - t.Run("Verify put/create on sonic yang node list, sibling to singleton container", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|test_device|32", put_sensor_device_expected, false)) + t.Run("Verify put/create on sonic yang node list, sibling to singleton container", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|test_device|32", put_sensor_device_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_delete_on_singleton_sonic_container +++++++++++++") url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_SENSOR_GLOBAL/global_sensor" // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) delete_expected := make(map[string]interface{}) t.Run("Delete on singleton sonic container", processDeleteRequest(url, false)) time.Sleep(1 * time.Second) - t.Run("Verify delete on sonic singleton container", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", delete_expected, false)) + t.Run("Verify delete on sonic singleton container", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", delete_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_delete_on_whole_sibling_list_to_singleton_sonic_container +++++++++++++") @@ -883,19 +580,19 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { prereq = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "test description for testmode", "reset_time": 25}, "global_sensor_timer": map[string]interface{}{"timer_mode": "sample", "timer_description": "test sample timer mode", "reset_time": 30}, "test_device|32": map[string]interface{}{"device_status": "OFF"}, "test_device|54": map[string]interface{}{"device_status": "ON"}}} cleanuptbl = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": "", "test_device|32": "", "test_device|54": ""}} // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) delete_expected = make(map[string]interface{}) delete_expected_global_sensor := map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "test description for testmode", "reset_time": 25}}} t.Run("Delete on singleton sonic container", processDeleteRequest(url, false)) time.Sleep(1 * time.Second) - t.Run("Verify delete on whole sibling list to singleton container", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|test_device|32", delete_expected, false)) - t.Run("Verify delete on whole sibling list to singleton container", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|test_device|54", delete_expected, false)) - t.Run("Verify delete on whole sibling list to singleton container", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", delete_expected_global_sensor, false)) + t.Run("Verify delete on whole sibling list to singleton container", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|test_device|32", delete_expected, false)) + t.Run("Verify delete on whole sibling list to singleton container", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|test_device|54", delete_expected, false)) + t.Run("Verify delete on whole sibling list to singleton container", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", delete_expected_global_sensor, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_delete_on_table_with_mutiple_sibling_singleton_sonic_containers_and_sibling_list +++++++++++++") @@ -904,15 +601,15 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { cleanuptbl = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": "", "global_sensor_timer": "", "test_device|32": ""}} // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) delete_expected = make(map[string]interface{}) t.Run("Delete on table with mutiple sibling singleton sonic containers and sibling list", processDeleteRequest(url, false)) time.Sleep(1 * time.Second) - t.Run("Verify delete on table with mutiple sonic singleton container and sibling list(global_sensor)", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", delete_expected, false)) - t.Run("Verify delete on table with mutiple sonic singleton container and sbling list(global_sensor_timer)", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor_timer", delete_expected, false)) - t.Run("Verify delete on table with mutiple sonic singleton containerand sibling list(test_device|32)", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|test_device|32", delete_expected, false)) + t.Run("Verify delete on table with mutiple sonic singleton container and sibling list(global_sensor)", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", delete_expected, false)) + t.Run("Verify delete on table with mutiple sonic singleton container and sbling list(global_sensor_timer)", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor_timer", delete_expected, false)) + t.Run("Verify delete on table with mutiple sonic singleton containerand sibling list(test_device|32)", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|test_device|32", delete_expected, false)) t.Log("++++++++++++++ Test_get_on_sonic_singleton_container +++++++++++++") @@ -920,13 +617,13 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_SENSOR_GLOBAL/global_sensor" // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) get_expected := "{\"sonic-test-xfmr:global_sensor\": { \"mode\": \"mode_test\", \"description\": \"test description for single container\" }}" t.Run("Get on Sonic singleton container", processGetRequest(url, nil, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_get_on_table_with_mutiple_sibling_singleton_sonic_containers_and_sibling_list +++++++++++++") @@ -935,13 +632,13 @@ func Test_singleton_sonic_yang_node_operations(t *testing.T) { cleanuptbl = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": "", "global_sensor_timer": "", "test_device|32": ""}} // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) get_expected = "{\"sonic-test-xfmr:TEST_SENSOR_GLOBAL\":{ \"global_sensor\": { \"mode\": \"testmode\", \"description\": \"test description for testmode\", \"reset_time\":25 },\"global_sensor_timer\": { \"timer_mode\": \"sample\", \"timer_description\": \"test sample timer mode\", \"reset_time\":30}, \"TEST_SENSOR_GLOBAL_LIST\": [{\"device_name\": \"test_device\",\"device_id\": 32, \"device_status\": \"OFF\"}]}}" t.Run("Get on Sonic table with mutiple sonic singleton containers and sibling list", processGetRequest(url, nil, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) } @@ -957,10 +654,10 @@ func Test_Query_Params_OC_Yang_Get(t *testing.T) { prereq_cntr := map[string]interface{}{"TEST_SENSOR_GROUP_COUNTERS": map[string]interface{}{"test_group_1": map[string]interface{}{"frame-in": "3435", "frame-out": "3452"}}} // Setup - Prerequisite - None - unloadDB(db.ConfigDB, cleanuptbl) - unloadDB(db.CountersDB, prereq_cntr) - loadDB(db.ConfigDB, prereq) - loadDB(db.CountersDB, prereq_cntr) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.CountersDB, prereq_cntr) + loadDB(hostDBName, db.ConfigDB, prereq) + loadDB(hostDBName, db.CountersDB, prereq_cntr) t.Log("++++++++++++++ Test_Query_Depth3_Container_Get +++++++++++++") url := "/openconfig-test-xfmr:test-xfmr" @@ -1095,8 +792,8 @@ func Test_Query_Params_OC_Yang_Get(t *testing.T) { t.Run("Test_Query_Fields_Error_Leaf_Get", processGetRequest(url, &qp, get_expected, true, expected_err)) // Teardown - unloadDB(db.ConfigDB, prereq) - unloadDB(db.CountersDB, prereq_cntr) + unloadDB(hostDBName, db.ConfigDB, prereq) + unloadDB(hostDBName, db.CountersDB, prereq_cntr) } /* sonic yang GET operation query-parameter tests */ @@ -1106,8 +803,8 @@ func Test_sonic_yang_content_query_parameter_operations(t *testing.T) { "TEST_CABLE_LENGTH": map[string]interface{}{"testcable_01": map[string]interface{}{"eth0": "10m"}}} prereq_nonconfig_db := map[string]interface{}{"TEST_SENSOR_MODE_TABLE": map[string]interface{}{"mode:testsensor123:3543": map[string]interface{}{"description": "Test sensor mode"}}} //Setup - loadDB(db.ConfigDB, prereq_config_db) - loadDB(db.CountersDB, prereq_nonconfig_db) + loadDB(hostDBName, db.ConfigDB, prereq_config_db) + loadDB(hostDBName, db.CountersDB, prereq_nonconfig_db) t.Log("++++++++++++++ Test_content_all_query_parameter_on_sonic_yang +++++++++++++") //covers singleton container and nested list url := "/sonic-test-xfmr:sonic-test-xfmr" @@ -1174,8 +871,8 @@ func Test_sonic_yang_content_query_parameter_operations(t *testing.T) { t.Run("Sonic yang query parameter nested list leaf content mismatch error", processGetRequest(url, &qp, get_expected, true, exp_err)) // Teardown - unloadDB(db.ConfigDB, prereq_config_db) - unloadDB(db.CountersDB, prereq_nonconfig_db) + unloadDB(hostDBName, db.ConfigDB, prereq_config_db) + unloadDB(hostDBName, db.CountersDB, prereq_nonconfig_db) } @@ -1191,7 +888,7 @@ func Test_sonic_yang_depth_query_parameter_operations(t *testing.T) { url := "/sonic-test-xfmr:sonic-test-xfmr/TEST_SENSOR_GLOBAL/global_sensor/description" qp.depth = 1 //Setup - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) get_expected := "{\"sonic-test-xfmr:description\":\"testdescription\"}" t.Run("Sonic yang query parameter depth=1(target is singleton container leaf)", processGetRequest(url, &qp, get_expected, false)) @@ -1247,7 +944,7 @@ func Test_sonic_yang_depth_query_parameter_operations(t *testing.T) { get_expected = "{\"sonic-test-xfmr:sonic-test-xfmr\": {\"TEST_SENSOR_GLOBAL\":{\"global_sensor\":{\"description\":\"testdescription\"}},\"TEST_CABLE_LENGTH\":{\"TEST_CABLE_LENGTH_LIST\": [{\"name\": \"testcable_01\",\"TEST_CABLE_LENGTH\": [{\"length\": \"10m\",\"port\": \"eth0\"},{\"length\": \"11m\",\"port\": \"eth1\"}]},{\"name\": \"testcable_02\", \"TEST_CABLE_LENGTH\": [{\"length\": \"22m\",\"port\": \"eth2\"}]}]}}}" t.Run("Sonic yang query parameter depth=5", processGetRequest(url, &qp, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, prereq) } func Test_sonic_yang_content_plus_depth_query_parameter_operations(t *testing.T) { @@ -1257,8 +954,8 @@ func Test_sonic_yang_content_plus_depth_query_parameter_operations(t *testing.T) "TEST_CABLE_LENGTH": map[string]interface{}{"testcable_01": map[string]interface{}{"eth0": "10m"}}} prereq_nonconfig_db := map[string]interface{}{"TEST_SENSOR_MODE_TABLE": map[string]interface{}{"mode:testsensor123:3543": map[string]interface{}{"description": "Test sensor mode"}}} //Setup - loadDB(db.ConfigDB, prereq_config_db) - loadDB(db.CountersDB, prereq_nonconfig_db) + loadDB(hostDBName, db.ConfigDB, prereq_config_db) + loadDB(hostDBName, db.CountersDB, prereq_nonconfig_db) t.Log("++++++++++++++ Test_content_all_depth_level_4_query_parameter_on_sonic_yang +++++++++++++") url := "/sonic-test-xfmr:sonic-test-xfmr" @@ -1281,8 +978,8 @@ func Test_sonic_yang_content_plus_depth_query_parameter_operations(t *testing.T) get_expected = "{\"sonic-test-xfmr:sonic-test-xfmr\":{\"TEST_SENSOR_MODE_TABLE\":{\"TEST_SENSOR_MODE_TABLE_LIST\":[{\"description\":\"Test sensor mode\",\"id\":3543,\"mode\":\"mode:testsensor123\"}]}}}" t.Run("Sonic yang query parameter content=nonconfig depth=4", processGetRequest(url, &qp, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, prereq_config_db) - unloadDB(db.CountersDB, prereq_nonconfig_db) + unloadDB(hostDBName, db.ConfigDB, prereq_config_db) + unloadDB(hostDBName, db.CountersDB, prereq_nonconfig_db) } func Test_sonic_yang_fields_query_parameter_operations(t *testing.T) { @@ -1293,7 +990,7 @@ func Test_sonic_yang_fields_query_parameter_operations(t *testing.T) { prereq := map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"description": "testdescription"}}, "TEST_SENSOR_A_TABLE": map[string]interface{}{"test_group_1|sensor_type_a_testA": map[string]interface{}{"exclude_filter": "filter_filterB", "description_a": "test group1 sensor type a descriptionXYZ"}, "test_group_2|sensor_type_a_testB": map[string]interface{}{"exclude_filter": "filter_filterA", "description_a": "test group2 sensor type a descriptionB"}}} url := "/sonic-test-xfmr:sonic-test-xfmr/TEST_SENSOR_A_TABLE/TEST_SENSOR_A_TABLE_LIST" qp.fields = append(qp.fields, "exclude_filter") - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) get_expected := "{\"sonic-test-xfmr:TEST_SENSOR_A_TABLE_LIST\":[{\"exclude_filter\": \"filter_filterB\",\"id\": \"test_group_1\",\"type\": \"sensor_type_a_testA\" },{\"exclude_filter\": \"filter_filterA\",\"id\": \"test_group_2\",\"type\": \"sensor_type_a_testB\"}]}" t.Run("Sonic yang query parameter fields(single field) ", processGetRequest(url, &qp, get_expected, false)) @@ -1320,7 +1017,7 @@ func Test_sonic_yang_fields_query_parameter_operations(t *testing.T) { exp_err = tlerr.InvalidArgsError{Format: "Bad Request - fields query parameter specified on a terminal node uri."} t.Run("Sonic yang invalid fields query parameter request target", processGetRequest(url, &qp, get_expected, true, exp_err)) // Teardown - unloadDB(db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, prereq) } func Test_OC_Sonic_OneOnOne_Composite_KeyMapping(t *testing.T) { @@ -1329,8 +1026,8 @@ func Test_OC_Sonic_OneOnOne_Composite_KeyMapping(t *testing.T) { prereq := map[string]interface{}{"TEST_SENSOR_COMPONENT_TABLE": map[string]interface{}{"FAN|TYPE1|14.31": map[string]interface{}{"description": "Test fan sensor type1 v14.31"}}} // Setup - Prerequisite - unloadDB(db.ConfigDB, prereq) - loadDB(db.ConfigDB, parent_prereq) + unloadDB(hostDBName, db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, parent_prereq) url := "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=test_group_1]/test-sensor-components" @@ -1342,16 +1039,16 @@ func Test_OC_Sonic_OneOnOne_Composite_KeyMapping(t *testing.T) { t.Run("SET on OC_Sonic_OneOnOne_Composite_KeyMapping", processSetRequest(url, url_body_json, "POST", false, nil)) time.Sleep(1 * time.Second) - t.Run("Test OC-Sonic one-one composite key mapping", verifyDbResult(rclient, "TEST_SENSOR_COMPONENT_TABLE|FAN|TYPE1|14.31", expected_map, false)) + t.Run("Test OC-Sonic one-one composite key mapping", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_COMPONENT_TABLE|FAN|TYPE1|14.31", expected_map, false)) // Teardown - unloadDB(db.ConfigDB, prereq) - unloadDB(db.ConfigDB, parent_prereq) + unloadDB(hostDBName, db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, parent_prereq) t.Log("++++++++++++++ Test_Get_OC_Sonic_OneOnOne_Composite_KeyMapping +++++++++++++") - loadDB(db.ConfigDB, parent_prereq) - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, parent_prereq) + loadDB(hostDBName, db.ConfigDB, prereq) url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=test_group_1]/test-sensor-components" @@ -1359,8 +1056,8 @@ func Test_OC_Sonic_OneOnOne_Composite_KeyMapping(t *testing.T) { t.Run("GET on List_OC_Sonic_OneOnOne_Composite_KeyMapping", processGetRequest(url, nil, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, prereq) - unloadDB(db.ConfigDB, parent_prereq) + unloadDB(hostDBName, db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, parent_prereq) } /* @@ -1378,39 +1075,39 @@ func Test_NodeWithListHavingConfigLeafRefByKey_OC_Yang(t *testing.T) { post_sensor_group_expected := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"test_group_1": map[string]interface{}{"color-hold-time": "10"}}} t.Run("Set on OC-Yang node with list having config leaf referenced by list key.", processSetRequest(url, post_payload, "POST", false)) time.Sleep(1 * time.Second) - t.Run("Verify set on OC-Yang node with list having config leaf referenced by list key.", verifyDbResult(rclient, "TEST_SENSOR_GROUP|test_group_1", post_sensor_group_expected, false)) + t.Run("Verify set on OC-Yang node with list having config leaf referenced by list key.", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|test_group_1", post_sensor_group_expected, false)) // Teardown - unloadDB(db.ConfigDB, pre_req) + unloadDB(hostDBName, db.ConfigDB, pre_req) t.Log("++++++++++++++ Test get on OC yang node with list having config leaf referenced by list key and state leaf same as list key +++++++++++++") url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group" // Setup - Prerequisite - loadDB(db.ConfigDB, pre_req) + loadDB(hostDBName, db.ConfigDB, pre_req) // Payload get_expected := "{\"openconfig-test-xfmr:test-sensor-group\":[{\"config\":{\"color-hold-time\":10,\"id\":\"test_group_1\"},\"id\":\"test_group_1\",\"state\":{\"color-hold-time\":10,\"id\":\"test_group_1\"}}]}" t.Run("Verify get on OC yang node with list having config leaf referenced by list key and state leaf same list key", processGetRequest(url, nil, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, pre_req) + unloadDB(hostDBName, db.ConfigDB, pre_req) t.Log("++++++++++++++ GET on OC YANG config container leaf that is referenced by immediate parent list's key and has no app annotations +++++++++++++") url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=test_group_1]/state/id" // Setup - Prerequisite - loadDB(db.ConfigDB, pre_req) + loadDB(hostDBName, db.ConfigDB, pre_req) // Payload get_expected = "{\"openconfig-test-xfmr:id\":\"test_group_1\"}" t.Run("Get on leaf in OC config container, with no app annotation, and is referenced by immediate parent list's key leaf", processGetRequest(url, nil, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, pre_req) + unloadDB(hostDBName, db.ConfigDB, pre_req) t.Log("++++++++++++++ GET on OC YANG State container leaf that is same as immediate parent list's key and has no app annotations +++++++++++++") url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=test_group_1]/state/id" // Setup - Prerequisite - loadDB(db.ConfigDB, pre_req) + loadDB(hostDBName, db.ConfigDB, pre_req) // Payload get_expected = "{\"openconfig-test-xfmr:id\":\"test_group_1\"}" t.Run("Get on leaf in OC state container, with no app annotation, and is same as immediate parent list's key leaf", processGetRequest(url, nil, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, pre_req) + unloadDB(hostDBName, db.ConfigDB, pre_req) } func Test_OC_Sonic_SingleKey_Mapping(t *testing.T) { @@ -1418,7 +1115,7 @@ func Test_OC_Sonic_SingleKey_Mapping(t *testing.T) { prereq := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"group1\\|1": map[string]interface{}{"color-hold-time": "1354"}}} // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) t.Log("++++++++++++++ Test_Get_OC_Sonic_SingleKey_Mapping +++++++++++++") @@ -1432,14 +1129,14 @@ func Test_OC_Sonic_SingleKey_Mapping(t *testing.T) { get_expected = "{\"sonic-test-xfmr:TEST_SENSOR_GROUP\":{\"TEST_SENSOR_GROUP_LIST\":[{\"color-hold-time\":1354,\"id\":\"group1\\\\|1\"}]}}" t.Run("GET on OC_Sonic_Single_KeyMapping_SonicRequest", processGetRequest(url, nil, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, prereq) t.Log("++++++++++++++ Test_Get_Sonic_SingleKey_Mapping +++++++++++++") prereq = map[string]interface{}{"TEST_INTERFACE_MODE_TABLE": map[string]interface{}{"testname": map[string]interface{}{"description": "single key list entry"}, "testname|testmode": map[string]interface{}{"description": "double key list entry"}}} // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_INTERFACE_MODE_TABLE" @@ -1447,46 +1144,46 @@ func Test_OC_Sonic_SingleKey_Mapping(t *testing.T) { t.Run("GET on Sonic_Single_KeyMapping", processGetRequest(url, nil, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, prereq) } func Test_sonic_yang_default_value_handling(t *testing.T) { t.Log("++++++++++++++ Test_set_on_sonic_yang_where_default_value_for_a_node_not_present_in_payload +++++++++++++") pre_req := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"test_group_1": ""}, "TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": ""}} //setup - unloadDB(db.ConfigDB, pre_req) + unloadDB(hostDBName, db.ConfigDB, pre_req) url := "/sonic-test-xfmr:sonic-test-xfmr" post_payload := "{ \"sonic-test-xfmr:TEST_SENSOR_GROUP\": { \"TEST_SENSOR_GROUP_LIST\": [ { \"id\": \"test_group_1\" } ] }, \"sonic-test-xfmr:TEST_SENSOR_GLOBAL\": { \"global_sensor\": { \"mode\": \"testmode\", \"description\": \"testdescription\"} }}" sensor_global_expected := map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"description": "testdescription", "mode": "testmode", "reset_time": 5}}} sensor_group_expected := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"test_group_1": map[string]interface{}{"color-hold-time": 10}}} t.Run("Test set on sonic yang where default value for a node not present in payload.", processSetRequest(url, post_payload, "POST", false, nil)) - t.Run("Verify set on sonic yang where default value for a node not present in payload for list node", verifyDbResult(rclient, "TEST_SENSOR_GROUP|test_group_1", sensor_group_expected, false)) - t.Run("Verify set on sonic yang where default value for a node not present in payload for singleton container", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", sensor_global_expected, false)) + t.Run("Verify set on sonic yang where default value for a node not present in payload for list node", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|test_group_1", sensor_group_expected, false)) + t.Run("Verify set on sonic yang where default value for a node not present in payload for singleton container", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", sensor_global_expected, false)) //Teardown - unloadDB(db.ConfigDB, pre_req) + unloadDB(hostDBName, db.ConfigDB, pre_req) t.Log("++++++++++++++ Test_delete_reseting_sonic_yang_leaf_node_to_default +++++++++++++") pre_req = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "reset_time": 19}}} //setup - loadDB(db.ConfigDB, pre_req) + loadDB(hostDBName, db.ConfigDB, pre_req) url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_SENSOR_GLOBAL/global_sensor/reset_time" sensor_global_expected = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "reset_time": 5}}} t.Run("Test delete reseting sonic yang leaf node to default", processDeleteRequest(url, false)) - t.Run("Verify delete reseting sonic yang leaf node to default", verifyDbResult(rclient, "TEST_SENSOR_GLOBAL|global_sensor", sensor_global_expected, false)) + t.Run("Verify delete reseting sonic yang leaf node to default", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", sensor_global_expected, false)) //Teardown - unloadDB(db.ConfigDB, pre_req) + unloadDB(hostDBName, db.ConfigDB, pre_req) } // Test partial key at whole list level func Test_WholeList_PartialKey(t *testing.T) { - /* Delete And Get at a parent yang list node should rerieve/process only those child nodes which are relevant to the parent list key */ - parent_prereq := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_1": map[string]interface{}{"NULL": "NULL"}, "sensor_group_2": map[string]interface{}{"NULL": "NULL"}}} + /* Delete at whole list returning partial key / parent key. Test if only relevant instances are deleted */ + parent_prereq := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_1": map[string]interface{}{"NULL": "NULL"}}} prereq := map[string]interface{}{"TEST_SENSOR_ZONE_TABLE": map[string]interface{}{"sensor_group_1|zoneA": map[string]interface{}{"description": "sensor_group_1 zoneA instance"}, "sensor_group_2|zoneA": map[string]interface{}{"description": "sensor_group_2 zoneA instance"}}} // Setup - Prerequisite - loadDB(db.ConfigDB, parent_prereq) - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, parent_prereq) + loadDB(hostDBName, db.ConfigDB, prereq) t.Log("++++++++++++++ GET Test_PartialKey_Get +++++++++++++") url := "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=sensor_group_1]" @@ -1503,52 +1200,25 @@ func Test_WholeList_PartialKey(t *testing.T) { t.Run("DELETE on whole list with partial/ parent key, ", processDeleteRequest(url, false)) time.Sleep(1 * time.Second) - t.Run("DELETE on whole list with partial/parent key - verify child table instance with parent key gets deleted", verifyDbResult(rclient, "TEST_SENSOR_ZONE_TABLE|sensor_group_1|zoneA", expected_del, false)) - t.Run("DELETE on whole list with partial/parent key - verify child table instance not having parent key still exists", verifyDbResult(rclient, "TEST_SENSOR_ZONE_TABLE|sensor_group_2|zoneA", expected_map, false)) - - /* Verify if get like traversal is happenning for delete when a yang list node in child hierarchy has partial key of parent */ - t.Log("++++++++++++++ DELETE On Container with Child Node List With PartialKey of Parent List ++++++++++++++") - // Setup - Prerequisite - loadDB(db.ConfigDB, parent_prereq) - loadDB(db.ConfigDB, prereq) - url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=sensor_group_1]/test-sensor-zones" - t.Run("Test_Delete_On_Container_with_Child_Node_List_With_PartialKey_of_Parent_List", processDeleteRequest(url, false)) - time.Sleep(1 * time.Second) - t.Run("Verify delete on container with child node list with partial key of parent - releavant child instances get deleted.", verifyDbResult(rclient, "TEST_SENSOR_ZONE_TABLE|sensor_group_1|zoneA", expected_del, false)) - t.Run("Verify delete on container with child node list with partial key of parent - non-releavant child instances not deleted.", verifyDbResult(rclient, "TEST_SENSOR_ZONE_TABLE|sensor_group_2|zoneA", expected_map, false)) - time.Sleep(1 * time.Second) - - t.Log("++++++++++++++ DELETE On List Instance With Child Node List With PartialKey Of Parent List ++++++++++++++") - // Setup - Prerequisite - loadDB(db.ConfigDB, parent_prereq) - loadDB(db.ConfigDB, prereq) - url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=sensor_group_1]" - expected_parent_map := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_2": map[string]interface{}{"NULL": "NULL"}}} - t.Run("Test_Delete_On_List_Instance_with_Child_Node_List_With_PartialKey_of_Parent_List", processDeleteRequest(url, false)) - time.Sleep(1 * time.Second) - t.Run("Verify delete on list instance with child node list with partial key of parent - parent instance specified in request gets deleted.", verifyDbResult(rclient, "TEST_SENSOR_GROUP|sensor_group_1", expected_del, false)) - t.Run("Verify delete on list instance with child node list with partial key of parent - other parent list instances stay intact.", verifyDbResult(rclient, "TEST_SENSOR_GROUP|sensor_group_2", expected_parent_map, false)) - t.Run("Verify delete on list instance with child node list with partial key of parent - releavant child instances get deleted.", verifyDbResult(rclient, "TEST_SENSOR_ZONE_TABLE|sensor_group_1|zoneA", expected_del, false)) - t.Run("Verify delete on list instance with child node list with partial key of parent - non-releavant child instances not deleted.s", verifyDbResult(rclient, "TEST_SENSOR_ZONE_TABLE|sensor_group_2|zoneA", expected_map, false)) - - t.Log("++++++++++++++ Done Test_GET_And_Delete_Involving_Node_With_PartialKey_Of_Parent +++++++++++++") + t.Run("DELETE on whole list with partial/parent key - verify child table instance with parent key gets deleted", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_ZONE_TABLE|sensor_group_1|zoneA", expected_del, false)) + t.Run("DELETE on whole list with partial/parent key - verify child table instance not having parent key still exists", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_ZONE_TABLE|sensor_group_2|zoneA", expected_map, false)) // Teardown - unloadDB(db.ConfigDB, parent_prereq) - unloadDB(db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, parent_prereq) + unloadDB(hostDBName, db.ConfigDB, prereq) } func Test_Validate_Handler_Get(t *testing.T) { prereq := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"test_group_1": map[string]interface{}{"color-hold-time": "10"}}, "TEST_SENSOR_A_TABLE": map[string]interface{}{"test_group_1|sensor_type_a_testA": map[string]interface{}{"exclude_filter": "filter_filterA1"}}, "TEST_SENSOR_B_TABLE": map[string]interface{}{"test_group_1|sensor_type_b_testB": map[string]interface{}{"exclude_filter": "filter_filterB"}}, "TEST_SENSOR_A_LIGHT_SENSOR_TABLE": map[string]interface{}{"test_group_1|sensor_type_a_testA|light_sensor_1": map[string]interface{}{"light-intensity-measure": 6}}} // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) t.Log("++++++++++++++ Test_Validate_Handler_Get +++++++++++++") url := "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=test_group_1]/test-sensor-types/test-sensor-type" get_expected := "{\"openconfig-test-xfmr:test-sensor-type\":[{\"config\":{\"exclude-filter\":\"filterA1\",\"type\":\"sensora_testA\"},\"sensor-a-light-sensors\":{\"sensor-a-light-sensor\":[{\"config\":{\"light-intensity-measure\":6,\"tag\":\"lightsensor_1\"},\"state\":{\"light-intensity-measure\":6,\"tag\":\"lightsensor_1\"},\"tag\":\"lightsensor_1\"}]},\"state\":{\"exclude-filter\":\"filterA1\",\"type\":\"sensora_testA\"},\"type\":\"sensora_testA\"},{\"config\":{\"exclude-filter\":\"filterB\",\"type\":\"sensorb_testB\"},\"state\":{\"exclude-filter\":\"filterB\",\"type\":\"sensorb_testB\"},\"type\":\"sensorb_testB\"}]}" //light sensor child nodes are valid/filled only for sensora type of parent t.Run("Test Get on list with children having validate handler", processGetRequest(url, nil, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, prereq) } //Sonic Nested list GET test cases @@ -1559,7 +1229,7 @@ func Test_Sonic_NestedList_Get(t *testing.T) { "TEST_SENSOR_GROUP": map[string]interface{}{"testgroup": map[string]interface{}{"color-hold-time": 20, "colors@": "red,blue"}, "testGroup": map[string]interface{}{"color-hold-time": 30, "colors@": "red,blue"}}} // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) t.Log("++++++++++++++ Test_Sonic_NestedList_Get at module level +++++++++++++") url := "/sonic-test-xfmr:sonic-test-xfmr" @@ -1602,7 +1272,7 @@ func Test_Sonic_NestedList_Get(t *testing.T) { t.Run("GET on Sonic_NestedList at inner list instance non key existent case", processGetRequest(url, nil, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, prereq) } @@ -1612,7 +1282,7 @@ func Test_Sonic_NestedList_Get_Fields_QueryParams(t *testing.T) { "TEST_SENSOR_GROUP": map[string]interface{}{"testgroup": map[string]interface{}{"color-hold-time": 20, "colors@": "red,blue"}, "testGroup": map[string]interface{}{"color-hold-time": 30, "colors@": "red,blue"}}} var qp queryParamsUT // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) t.Log("++++++++++++++ Test_Sonic_NestedList_Get fields Query parameter having inner list in query +++++++++++++") qp.fields = []string{"TEST_CABLE_LENGTH/port"} @@ -1636,7 +1306,7 @@ func Test_Sonic_NestedList_Get_Fields_QueryParams(t *testing.T) { t.Log("++++++++++++++ Test_Sonic_NestedList_Get fields Query parameter for multiple tables +++++++++++++") prereq2 := map[string]interface{}{"TEST_SENSOR_MODE_TABLE": map[string]interface{}{"mode:testsensor:23": map[string]interface{}{"description": "testDesc"}, "testsensor:23": map[string]interface{}{"description": "testDesc"}}} - loadDB(db.CountersDB, prereq2) + loadDB(hostDBName, db.CountersDB, prereq2) time.Sleep(1 * time.Second) qp.fields = make([]string, 0) qp.fields = append(qp.fields, "TEST_CABLE_LENGTH", "TEST_SENSOR_MODE_TABLE") @@ -1645,8 +1315,8 @@ func Test_Sonic_NestedList_Get_Fields_QueryParams(t *testing.T) { t.Run("GET on Sonic_NestedList fields Query parameter for multiple tables", processGetRequest(url, &qp, get_expected, false)) // Teardown - unloadDB(db.ConfigDB, prereq) - unloadDB(db.CountersDB, prereq2) + unloadDB(hostDBName, db.ConfigDB, prereq) + unloadDB(hostDBName, db.CountersDB, prereq2) } @@ -1655,7 +1325,7 @@ func Test_Sonic_NestedList_Create(t *testing.T) { cleanuptbl := map[string]interface{}{"TEST_CABLE_LENGTH": map[string]interface{}{"testCable": ""}} // Setup - Prerequisite - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) t.Log("++++++++++++++ Test_Sonic_Nested_list_Create_instance_err +++++++++++++") url := "/sonic-test-xfmr:sonic-test-xfmr/TEST_CABLE_LENGTH/TEST_CABLE_LENGTH_LIST[name=testCable]" @@ -1669,7 +1339,7 @@ func Test_Sonic_NestedList_Create(t *testing.T) { expected_map := map[string]interface{}{"TEST_CABLE_LENGTH": map[string]interface{}{"testCable": map[string]interface{}{"eth0": "12m"}}} t.Run("Test_Sonic_Nested_list_Create_instance", processSetRequest(url, url_body_json, "POST", false, nil)) time.Sleep(1 * time.Second) - t.Run("Test_Sonic_Nested_list_Create_instance Verify DB", verifyDbResult(rclient, "TEST_CABLE_LENGTH|testCable", expected_map, false)) + t.Run("Test_Sonic_Nested_list_Create_instance Verify DB", verifyDbResult(rclient[hostDBName], "TEST_CABLE_LENGTH|testCable", expected_map, false)) t.Log("++++++++++++++ Test_Sonic_Nested_list_Create_modify_instance +++++++++++++") url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_CABLE_LENGTH/TEST_CABLE_LENGTH_LIST[name=testCable]" @@ -1677,10 +1347,10 @@ func Test_Sonic_NestedList_Create(t *testing.T) { expected_map = map[string]interface{}{"TEST_CABLE_LENGTH": map[string]interface{}{"testCable": map[string]interface{}{"eth0": "12m", "eth1": "22m"}}} t.Run("Test_Sonic_Nested_list_Create_modify_instance", processSetRequest(url, url_body_json, "POST", false, nil)) time.Sleep(1 * time.Second) - t.Run("Test_Sonic_Nested_list_Create_modify_instance Verify DB", verifyDbResult(rclient, "TEST_CABLE_LENGTH|testCable", expected_map, false)) + t.Run("Test_Sonic_Nested_list_Create_modify_instance Verify DB", verifyDbResult(rclient[hostDBName], "TEST_CABLE_LENGTH|testCable", expected_map, false)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) } @@ -1690,7 +1360,7 @@ func Test_Sonic_NestedList_Update(t *testing.T) { prereq := map[string]interface{}{"TEST_CABLE_LENGTH": map[string]interface{}{"testCable": map[string]interface{}{"eth0": "12m", "eth1": "22m"}}} // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) t.Log("++++++++++++++ Test_Sonic_Nested_list_Update_inner_list_instance_existance_case +++++++++++++") url := "/sonic-test-xfmr:sonic-test-xfmr/TEST_CABLE_LENGTH/TEST_CABLE_LENGTH_LIST[name=testCable]/TEST_CABLE_LENGTH[port=eth0]" @@ -1698,7 +1368,7 @@ func Test_Sonic_NestedList_Update(t *testing.T) { expected_map := map[string]interface{}{"TEST_CABLE_LENGTH": map[string]interface{}{"testCable": map[string]interface{}{"eth0": "77m", "eth1": "22m"}}} t.Run("Test_Sonic_Nested_list_Update_inner_list_instance_existance_case", processSetRequest(url, url_body_json, "PATCH", false, nil)) time.Sleep(1 * time.Second) - t.Run("Test_Sonic_Nested_list_Update_inner_list_instance_existance_case", verifyDbResult(rclient, "TEST_CABLE_LENGTH|testCable", expected_map, false)) + t.Run("Test_Sonic_Nested_list_Update_inner_list_instance_existance_case", verifyDbResult(rclient[hostDBName], "TEST_CABLE_LENGTH|testCable", expected_map, false)) t.Log("++++++++++++++ Test_Sonic_Nested_list_Update_inner_list_instance_non_existance_case +++++++++++++") url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_CABLE_LENGTH/TEST_CABLE_LENGTH_LIST[name=testCable]/TEST_CABLE_LENGTH[port=eth3]" @@ -1707,7 +1377,7 @@ func Test_Sonic_NestedList_Update(t *testing.T) { t.Run("Test_Sonic_Nested_list_Update_inner_list_instance_non_existance_case", processSetRequest(url, url_body_json, "PATCH", true, expected_err)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) } func Test_Sonic_NestedList_Replace(t *testing.T) { @@ -1716,7 +1386,7 @@ func Test_Sonic_NestedList_Replace(t *testing.T) { prereq := map[string]interface{}{"TEST_CABLE_LENGTH": map[string]interface{}{"testCable": map[string]interface{}{"eth0": "77m", "eth1": "22m"}}} // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) t.Log("++++++++++++++ Test_Sonic_Nested_list_Replace_inner_list_instance_non_existance_case +++++++++++++") url := "/sonic-test-xfmr:sonic-test-xfmr/TEST_CABLE_LENGTH/TEST_CABLE_LENGTH_LIST[name=testCable]/TEST_CABLE_LENGTH[port=eth3]" @@ -1724,7 +1394,7 @@ func Test_Sonic_NestedList_Replace(t *testing.T) { expected_map := map[string]interface{}{"TEST_CABLE_LENGTH": map[string]interface{}{"testCable": map[string]interface{}{"eth0": "77m", "eth1": "22m", "eth3": "66m"}}} t.Run("Test_Sonic_Nested_list_Replace_inner_list_instance_non_existance_case", processSetRequest(url, url_body_json, "PUT", false, nil)) time.Sleep(1 * time.Second) - t.Run("Test_Sonic_Nested_list_Replace_inner_list_instance_non_existance_case Verify", verifyDbResult(rclient, "TEST_CABLE_LENGTH|testCable", expected_map, false)) + t.Run("Test_Sonic_Nested_list_Replace_inner_list_instance_non_existance_case Verify", verifyDbResult(rclient[hostDBName], "TEST_CABLE_LENGTH|testCable", expected_map, false)) t.Log("++++++++++++++ Test_Sonic_Nested_list_Replace_inner_list_non_key_leaf_existance_case +++++++++++++") url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_CABLE_LENGTH/TEST_CABLE_LENGTH_LIST[name=testCable]/TEST_CABLE_LENGTH[port=eth1]/length" @@ -1732,7 +1402,7 @@ func Test_Sonic_NestedList_Replace(t *testing.T) { expected_map = map[string]interface{}{"TEST_CABLE_LENGTH": map[string]interface{}{"testCable": map[string]interface{}{"eth0": "77m", "eth1": "11m", "eth3": "66m"}}} t.Run("Test_Sonic_Nested_list_Replace_inner_list_non_key_leaf_existance_case", processSetRequest(url, url_body_json, "PUT", false, nil)) time.Sleep(1 * time.Second) - t.Run("Test_Sonic_Nested_list_Replace_inner_list_non_key_leaf_existance_case Verify", verifyDbResult(rclient, "TEST_CABLE_LENGTH|testCable", expected_map, false)) + t.Run("Test_Sonic_Nested_list_Replace_inner_list_non_key_leaf_existance_case Verify", verifyDbResult(rclient[hostDBName], "TEST_CABLE_LENGTH|testCable", expected_map, false)) t.Log("++++++++++++++ Test_Sonic_Nested_list_Replace_inner_list_non_key_leaf_non_existance_case +++++++++++++") url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_CABLE_LENGTH/TEST_CABLE_LENGTH_LIST[name=testCable]/TEST_CABLE_LENGTH[port=eth8]/length" @@ -1741,7 +1411,7 @@ func Test_Sonic_NestedList_Replace(t *testing.T) { t.Run("Test_Sonic_Nested_list_Replace_inner_list_non_key_leaf_non_existance_case", processSetRequest(url, url_body_json, "PUT", true, expected_err)) // Teardown - unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) } func Test_Sonic_NestedList_Delete(t *testing.T) { @@ -1749,7 +1419,7 @@ func Test_Sonic_NestedList_Delete(t *testing.T) { "testcable_02": map[string]interface{}{"eth0": "30m"}}} // Setup - Prerequisite - loadDB(db.ConfigDB, prereq) + loadDB(hostDBName, db.ConfigDB, prereq) //Delete targeted on nested non-key leaf when nested list instance doesn't exist in DB url := "/sonic-test-xfmr:sonic-test-xfmr/TEST_CABLE_LENGTH/TEST_CABLE_LENGTH_LIST[name=testcable_01]/TEST_CABLE_LENGTH[port=eth4]/length" @@ -1773,14 +1443,14 @@ func Test_Sonic_NestedList_Delete(t *testing.T) { expected_map := map[string]interface{}{"TEST_CABLE_LENGTH": map[string]interface{}{"testcable_01": map[string]interface{}{"eth1": "20m"}}} t.Log("++++++++++++++ Test_Sonic_NestedList_Delete on nested list instance and that instance exists in DB +++++++++++++") t.Run("DELETE on nested list instance and that instance exists in DB", processDeleteRequest(url, false)) - t.Run("DELETE on nested list instance and that instance exists in DB - verify other instance of nested list still exists and the one deleted doesn't exist", verifyDbResult(rclient, "TEST_CABLE_LENGTH|testcable_01", expected_map, false)) + t.Run("DELETE on nested list instance and that instance exists in DB - verify other instance of nested list still exists and the one deleted doesn't exist", verifyDbResult(rclient[hostDBName], "TEST_CABLE_LENGTH|testcable_01", expected_map, false)) //Delete targeted on whole nested list url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_CABLE_LENGTH/TEST_CABLE_LENGTH_LIST[name=testcable_01]/TEST_CABLE_LENGTH" expected_map = map[string]interface{}{"TEST_CABLE_LENGTH": map[string]interface{}{"testcable_01": map[string]interface{}{"NULL": "NULL"}}} t.Log("++++++++++++++ Test_Sonic_NestedList_Delete on whole nested list +++++++++++++") t.Run("DELETE on whole nested list", processDeleteRequest(url, false)) - t.Run("DELETE on whole nested list - verify that all nested list instances are replaced by NULL/NULL preserving parent list instance", verifyDbResult(rclient, "TEST_CABLE_LENGTH|testcable_01", expected_map, true)) + t.Run("DELETE on whole nested list - verify that all nested list instances are replaced by NULL/NULL preserving parent list instance", verifyDbResult(rclient[hostDBName], "TEST_CABLE_LENGTH|testcable_01", expected_map, true)) //Delete targetted at list instance that has nested child list url = "/sonic-test-xfmr:sonic-test-xfmr/TEST_CABLE_LENGTH/TEST_CABLE_LENGTH_LIST[name=testcable_01]" @@ -1788,10 +1458,10 @@ func Test_Sonic_NestedList_Delete(t *testing.T) { expected_map_testcable_02 := map[string]interface{}{"TEST_CABLE_LENGTH": map[string]interface{}{"testcable_02": map[string]interface{}{"eth0": "30m"}}} t.Log("++++++++++++++ Test_Sonic_NestedList_Delete on list instance that has nested child list +++++++++++++") t.Run("DELETE on list instance that has nested child list", processDeleteRequest(url, false)) - t.Run("DELETE on list instance that has nested child list - verify that only that parent list instance is deleted and other instnaces are instact(testcable_01 is deleted)", verifyDbResult(rclient, "TEST_CABLE_LENGTH|testcable_01", expected_map_testcable_01, false)) - t.Run("DELETE on list instance that has nested child list - verify that only that parent list instance is deleted and other instnaces are instact(testcable_02 is instact)", verifyDbResult(rclient, "TEST_CABLE_LENGTH|testcable_02", expected_map_testcable_02, false)) + t.Run("DELETE on list instance that has nested child list - verify that only that parent list instance is deleted and other instnaces are instact(testcable_01 is deleted)", verifyDbResult(rclient[hostDBName], "TEST_CABLE_LENGTH|testcable_01", expected_map_testcable_01, false)) + t.Run("DELETE on list instance that has nested child list - verify that only that parent list instance is deleted and other instnaces are instact(testcable_02 is instact)", verifyDbResult(rclient[hostDBName], "TEST_CABLE_LENGTH|testcable_02", expected_map_testcable_02, false)) //Teardown - unloadDB(db.ConfigDB, prereq) + unloadDB(hostDBName, db.ConfigDB, prereq) } diff --git a/translib/transformer/transformer_test.go b/translib/transformer/transformer_test.go index 1a98df0e4..af96e38fe 100644 --- a/translib/transformer/transformer_test.go +++ b/translib/transformer/transformer_test.go @@ -29,17 +29,22 @@ import ( "github.com/go-redis/redis/v7" "github.com/openconfig/ygot/ytypes" + "sort" + "strings" "testing" ) -var dbConfig struct { +var MdbConfig = make(map[string]struct { Instances map[string]map[string]interface{} `json:"INSTANCES"` Databases map[string]map[string]interface{} `json:"DATABASES"` -} -var rclient *redis.Client +}) + +var rclient map[string]*redis.Client var filehandle *os.File var ygSchema *ytypes.Schema -var rclientDBNum map[db.DBNum]*redis.Client +var rclientDBNum map[string]map[db.DBNum]*redis.Client + +const hostDBName string = "host" func getDBOptions(dbNo db.DBNum, isWriteDisabled bool) db.Options { var opt db.Options @@ -77,18 +82,57 @@ func TestMain(t *testing.M) { } func initDbConfig() error { - dbConfigFile := "/run/redis/sonic-db/database_config.json" - if path, ok := os.LookupEnv("DB_CONFIG_PATH"); ok { - dbConfigFile = path + + dbGlobalFile := "/var/run/redis/sonic-db/database_global.json" + + type Include struct { + Namespace string `json:"namespace"` + Include string `json:"include"` + } + + var DBConfig struct { + Includes []Include `json:"INCLUDES"` + Version string `json:"VERSION"` + } + + dbConfigJson, err := ioutil.ReadFile(dbGlobalFile) + if err != nil { + return err + } + + err = json.Unmarshal(dbConfigJson, &DBConfig) + if err != nil { + return err } - fmt.Println("dbConfigFile =", dbConfigFile) - dbConfigJson, err := ioutil.ReadFile(dbConfigFile) - if err == nil { + for _, DbVal := range DBConfig.Includes { + var dbConfig struct { + Instances map[string]map[string]interface{} `json:"INSTANCES"` + Databases map[string]map[string]interface{} `json:"DATABASES"` + } + + if path, ok := os.LookupEnv("DB_CONFIG_PATH"); ok { + DbVal.Include = path + } + + dbConfigJson, err := ioutil.ReadFile(strings.Replace(DbVal.Include, "../../", "/var/run/", -1)) + if err != nil { + return err + } + err = json.Unmarshal(dbConfigJson, &dbConfig) + if err != nil { + return err + } + if DbVal.Namespace == "" { + MdbConfig[hostDBName] = dbConfig + } else { + MdbConfig[DbVal.Namespace] = dbConfig + } } - return err + fmt.Println("------------------ database_global ----------------", DBConfig, MdbConfig) + return nil } func clearDb() { @@ -106,13 +150,13 @@ func clearDb() { for dbNum, tblList := range dbNumTblList { for _, tbl := range tblList { - tblKeys, keysErr := rclientDBNum[dbNum].Keys(tbl + "|*").Result() + tblKeys, keysErr := rclientDBNum[hostDBName][dbNum].Keys(tbl + "|*").Result() if keysErr != nil { fmt.Printf("Couldn't fetch keys for table %v", tbl) continue } for _, key := range tblKeys { - e := rclientDBNum[dbNum].Del(key).Err() + e := rclientDBNum[hostDBName][dbNum].Del(key).Err() if e != nil { fmt.Printf("Couldn't delete key %v", key) } @@ -123,27 +167,40 @@ func clearDb() { /* Prepares the database clients in Redis Server. */ func prepareDb() bool { + rclient = make(map[string]*redis.Client) + rclientDBNum = make(map[string]map[db.DBNum]*redis.Client) - rclientDBNum = make(map[db.DBNum]*redis.Client) /*Add redis client for specific DB as and how needed*/ - rclientDBNum[db.CountersDB] = getDbClient(int(db.CountersDB)) - if rclientDBNum[db.CountersDB] == nil { - fmt.Printf("error in getDbClient(int(db.CountersDB)") - return false - } - rclientDBNum[db.ConfigDB] = getDbClient(int(db.ConfigDB)) - if rclientDBNum[db.ConfigDB] == nil { - fmt.Printf("error in getDbClient(int(db.ConfigDB)") - return false - } - rclient = rclientDBNum[db.ConfigDB] + for dbName, _ := range MdbConfig { + if rclientDBNum[dbName] == nil { + rclientDBNum[dbName] = make(map[db.DBNum]*redis.Client) + } + rclientDBNum[dbName][db.CountersDB] = getDbClient(dbName, int(db.CountersDB)) + if rclientDBNum[dbName][db.CountersDB] == nil { + fmt.Printf("error in getDbClient(int(db.CountersDB)") + return false + } - rclientDBNum[db.ApplDB] = getDbClient(int(db.ApplDB)) - if rclientDBNum[db.ApplDB] == nil { - fmt.Printf("error in getDbClient(int(db.ApplDB)") - return false - } + rclientDBNum[dbName][db.StateDB] = getDbClient(dbName, int(db.StateDB)) + if rclientDBNum[dbName][db.StateDB] == nil { + fmt.Printf("error in getDbClient(int(db.StateDB)") + return false + } + rclientDBNum[dbName][db.ConfigDB] = getDbClient(dbName, int(db.ConfigDB)) + if rclientDBNum[dbName][db.ConfigDB] == nil { + fmt.Printf("error in getDbClient(int(db.ConfigDB)") + return false + } + + rclient[dbName] = rclientDBNum[dbName][db.ConfigDB] + + rclientDBNum[dbName][db.ApplDB] = getDbClient(dbName, int(db.ApplDB)) + if rclientDBNum[dbName][db.ApplDB] == nil { + fmt.Printf("error in getDbClient(int(db.ApplDB)") + return false + } + } return true } @@ -174,17 +231,24 @@ func setup() error { func teardown() error { fmt.Println("----- Performing teardown -----") clearDb() - for dbNum := range rclientDBNum { - if rclientDBNum[dbNum] != nil { - rclientDBNum[dbNum].Close() + + for dbName, clients := range rclientDBNum { + for dbNum, client := range clients { + if client != nil { + err := client.Close() + if err != nil { + fmt.Printf("Error closing Redis client for %s, DB %v: %v\n", dbName, dbNum, err) + } else { + fmt.Printf("Successfully closed Redis client for %s, DB %v\n", dbName, dbNum) + } + } } } - return nil } -func loadDB(dbNum db.DBNum, mpi map[string]interface{}) { - client := rclientDBNum[dbNum] +func loadDB(dbName string, dbNum db.DBNum, mpi map[string]interface{}) { + client := rclientDBNum[dbName][dbNum] opts := getDBOptions(dbNum, false) for key, fv := range mpi { switch fv.(type) { @@ -204,8 +268,8 @@ func loadDB(dbNum db.DBNum, mpi map[string]interface{}) { } } -func unloadDB(dbNum db.DBNum, mpi map[string]interface{}) { - client := rclientDBNum[dbNum] +func unloadDB(dbName string, dbNum db.DBNum, mpi map[string]interface{}) { + client := rclientDBNum[dbName][dbNum] opts := getDBOptions(dbNum, false) for key, fv := range mpi { switch fv.(type) { @@ -223,18 +287,17 @@ func unloadDB(dbNum db.DBNum, mpi map[string]interface{}) { fmt.Printf("Invalid data for db: %v : %v", key, fv) } } - } -func getDbClient(dbNum int) *redis.Client { - addr := "localhost:6379" +func getDbClient(dbName string, dbNum int) *redis.Client { + addr := fmt.Sprint(MdbConfig[dbName].Instances["redis"]["hostname"]) pass := "" - for _, d := range dbConfig.Databases { + for _, d := range MdbConfig[dbName].Databases { if id, ok := d["id"]; !ok || int(id.(float64)) != dbNum { continue } - dbi := dbConfig.Instances[d["instance"].(string)] + dbi := MdbConfig[dbName].Instances[d["instance"].(string)] addr = fmt.Sprintf("%v:%v", dbi["hostname"], dbi["port"]) if p, ok := dbi["password_path"].(string); ok { pwd, _ := ioutil.ReadFile(p) @@ -242,17 +305,29 @@ func getDbClient(dbNum int) *redis.Client { } break } - - rclient := redis.NewClient(&redis.Options{ + client := redis.NewClient(&redis.Options{ Network: "tcp", Addr: addr, Password: pass, DB: dbNum, DialTimeout: 0, }) - _, err := rclient.Ping().Result() + _, err := client.Ping().Result() + if err != nil { fmt.Printf("failed to connect to redis server %v", err) } - return rclient + return client +} + +func getMdbNames() []string { + var dbNames []string + for dbName, _ := range MdbConfig { + if dbName != hostDBName { + dbNames = append(dbNames, dbName) + } + } + + sort.Strings(dbNames) + return dbNames } diff --git a/translib/transformer/utils_test.go b/translib/transformer/utils_test.go index e54193a6c..d6be84640 100644 --- a/translib/transformer/utils_test.go +++ b/translib/transformer/utils_test.go @@ -28,6 +28,7 @@ import ( . "github.com/Azure/sonic-mgmt-common/translib" db "github.com/Azure/sonic-mgmt-common/translib/db" "github.com/go-redis/redis/v7" + //log "github.com/golang/glog" ) type queryParamsUT struct { @@ -49,6 +50,7 @@ func processGetRequest(url string, qparams *queryParamsUT, expectedRespJson stri var expectedMap map[string]interface{} var receivedMap map[string]interface{} var qp QueryParameters + var respJson []byte qp.Depth = 0 qp.Content = "" @@ -73,8 +75,11 @@ func processGetRequest(url string, qparams *queryParamsUT, expectedRespJson stri if err != nil { t.Fatalf("failed to unmarshal %v err: %v", expectedRespJson, err) } - - respJson := response.Payload + if len(response) == 0 { + respJson = []byte("{}") + } else { + respJson = response[0].Payload + } err = json.Unmarshal(respJson, &receivedMap) if err != nil { t.Fatalf("failed to unmarshal %v err: %v", string(respJson), err) @@ -110,7 +115,7 @@ func processGetRequestWithFile(url string, expectedJsonFile string, errorCase bo return } - respJson := response.Payload + respJson := response[0].Payload err = json.Unmarshal(respJson, &receivedMap) if err != nil { t.Fatalf("failed to unmarshal %v err: %v", string(respJson), err) diff --git a/translib/transformer/xfmr_aps.go b/translib/transformer/xfmr_aps.go index 682745eaa..c899e38b9 100644 --- a/translib/transformer/xfmr_aps.go +++ b/translib/transformer/xfmr_aps.go @@ -395,7 +395,7 @@ var aps_name_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([] payloads = append(payloads, raw) log.Infof("appending raw to the payloads %v", payloads) } else { - payloads = []map[string]interface{}{} + payloads = []map[string]interface{}{} } log.Infof("based on the key return %v=dbName %v=key", dbName, key) return []NamespacePayload{ @@ -459,7 +459,7 @@ var aps_name_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([] nsPayloadMap[dbName] = append(nsPayloadMap[dbName], payloadWithKey{ payload: finalMap, key: key.String(), - }) + }) if outStr, err := json.MarshalIndent(finalMap, "", " "); err == nil { log.Infof("Namespace: %s\nWrapped Output:\n%s", dbName, string(outStr)) diff --git a/translib/transformer/xfmr_atten.go b/translib/transformer/xfmr_atten.go index aed1c1c2d..25fc01d8d 100644 --- a/translib/transformer/xfmr_atten.go +++ b/translib/transformer/xfmr_atten.go @@ -243,7 +243,7 @@ var attn_name_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([ nsPayloadMap[dbName] = append(nsPayloadMap[dbName], payloadWithKey{ payload: finalMap, key: key.String(), - }) + }) if outStr, err := json.MarshalIndent(finalMap, "", " "); err == nil { log.Infof("Namespace: %s\nWrapped Output:\n%s", dbName, string(outStr)) diff --git a/translib/transformer/xfmr_channel_monitor.go b/translib/transformer/xfmr_channel_monitor.go index d2cb088ac..38c0ab745 100644 --- a/translib/transformer/xfmr_channel_monitor.go +++ b/translib/transformer/xfmr_channel_monitor.go @@ -168,7 +168,7 @@ var ocm_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]Names payloads = append(payloads, raw) log.Infof("appending raw to the payloads %v", payloads) } else { - payloads = []map[string]interface{}{} + payloads = []map[string]interface{}{} } log.Infof("based on the key return %v=dbName %v=key", dbName, key) return []NamespacePayload{ diff --git a/translib/transformer/xfmr_interface.go b/translib/transformer/xfmr_interface.go index ad48ca770..bc8986e11 100644 --- a/translib/transformer/xfmr_interface.go +++ b/translib/transformer/xfmr_interface.go @@ -57,6 +57,7 @@ type XfmrParams struct { invokeCRUSubtreeOnce *bool ctxt context.Context isNotTblOwner *bool + body []byte } // SubscProcType represents subcription process type identifying the type of subscription request made from translib. @@ -144,6 +145,13 @@ type XfmrDbToYgPathParams struct { ygPathKeys map[string]string //to keep translated yang keys as values for the each yang key leaf node } +type NamespacePayload struct { + Namespace string + Payloads []map[string]interface{} + Key string + Commited bool +} + // KeyXfmrYangToDb type is defined to use for conversion of Yang key to DB Key, // Transformer function definition. // Param: XfmrParams structure having Database info, YgotRoot, operation, Xpath @@ -207,6 +215,11 @@ type PostXfmrFunc func(inParams XfmrParams) error // Return: List of table names, error type TableXfmrFunc func(inParams XfmrParams) ([]string, error) +// GetNamespaceFunc type is defined to retrieve namespace associated with the uri path/payload. +// Param: XfmrParams structure having operation, uri +// Return: Array of NamespacePayload struct, error +type GetNamespaceFunc func(inParams XfmrParams) ([]NamespacePayload, error) + // ValueXfmrFunc type is defined to use for conversion of DB field value from one forma to another // Transformer function definition. // Param: XfmrDbParams structure having Database info, operation, db-number, table, key, field, value @@ -261,6 +274,9 @@ func (SubTreeXfmrSubscribe) xfmrInterfaceValiidate() { func (TableXfmrFunc) xfmrInterfaceValiidate() { xfmrLogInfo("xfmrInterfaceValiidate for TableXfmrFunc") } +func (GetNamespaceFunc) xfmrInterfaceValiidate() { + xfmrLogInfo("xfmrInterfaceValiidate for GetNamespaceFunc") +} func (SonicKeyXfmrDbToYang) xfmrInterfaceValiidate() { xfmrLogInfo("xfmrInterfaceValiidate for SonicKeyXfmrDbToYang") } diff --git a/translib/transformer/xfmr_testxfmr_callbacks.go b/translib/transformer/xfmr_testxfmr_callbacks.go index 25869d82e..2bae9c2bd 100644 --- a/translib/transformer/xfmr_testxfmr_callbacks.go +++ b/translib/transformer/xfmr_testxfmr_callbacks.go @@ -84,7 +84,7 @@ func init() { XlateFuncBind("validate_bgp_proto", validate_bgp_proto) XlateFuncBind("validate_ospfv2_proto", validate_ospfv2_proto) - // Sonic yang Key transformer functions + //Sonic yang Key transformer functions XlateFuncBind("DbToYang_test_sensor_mode_key_xfmr", DbToYang_test_sensor_mode_key_xfmr) } diff --git a/translib/transformer/xfmr_wavelength_router.go b/translib/transformer/xfmr_wavelength_router.go index eccb1cfbe..053bd625d 100644 --- a/translib/transformer/xfmr_wavelength_router.go +++ b/translib/transformer/xfmr_wavelength_router.go @@ -171,7 +171,6 @@ var DbToYang_media_channel_uf_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrP return rmap, nil } - func getMediaChannelObj(s *ygot.GoStruct) *ocbinds.OpenconfigWavelengthRouter_WavelengthRouter { deviceObj := (*s).(*ocbinds.Device) return deviceObj.WavelengthRouter @@ -184,7 +183,6 @@ var media_channel_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams payload map[string]interface{} key string } - // Updated map to hold list of payload+key per namespace var nsPayloadMap = make(map[string][]payloadWithKey) @@ -192,7 +190,7 @@ var media_channel_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams log.Infof("media_channel_get_namespace_xfmr: inParams: %v", inParams) pathInfo := NewPathInfo(inParams.uri) - + keyStr := pathInfo.Var("index") log.Infof("media_channel_get_namespace_xfmr: key: %v", keyStr) @@ -202,7 +200,7 @@ var media_channel_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams keyUint64, err := strconv.ParseUint(keyStr, 10, 32) if err != nil { log.Errorf("Invalid key format: %v", keyStr) - return nil, fmt.Errorf("Invalid key format: %v", keyStr) + return nil, fmt.Errorf("Invalid key format: %v", keyStr) } key := uint32(keyUint64) @@ -228,8 +226,8 @@ var media_channel_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams { Namespace: dbName, Payloads: payloads, - - Key: fmt.Sprintf("%d", key), + + Key: fmt.Sprintf("%d", key), }, }, nil } @@ -326,8 +324,6 @@ var media_channel_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams return result, nil } - - var media_channel_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[string]map[string]db.Value, error) { retDbDataMap := (*inParams.dbDataMap)[inParams.curDb] @@ -408,5 +404,3 @@ func customMcGetNamespaceFunc(inParams XfmrParams) ([]NamespacePayload, error) { return nameSpaceList, err } - - diff --git a/translib/transformer/xlate.go b/translib/transformer/xlate.go index 593339646..03e5814a7 100644 --- a/translib/transformer/xlate.go +++ b/translib/transformer/xlate.go @@ -897,6 +897,7 @@ func SortSncTableDbKeys(tableName string, dbKeyMap map[string]db.Value) []string return ordDbKey } + func IsDependentChildTable(depChildTbl string, parentTbl string, uriModuleNm string) bool { /* This function checks if the input table(depChildTbl) is a dependent child of parentTbl across sonic modules based on CVL provided dependency info. @@ -930,3 +931,72 @@ func IsDependentChildTable(depChildTbl string, parentTbl string, uriModuleNm str } return IsDependentChildTable } + +func topLevel(uri string) bool { + + topLevelCheck := strings.Count(uri, "/") + if topLevelCheck > 1 { + return false + } + + return true +} + +func getXdbSpecMapKey(uri string) string { + var key string + if !topLevel(uri) { + _, _, key = sonicXpathKeyExtract(uri) //key - tableName + } else { + key = uri + } + + return key +} + +func GetNamespace(uri string, ygotRoot *ygot.GoStruct, body []byte) ([]NamespacePayload, error) { + var nameSpaceFunc string + var nsPayloads []NamespacePayload + + xpath, _, err := XfmrRemoveXPATHPredicates(uri) + if err != nil { + return nil, err + } + + if isSonicYang(uri) { + key := getXdbSpecMapKey(uri) + spec, ok := xDbSpecMap[key] + log.Info("GetNamespace: SONiC YANG - tableName, xDbSpecMap[key]:", key, xDbSpecMap[key]) + if !ok { + errMsg := "xDbSpecMap data not found for xpath: " + xpath + log.Warning(errMsg) + return nil, errors.New(errMsg) + } + nameSpaceFunc = spec.namespaceFunc + } else { + spec, ok := xYangSpecMap[xpath] + if !ok { + errMsg := "xYangSpecMap data not found for xpath: " + xpath + log.Warning(errMsg) + return nil, errors.New(errMsg) + } + nameSpaceFunc = spec.namespaceFunc + } + + // Updated call: use the updated handler returning []NamespacePayload + nsPayloads, err = namespaceHandlerFunc(nameSpaceFunc, uri, ygotRoot, body) + if err != nil { + return nil, err + } + + // If no payloads, add wildcard with empty slice + if len(nsPayloads) == 0 { + nsPayloads = append(nsPayloads, NamespacePayload{ + Namespace: "host", + Payloads: []map[string]interface{}{}, + Key: "", + }) + } + + log.Infof("GetNamespace: xpath %v: nsPayloads %v", xpath, nsPayloads) + return nsPayloads, nil +} diff --git a/translib/transformer/xlate_from_db.go b/translib/transformer/xlate_from_db.go index 7cb36caf3..fc848c608 100644 --- a/translib/transformer/xlate_from_db.go +++ b/translib/transformer/xlate_from_db.go @@ -1483,7 +1483,7 @@ func yangDataFill(inParamsForGet xlateFromDbParams, isOcMdl bool) error { xpath := inParamsForGet.xpath var chldUri string - log.V(5).Infof("yangDataFill: uri: %v; parent obj: %v; inParamsForGet.relUri: %v; xpath: %v", + log.Infof("yangDataFill: uri: %v; parent obj: %v; inParamsForGet.relUri: %v; xpath: %v", inParamsForGet.uri, reflect.TypeOf(*inParamsForGet.ygParentObj), inParamsForGet.relUri, xpath) yangNode, ok := xYangSpecMap[xpath] @@ -1511,7 +1511,7 @@ func yangDataFill(inParamsForGet xlateFromDbParams, isOcMdl bool) error { inParamsForGet.ygSchema = ygotCtx.trgtYgSchema inParamsForGet.relUri = "" } - log.V(5).Infof("yangDataFill: after uri marshalling: uri: %v; parent obj: %v", inParamsForGet.uri, reflect.TypeOf(*inParamsForGet.ygParentObj)) + log.Infof("yangDataFill: after uri marshalling: uri: %v; parent obj: %v", inParamsForGet.uri, reflect.TypeOf(*inParamsForGet.ygParentObj)) } for yangChldName := range yangNode.yangEntry.Dir { @@ -1527,6 +1527,7 @@ func yangDataFill(inParamsForGet xlateFromDbParams, isOcMdl bool) error { inParamsForGet.relUri = "" if xYangSpecMap[chldXpath] != nil && yangNode.yangEntry.Dir[yangChldName] != nil { chldYangType := xYangSpecMap[chldXpath].yangType + if chldYangType == YANG_CONTAINER || chldYangType == YANG_LIST { inParamsForGet.relUri = "/" + yangChldName log.V(5).Infof("yangDataFill: About to process URI : %v, chldYangType: %v; inParamsForGet.relUri: %v, validate-handler-name: %v", @@ -1640,6 +1641,7 @@ func yangDataFill(inParamsForGet xlateFromDbParams, isOcMdl bool) error { if qdbMap, getOk := inParamsForGet.dbTblKeyGetCache[cdb]; getOk { if dbTblData, tblPresent := qdbMap[chtbl]; tblPresent { qdbMapHasTblData = true + if _, keyPresent := dbTblData[tblKey]; keyPresent { qdbMapHasTblKeyData = true } @@ -1741,6 +1743,7 @@ func yangDataFill(inParamsForGet xlateFromDbParams, isOcMdl bool) error { inParamsForGet.dbDataMap = dbDataMap inParamsForGet.ygRoot = ygRoot } else if chldYangType == YANG_LIST { + xpathKeyExtRet, xerr := xpathKeyExtractForGet(dbs[cdb], ygRoot, GET, chldUri, requestUri, dbDataMap, nil, txCache, inParamsForGet.xfmrDbTblKeyCache, dbs) if xerr != nil && len(xpathKeyExtRet.dbKey) == 0 { log.Warningf("yangDataFill: could not convert yang key into db key, error: %v; chldUri: %v", xerr.Error(), chldUri) diff --git a/translib/transformer/xlate_to_db.go b/translib/transformer/xlate_to_db.go index 890ca1618..7fd3601a5 100644 --- a/translib/transformer/xlate_to_db.go +++ b/translib/transformer/xlate_to_db.go @@ -1381,7 +1381,7 @@ func verifyParentTable(d *db.DB, dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, op } } -func verifyParentTblSubtree(dbs [db.MaxDB]*db.DB, uri string, xfmrFuncNm string, oper Operation, dbData RedisDbMap) (bool, error) { +func verifyParentTblSubtree(nameSpace string, dbs [db.MaxDB]*db.DB, uri string, xfmrFuncNm string, oper Operation, dbData RedisDbMap) (bool, error) { var inParams XfmrSubscInParams inParams.uri = uri inParams.dbDataMap = make(RedisDbMap) @@ -1416,7 +1416,7 @@ func verifyParentTblSubtree(dbs [db.MaxDB]*db.DB, uri string, xfmrFuncNm string, // Infra MUST always pass ConfigDB handle (for bulk & config session usecase) err = tlerr.New("DB access failure") } else { - dptr, err = db.NewDB(getDBOptions(dbNo)) + dptr, err = db.NewDB(getDBOptions(dbNo, SetMDBName(nameSpace))) defer dptr.DeleteDB() } if err != nil { @@ -1517,7 +1517,7 @@ func verifyParentTableOc(d *db.DB, dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, if len(curXpathInfo.xfmrFunc) > 0 { xfmrLogDebug("Found subtree for URI - %v", curUri) stParentTblExists := false - stParentTblExists, err = verifyParentTblSubtree(dbs, curUri, curXpathInfo.xfmrFunc, oper, dbData) + stParentTblExists, err = verifyParentTblSubtree(d.Opts.MDBName, dbs, curUri, curXpathInfo.xfmrFunc, oper, dbData) if err != nil { parentTblExists = false break @@ -1608,7 +1608,7 @@ func verifyParentTableOc(d *db.DB, dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, return true, nil } xfmrLogDebug("Found subtree for URI - %v", uri) - parentTblExists, err = verifyParentTblSubtree(dbs, uri, xpathInfo.xfmrFunc, oper, dbData) + parentTblExists, err = verifyParentTblSubtree(d.Opts.MDBName, dbs, uri, xpathInfo.xfmrFunc, oper, dbData) if err != nil { return false, err } @@ -1758,3 +1758,10 @@ func printDbData(resMap map[Operation]map[db.DBNum]map[string]map[string]db.Valu } fmt.Fprintf(fp, "-----------------------------------------------------------------\r\n") } + +// Define a new function to set the MDBName in Options +func SetMDBName(nameSpace string) func(*db.Options) { + return func(o *db.Options) { + o.MDBName = nameSpace + } +} diff --git a/translib/transformer/xlate_utils.go b/translib/transformer/xlate_utils.go index e3966dad3..9d4e48d83 100644 --- a/translib/transformer/xlate_utils.go +++ b/translib/transformer/xlate_utils.go @@ -642,6 +642,10 @@ func getDBOptions(dbNo db.DBNum, opts ...func(*db.Options)) db.Options { for _, setopt := range opts { setopt(&opt) } + // If MDBName is not set, use the default nameSpace value + if opt.MDBName == "" { + opt.MDBName = "host" + } return opt } @@ -958,12 +962,12 @@ func xpathKeyExtractForGet(d *db.DB, ygRoot *ygot.GoStruct, oper Operation, path tblKeyInfo, tblKeyOk = xfmrTblKeyCache[retData.xpath] } - if tblKeyOk { + if tblKeyOk && tblKeyInfo.ygXpathInfo != nil { ygXpathInfo = tblKeyInfo.ygXpathInfo curPathWithKey = strings.Join(pathList[:tblKeyInfo.pathIdx], "/") pathIdx = tblKeyInfo.pathIdx childListNodePathIdx = tblKeyInfo.childListNodePathIdx - log.V(5).Infof("xpathKeyExtractForGet: found key xfmr: %v in cache; retData.xpath: %v; pathIdx: %v;"+ + log.V(5).Infof("xpathKeyExtractForGet: found key xfmr: %v in cache; retData.xpath: %v; pathIdx: %v;"+ " childListNodePathIdx: %v; curPathWithKey: %v", ygXpathInfo.xfmrKey, retData.xpath, pathIdx, childListNodePathIdx, curPathWithKey) } else { for len(ygXpathInfo.xfmrKey) == 0 { diff --git a/translib/transformer/xlate_xfmr_handler.go b/translib/transformer/xlate_xfmr_handler.go index 19c69a49f..a1ac9b5e4 100644 --- a/translib/transformer/xlate_xfmr_handler.go +++ b/translib/transformer/xlate_xfmr_handler.go @@ -21,6 +21,7 @@ package transformer import ( "github.com/Azure/sonic-mgmt-common/translib/db" log "github.com/golang/glog" + "github.com/openconfig/ygot/ygot" ) func xfmrHandlerFunc(inParams XfmrParams, xfmrFuncNm string, ygotCtx *ygotUnMarshalCtx) error { @@ -144,6 +145,38 @@ func validateHandlerFunc(inParams XfmrParams, validateFuncNm string) bool { return result } +func namespaceHandlerFunc(namespaceFuncNm string, uri string, ygotRoot *ygot.GoStruct, body []byte) ([]NamespacePayload, error) { + var inParams XfmrParams + inParams.uri = uri + inParams.ygRoot = ygotRoot + inParams.body = body + + ret, err := XlateFuncCall(namespaceFuncNm, inParams) + if err != nil { + return nil, err + } + + var nsPayloads []NamespacePayload + + if len(ret) > 0 && ret != nil { + val := ret[0].Interface() + + if castedPayloads, ok := val.([]NamespacePayload); ok { + nsPayloads = castedPayloads + } else if namespaces, ok := val.([]string); ok { + for _, ns := range namespaces { + nsPayloads = append(nsPayloads, NamespacePayload{ + Namespace: ns, + Payloads: []map[string]interface{}{}, + }) + } + } + } + + xfmrLogDebug("Namespace transformer returned %v", nsPayloads) + return nsPayloads, nil +} + func xfmrTblHandlerFunc(xfmrTblFunc string, inParams XfmrParams, xfmrTblKeyCache map[string]tblKeyCache) ([]string, error) { const ( TBL_XFMR_RET_ARGS = 2 diff --git a/translib/transformer/xspec.go b/translib/transformer/xspec.go index d306ab942..9c35a7c67 100644 --- a/translib/transformer/xspec.go +++ b/translib/transformer/xspec.go @@ -55,6 +55,7 @@ type yangXpathInfo struct { xfmrFunc string xfmrField string validateFunc string + namespaceFunc string xfmrKey string keyName *string dbIndex db.DBNum @@ -79,21 +80,22 @@ type yangXpathInfo struct { } type dbInfo struct { - dbIndex db.DBNum - keyName *string - dbEntry *yang.Entry - yangXpath []string - module string - delim string - leafRefPath []string - listName []string - keyList []string - xfmrKey string - xfmrValue *string - hasXfmrFn bool - cascadeDel int8 - yangType yangElementType - isKey bool + dbIndex db.DBNum + keyName *string + dbEntry *yang.Entry + yangXpath []string + module string + delim string + leafRefPath []string + listName []string + keyList []string + xfmrKey string + xfmrValue *string + hasXfmrFn bool + cascadeDel int8 + yangType yangElementType + isKey bool + namespaceFunc string } type moduleAnnotInfo struct { @@ -357,6 +359,10 @@ func yangToDbMapFill(keyLevel uint8, xYangSpecMap map[string]*yangXpathInfo, ent xpathData.validateFunc = parentXpathData.validateFunc } + if ok && len(parentXpathData.namespaceFunc) > 0 { + xpathData.namespaceFunc = parentXpathData.namespaceFunc + } + if ok && len(parentXpathData.xfmrFunc) > 0 && len(xpathData.xfmrFunc) == 0 { xpathData.xfmrFunc = parentXpathData.xfmrFunc } @@ -940,6 +946,8 @@ func annotEntryFill(xYangSpecMap map[string]*yangXpathInfo, xpath string, entry xYangModSpecMap[xpath].xfmrPre = ext.NName() case "validate-xfmr": xpathData.validateFunc = ext.NName() + case "get-namespace": + xpathData.namespaceFunc = ext.NName() case "rpc-callback": xYangRpcSpecMap[xpath] = ext.NName() xpathData.yangType = YANG_RPC @@ -1061,9 +1069,39 @@ func annotDbSpecMapFill(xDbSpecMap map[string]*dbInfo, dbXpath string, entry *ya var err error var dbXpathData *dbInfo var ok bool + var tableName string pname := strings.Split(dbXpath, "/") - if len(pname) < 3 { + + if len(pname) == 2 { + //Populating getnamespace function name for topLevel container + tableName = pname[1] + for key := range xDbSpecMap { + // Check if the key starts with the tableName + if strings.Contains(key, tableName) { + tableName = key + break + } + } + dbXpathData, ok = xDbSpecMap[tableName] + if !ok { + log.Warningf("DB spec-map data not found(%v) \r\n", dbXpath) + return err + } + if entry != nil && len(entry.Exts) > 0 { + for _, ext := range entry.Exts { + dataTagArr := strings.Split(ext.Keyword, ":") + tagType := dataTagArr[len(dataTagArr)-1] + switch tagType { + case "get-namespace": + dbXpathData.namespaceFunc = ext.NName() + + default: + } + } + } + + } else if len(pname) < 3 { // check rpc? if entry != nil && len(entry.Exts) > 0 { for _, ext := range entry.Exts { @@ -1079,50 +1117,53 @@ func annotDbSpecMapFill(xDbSpecMap map[string]*dbInfo, dbXpath string, entry *ya log.Warningf("DB Rpc spec-map doesn't contain rpc entry(%v) \r\n", dbXpath) } return err - } - tableName := pname[2] - // container(redis tablename) - dbXpathData, ok = xDbSpecMap[tableName] - if !ok { - log.Warningf("DB spec-map data not found(%v) \r\n", dbXpath) - return err - } + } else { + tableName = pname[2] - if dbXpathData.dbIndex >= db.MaxDB { - dbXpathData.dbIndex = db.ConfigDB // default value - } + // container(redis tablename) + dbXpathData, ok = xDbSpecMap[tableName] - /* fill table with cvl yang extension data. */ - if entry != nil && len(entry.Exts) > 0 { - for _, ext := range entry.Exts { - dataTagArr := strings.Split(ext.Keyword, ":") - tagType := dataTagArr[len(dataTagArr)-1] - switch tagType { - case "key-name": - if dbXpathData.keyName == nil { - dbXpathData.keyName = new(string) - } - *dbXpathData.keyName = ext.NName() - case "value-transformer": - fieldName := pname[len(pname)-1] - fieldXpath := tableName + "/" + fieldName - if fldXpathData, ok := xDbSpecMap[fieldXpath]; ok { - fldXpathData.xfmrValue = new(string) - *fldXpathData.xfmrValue = ext.NName() - dbXpathData.hasXfmrFn = true - if xpathList, ok := sonicLeafRefMap[fieldXpath]; ok { - for _, curpath := range xpathList { - if curSpecData, ok := xDbSpecMap[curpath]; ok && curSpecData.xfmrValue == nil { - curSpecData.xfmrValue = fldXpathData.xfmrValue - curTableName := strings.Split(curpath, "/")[0] - if curTblSpecInfo, ok := xDbSpecMap[curTableName]; ok { - curTblSpecInfo.hasXfmrFn = true + if !ok { + log.Warningf("DB spec-map data not found(%v) \r\n", dbXpath) + return err + } + + if dbXpathData.dbIndex >= db.MaxDB { + dbXpathData.dbIndex = db.ConfigDB // default value + } + + /* fill table with cvl yang extension data. */ + if entry != nil && len(entry.Exts) > 0 { + for _, ext := range entry.Exts { + dataTagArr := strings.Split(ext.Keyword, ":") + tagType := dataTagArr[len(dataTagArr)-1] + switch tagType { + case "key-name": + if dbXpathData.keyName == nil { + dbXpathData.keyName = new(string) + } + *dbXpathData.keyName = ext.NName() + case "value-transformer": + fieldName := pname[len(pname)-1] + fieldXpath := tableName + "/" + fieldName + if fldXpathData, ok := xDbSpecMap[fieldXpath]; ok { + fldXpathData.xfmrValue = new(string) + *fldXpathData.xfmrValue = ext.NName() + dbXpathData.hasXfmrFn = true + if xpathList, ok := sonicLeafRefMap[fieldXpath]; ok { + for _, curpath := range xpathList { + if curSpecData, ok := xDbSpecMap[curpath]; ok && curSpecData.xfmrValue == nil { + curSpecData.xfmrValue = fldXpathData.xfmrValue + curTableName := strings.Split(curpath, "/")[0] + if curTblSpecInfo, ok := xDbSpecMap[curTableName]; ok { + curTblSpecInfo.hasXfmrFn = true + } } } } } - } + case "cascade-delete": fieldName := pname[len(pname)-1] fieldXpath := tableName + "/" + fieldName @@ -1144,7 +1185,12 @@ func annotDbSpecMapFill(xDbSpecMap map[string]*dbInfo, dbXpath string, entry *ya listXpathData.xfmrKey = ext.NName() } - default: + case "get-namespace": + dbXpathData.namespaceFunc = ext.NName() + + default: + + } } } } @@ -1244,6 +1290,7 @@ func mapPrint(fileName string) { fmt.Fprintf(fp, "\r\n xfmrField :%v", d.xfmrField) fmt.Fprintf(fp, "\r\n dbIndex : %v", d.dbIndex) fmt.Fprintf(fp, "\r\n validateFunc : %v", d.validateFunc) + fmt.Fprintf(fp, "\r\n namespaceFunc : %v", d.namespaceFunc) fmt.Fprintf(fp, "\r\n yangEntry: ") if d.yangEntry != nil { fmt.Fprintf(fp, "%v", *d.yangEntry) diff --git a/translib/translib.go b/translib/translib.go index efa69f6f7..70be9382b 100644 --- a/translib/translib.go +++ b/translib/translib.go @@ -35,13 +35,17 @@ package translib import ( "context" - "sync" - + "encoding/json" + "errors" + //"fmt" "github.com/Azure/sonic-mgmt-common/translib/db" "github.com/Azure/sonic-mgmt-common/translib/tlerr" "github.com/Workiva/go-datastructures/queue" log "github.com/golang/glog" "github.com/openconfig/ygot/ygot" + //"os" + //"path/filepath" + "sync" ) // Write lock for all write operations to be synchronized @@ -54,6 +58,11 @@ const ( AppErr ) +const ( + TYPE_ACTION = "Action" + TYPE_GET = "Get" +) + type TranslibFmtType int const ( @@ -152,10 +161,120 @@ func init() { log.Flush() } +func ResponseError(optype string, payload []byte, errorType ErrSource) interface{} { + if optype == TYPE_GET { + allResp := make([]GetResponse, 1) + allResp[0] = GetResponse{Payload: payload, ErrSrc: errorType} + return allResp + } else { + allResp := make([]ActionResponse, 1) + allResp[0] = ActionResponse{Payload: payload, ErrSrc: errorType} + return allResp + } +} + +func commitTransactions(redisMdbInstances map[string]*db.DB, nsMaps []NamespacePayload) error { + total := len(redisMdbInstances) + i := 0 + for ns, redisDbInstance := range redisMdbInstances { + i++ + + if err := redisDbInstance.CommitTx(); err != nil { + return err + } + + // Find the NamespaceMap with Namespace == ns and mark committed + for i := range nsMaps { + if nsMaps[i].Namespace == ns { + nsMaps[i].Commited = true + } + } + + // Purposefully fail on last iteration + if i == total { + // err := fmt.Errorf("Intentional failure on last iteration: %s", ns) + // return tlerr.InvalidArgsError{Format: err.Error()} + } + + } + + return nil +} + +func abortTransactions(redisMdbInstances map[string]*db.DB) error { + + for _, redisDbInstance := range redisMdbInstances { + + if err := redisDbInstance.AbortTx(); err != nil { + log.Infof("Abort transaction failed for %s: %v", redisDbInstance, err) + return err + } + } + return nil +} + +func initializeMDBInstance(mdbName string, redisMdbInstances map[string]*db.DB) (*db.DB, error) { + var d *db.DB + // Check if the MDB instance already exists in the map + if existingInstance, exists := redisMdbInstances[mdbName]; !exists { + var err error + d, err = db.NewDB(getDBOptions(db.ConfigDB, SetMDBName(mdbName))) + if err != nil { + return nil, err + } + + err = d.StartTx(nil, nil) + if err != nil { + return nil, err + } + + redisMdbInstances[mdbName] = d + } else { + d = existingInstance + } + return d, nil +} + +func processPostPhase() error { + log.Infof("Cleanup: deleting all backup files from /tmp") + /* + // Match all files with pattern: /tmp/common_backup_*.json + backupFiles, err := filepath.Glob("/var/tmp/common_backup_*.json") + if err != nil { + log.Infof("Failed to list backup files: %v", err) + return err + } + + if len(backupFiles) == 0 { + log.Infof("No backup files found to delete.") + return nil + } + + for _, file := range backupFiles { + err := os.Remove(file) + if err != nil { + log.Infof("Failed to delete backup file: %s, error: %v", file, err) + return err + } + log.Infof("Deleted backup file: %s", file) + } + */ + return nil +} + // Create - Creates entries in the redis DB pertaining to the path and payload func Create(req SetRequest) (SetResponse, error) { var keys []db.WatchKeys var resp SetResponse + var d *db.DB + + // Define a map to hold multiple Redis DB instances with mdbName as key + var redisMdbInstances map[string]*db.DB + + if redisMdbInstances == nil { + redisMdbInstances = make(map[string]*db.DB) + } + path := req.Path payload := req.Payload if !isAuthorizedForSet(req) { @@ -182,53 +301,161 @@ func Create(req SetRequest) (SetResponse, error) { return resp, err } + namespacePayloads, err := (*app).getNamespace(path) + + if err != nil { + log.Infof("Error from getNamespace %v", err) + resp.ErrSrc = AppErr + return resp, tlerr.InvalidArgsError{Format: err.Error()} + } + writeMutex.Lock() defer writeMutex.Unlock() - d, err := db.NewDB(getDBOptions(db.ConfigDB)) + for _, nsPayload := range namespacePayloads { + nameSpace := nsPayload.Namespace + payloads := nsPayload.Payloads + if len(payloads) == 0 { + log.Infof("Payloads for namespace '%s' are empty, using top-level payload", nameSpace) + + var topLevelPayload map[string]interface{} + err := json.Unmarshal(payload, &topLevelPayload) + if err != nil { + resp.ErrSrc = AppErr + log.Errorf("Failed to unmarshal top-level payload: %v", err) + return resp, err + } - if err != nil { - resp.ErrSrc = ProtoErr - return resp, err - } + payloads = append(payloads, topLevelPayload) + } - defer d.DeleteDB() + log.Infof("Namespace: %s", nameSpace) - keys, err = (*app).translateCreate(d) + for _, payload := range payloads { - if err != nil { - resp.ErrSrc = AppErr - return resp, err - } + payloadBytes, err := json.Marshal(payload) + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } - err = d.StartTx(keys, appInfo.tablesToWatch) + err = appInitialize(app, appInfo, path, &payloadBytes, nil, CREATE) + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } - if err != nil { - resp.ErrSrc = AppErr - return resp, err - } + d, err = initializeMDBInstance(nameSpace, redisMdbInstances) - resp, err = (*app).processCreate(d) + if err != nil { + resp.ErrSrc = ProtoErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + defer d.DeleteDB() - if err != nil { - d.AbortTx() - resp.ErrSrc = AppErr - return resp, err - } + keys, err = (*app).translateCreate(d) - err = d.CommitTx() + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + err = d.AppendWatchTx(keys, appInfo.tablesToWatch) + + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + err = (*app).processPreparePhase(d, nsPayload.Key) + + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + resp, err = (*app).processCreate(d) + + if err != nil { + d.AbortTx() + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + // Check if the entry with the same nameSpace already exists in the map + if _, exists := redisMdbInstances[nameSpace]; !exists { + redisMdbInstances[nameSpace] = d + } + + } + } + + cerr := commitTransactions(redisMdbInstances, namespacePayloads) + + if cerr != nil { + for ns, redisDbInstance := range redisMdbInstances { + for _, payload := range namespacePayloads { + if payload.Namespace == ns && payload.Commited { + // Pass the payload.Key for rollback + log.Infof("Rollback key:%v,Namespace: %s", payload.Namespace, payload.Key) + err = (*app).rollback(redisDbInstance) + if err != nil { + log.Infof("Rollback operation failed!") + } + } + } + } + } + err = processPostPhase() if err != nil { - resp.ErrSrc = AppErr + log.Infof("Cleanup of backup entries operation failed!") } - return resp, err + return resp, cerr + } // Update - Updates entries in the redis DB pertaining to the path and payload func Update(req SetRequest) (SetResponse, error) { var keys []db.WatchKeys var resp SetResponse + var d *db.DB + + // Define a map to hold multiple Redis DB instances with mdbName as key + var redisMdbInstances map[string]*db.DB + + if redisMdbInstances == nil { + redisMdbInstances = make(map[string]*db.DB) + } + path := req.Path payload := req.Payload if !isAuthorizedForSet(req) { @@ -254,48 +481,147 @@ func Update(req SetRequest) (SetResponse, error) { resp.ErrSrc = AppErr return resp, err } + namespacePayloads, err := (*app).getNamespace(path) + + if err != nil { + log.Infof("Error from getNamespace %v", err) + resp.ErrSrc = AppErr + return resp, tlerr.InvalidArgsError{Format: err.Error()} + } writeMutex.Lock() defer writeMutex.Unlock() - d, err := db.NewDB(getDBOptions(db.ConfigDB)) + for _, nsPayload := range namespacePayloads { + nameSpace := nsPayload.Namespace + payloads := nsPayload.Payloads + if len(payloads) == 0 { + log.Infof("Payloads for namespace '%s' are empty, using top-level payload", nameSpace) + + var topLevelPayload map[string]interface{} + err := json.Unmarshal(payload, &topLevelPayload) + if err != nil { + resp.ErrSrc = AppErr + log.Errorf("Failed to unmarshal top-level payload: %v", err) + return resp, err + } - if err != nil { - resp.ErrSrc = ProtoErr - return resp, err - } + payloads = append(payloads, topLevelPayload) + } - defer d.DeleteDB() + log.Infof("Namespace: %s", nameSpace) - keys, err = (*app).translateUpdate(d) + for _, payload := range payloads { - if err != nil { - resp.ErrSrc = AppErr - return resp, err - } + payloadBytes, err := json.Marshal(payload) + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } - err = d.StartTx(keys, appInfo.tablesToWatch) + err = appInitialize(app, appInfo, path, &payloadBytes, nil, UPDATE) - if err != nil { - resp.ErrSrc = AppErr - return resp, err - } + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } - resp, err = (*app).processUpdate(d) + d, err = initializeMDBInstance(nameSpace, redisMdbInstances) - if err != nil { - d.AbortTx() - resp.ErrSrc = AppErr - return resp, err - } + if err != nil { + resp.ErrSrc = ProtoErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + defer d.DeleteDB() + + keys, err = (*app).translateUpdate(d) + + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + err = d.AppendWatchTx(keys, appInfo.tablesToWatch) + + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + err = (*app).processPreparePhase(d, nsPayload.Key) + + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } - err = d.CommitTx() + resp, err = (*app).processUpdate(d) + if err != nil { + d.AbortTx() + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + // Check if the entry with the same nameSpace already exists in the map + if _, exists := redisMdbInstances[nameSpace]; !exists { + redisMdbInstances[nameSpace] = d + } + + } + } + + cerr := commitTransactions(redisMdbInstances, namespacePayloads) + + if cerr != nil { + for ns, redisDbInstance := range redisMdbInstances { + for _, payload := range namespacePayloads { + if payload.Namespace == ns && payload.Commited { + // Pass the payload.Key for rollback + log.Infof("Rollback key:%v,Namespace: %s", payload.Namespace, payload.Key) + err = (*app).rollback(redisDbInstance) + if err != nil { + log.Infof("Rollback operation failed!") + } + } + } + } + } + err = processPostPhase() if err != nil { - resp.ErrSrc = AppErr + log.Infof("Cleanup of backup entries operation failed!") } - return resp, err + return resp, cerr + } // Replace - Replaces entries in the redis DB pertaining to the path and payload @@ -303,6 +629,15 @@ func Replace(req SetRequest) (SetResponse, error) { var err error var keys []db.WatchKeys var resp SetResponse + var d *db.DB + + // Define a map to hold multiple Redis DB instances with mdbName as key + var redisMdbInstances map[string]*db.DB + + if redisMdbInstances == nil { + redisMdbInstances = make(map[string]*db.DB) + } + path := req.Path payload := req.Payload if !isAuthorizedForSet(req) { @@ -312,9 +647,6 @@ func Replace(req SetRequest) (SetResponse, error) { } } - log.Info("Replace request received with path =", path) - log.Info("Replace request received with payload =", string(payload)) - app, appInfo, err := getAppModule(path, req.ClientVersion) if err != nil { @@ -322,6 +654,9 @@ func Replace(req SetRequest) (SetResponse, error) { return resp, err } + log.Info("Replace request received with path =", path) + log.Info("Replace request received with payload =", string(payload)) + err = appInitialize(app, appInfo, path, &payload, nil, REPLACE) if err != nil { @@ -329,54 +664,162 @@ func Replace(req SetRequest) (SetResponse, error) { return resp, err } + namespacePayloads, err := (*app).getNamespace(path) + + if err != nil { + log.Infof("Error from getNamespace %v", err) + resp.ErrSrc = AppErr + return resp, tlerr.InvalidArgsError{Format: err.Error()} + } + writeMutex.Lock() defer writeMutex.Unlock() - d, err := db.NewDB(getDBOptions(db.ConfigDB)) + for _, nsPayload := range namespacePayloads { + nameSpace := nsPayload.Namespace + payloads := nsPayload.Payloads + if len(payloads) == 0 { + log.Infof("Payloads for namespace '%s' are empty, using top-level payload", nameSpace) + + var topLevelPayload map[string]interface{} + err := json.Unmarshal(payload, &topLevelPayload) + if err != nil { + resp.ErrSrc = AppErr + log.Errorf("Failed to unmarshal top-level payload: %v", err) + return resp, err + } - if err != nil { - resp.ErrSrc = ProtoErr - return resp, err - } + payloads = append(payloads, topLevelPayload) + } - defer d.DeleteDB() + log.Infof("Namespace: %s", nameSpace) - keys, err = (*app).translateReplace(d) + for _, payload := range payloads { - if err != nil { - resp.ErrSrc = AppErr - return resp, err - } + payloadBytes, err := json.Marshal(payload) + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } - err = d.StartTx(keys, appInfo.tablesToWatch) + err = appInitialize(app, appInfo, path, &payloadBytes, nil, REPLACE) - if err != nil { - resp.ErrSrc = AppErr - return resp, err - } + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } - resp, err = (*app).processReplace(d) + d, err = initializeMDBInstance(nameSpace, redisMdbInstances) - if err != nil { - d.AbortTx() - resp.ErrSrc = AppErr - return resp, err - } + if err != nil { + resp.ErrSrc = ProtoErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + defer d.DeleteDB() + + keys, err = (*app).translateReplace(d) + + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + err = d.AppendWatchTx(keys, appInfo.tablesToWatch) + + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + err = (*app).processPreparePhase(d, nsPayload.Key) + + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + resp, err = (*app).processReplace(d) + + if err != nil { + d.AbortTx() + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } - err = d.CommitTx() + // Check if the entry with the same nameSpace already exists in the map + if _, exists := redisMdbInstances[nameSpace]; !exists { + redisMdbInstances[nameSpace] = d + } + + } + } + cerr := commitTransactions(redisMdbInstances, namespacePayloads) + + if cerr != nil { + for ns, redisDbInstance := range redisMdbInstances { + for _, payload := range namespacePayloads { + if payload.Namespace == ns && payload.Commited { + // Pass the payload.Key for rollback + log.Infof("Rollback key:%v,Namespace: %s", payload.Namespace, payload.Key) + err = (*app).rollback(redisDbInstance) + if err != nil { + log.Infof("Rollback operation failed!") + } + } + } + } + } + err = processPostPhase() if err != nil { - resp.ErrSrc = AppErr + log.Infof("Cleanup of backup entries operation failed!") } - return resp, err + return resp, cerr } // Delete - Deletes entries in the redis DB pertaining to the path func Delete(req SetRequest) (SetResponse, error) { var err error - var keys []db.WatchKeys var resp SetResponse + var keys []db.WatchKeys + var d *db.DB + + // Define a map to hold multiple Redis DB instances with mdbName as key + var redisMdbInstances map[string]*db.DB + + if redisMdbInstances == nil { + redisMdbInstances = make(map[string]*db.DB) + } + path := req.Path if !isAuthorizedForSet(req) { return resp, tlerr.AuthorizationError{ @@ -395,6 +838,7 @@ func Delete(req SetRequest) (SetResponse, error) { } opts := appOptions{deleteEmptyEntry: req.DeleteEmptyEntry} + err = appInitialize(app, appInfo, path, nil, &opts, DELETE) if err != nil { @@ -402,56 +846,152 @@ func Delete(req SetRequest) (SetResponse, error) { return resp, err } + namespacePayloads, err := (*app).getNamespace(path) + + if err != nil { + log.Infof("Error from getNamespace %v", err) + resp.ErrSrc = AppErr + return resp, tlerr.InvalidArgsError{Format: err.Error()} + } + + // Fetching the DBNames to iterate if getNamespace returned * + // if keys is not present in xpath of GetRequest. + if len(namespacePayloads) == 1 && namespacePayloads[0].Namespace == "*" { + allNamespaces := db.GetMultiDbNames() + key := namespacePayloads[0].Key + namespacePayloads = nil + for _, ns := range allNamespaces { + namespacePayloads = append(namespacePayloads, NamespacePayload{ + Namespace: ns, + Payloads: nil, // no payload needed for delete + Key: key, // preserve original key * + }) + } + + } + writeMutex.Lock() defer writeMutex.Unlock() - d, err := db.NewDB(getDBOptions(db.ConfigDB)) + for _, nsPayload := range namespacePayloads { - if err != nil { - resp.ErrSrc = ProtoErr - return resp, err - } + opts := appOptions{deleteEmptyEntry: req.DeleteEmptyEntry} - defer d.DeleteDB() + err = appInitialize(app, appInfo, path, nil, &opts, DELETE) - keys, err = (*app).translateDelete(d) + if err != nil { + resp.ErrSrc = AppErr + return resp, err + } - if err != nil { - resp.ErrSrc = AppErr - return resp, err - } + nameSpace := nsPayload.Namespace - err = d.StartTx(keys, appInfo.tablesToWatch) + log.Infof("Namespace: %s", nameSpace) - if err != nil { - resp.ErrSrc = AppErr - return resp, err - } + log.Info("Delete operation going to be performed on ", nameSpace) + d, err = initializeMDBInstance(nameSpace, redisMdbInstances) + + if err != nil { + resp.ErrSrc = ProtoErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + defer d.DeleteDB() - resp, err = (*app).processDelete(d) + keys, err = (*app).translateDelete(d) - if err != nil { - d.AbortTx() - resp.ErrSrc = AppErr - return resp, err + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + err = d.AppendWatchTx(keys, appInfo.tablesToWatch) + + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + log.Infof("Calling processPreparePhase") + err = (*app).processPreparePhase(d, nsPayload.Key) + log.Infof("Return processPreparePhase") + + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + resp, err = (*app).processDelete(d) + + if err != nil { + d.AbortTx() + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + // Check if the entry with the same nameSpace already exists in the map + if _, exists := redisMdbInstances[nameSpace]; !exists { + redisMdbInstances[nameSpace] = d + } } - err = d.CommitTx() + cerr := commitTransactions(redisMdbInstances, namespacePayloads) + if cerr != nil { + for ns, redisDbInstance := range redisMdbInstances { + for _, payload := range namespacePayloads { + if payload.Namespace == ns && payload.Commited { + // Pass the payload.Key for rollback + log.Infof("Rollback key:%v,Namespace: %s", payload.Namespace, payload.Key) + err = (*app).rollback(redisDbInstance) + if err != nil { + log.Infof("Rollback operation failed!") + } + } + } + } + } + err = processPostPhase() if err != nil { - resp.ErrSrc = AppErr + log.Infof("Cleanup of backup entries operation failed!") } - return resp, err + return resp, cerr + } // Get - Gets data from the redis DB and converts it to northbound format -func Get(req GetRequest) (GetResponse, error) { +func Get(req GetRequest) ([]GetResponse, error) { var payload []byte + var allResp []GetResponse var resp GetResponse + var mdb map[string][db.MaxDB]*db.DB + allErrors := true + var errorSrc ErrSource + var nameSpaces []string + path := req.Path if !isAuthorizedForGet(req) { - return resp, tlerr.AuthorizationError{ + return allResp, tlerr.AuthorizationError{ Format: "User is unauthorized for Get Operation", Path: path, } @@ -462,46 +1002,122 @@ func Get(req GetRequest) (GetResponse, error) { app, appInfo, err := getAppModule(path, req.ClientVersion) if err != nil { - resp = GetResponse{Payload: payload, ErrSrc: ProtoErr} - return resp, err + allResp := ResponseError(TYPE_GET, payload, ProtoErr) + return allResp.([]GetResponse), err } opts := appOptions{depth: req.QueryParams.Depth, content: req.QueryParams.Content, fields: req.QueryParams.Fields, ctxt: req.Ctxt} err = appInitialize(app, appInfo, path, nil, &opts, GET) if err != nil { - resp = GetResponse{Payload: payload, ErrSrc: AppErr} - return resp, err + allResp := ResponseError(TYPE_GET, payload, AppErr) + return allResp.([]GetResponse), err } - dbs, err := getAllDbs(withWriteDisable) + namespacePayloads, err := (*app).getNamespace(path) if err != nil { - resp = GetResponse{Payload: payload, ErrSrc: ProtoErr} - return resp, err + log.Infof("Error from getNamespace %v", err) + allResp := ResponseError(TYPE_GET, payload, AppErr) + return allResp.([]GetResponse), err } - defer closeAllDbs(dbs[:]) + // Fetching the DBNames to iterate if getNamespace returned * + // if keys is not present in xpath of GetRequest. + if len(namespacePayloads) == 1 && namespacePayloads[0].Namespace == "*" { + nameSpaces = db.GetMultiDbNames() + } else { + nameSpaces = append(nameSpaces, namespacePayloads[0].Namespace) //Specfic key Get operation. + } - err = (*app).translateGet(dbs) + for _, nameSpace := range nameSpaces { - if err != nil { - resp = GetResponse{Payload: payload, ErrSrc: AppErr} - return resp, err - } + opts := appOptions{depth: req.QueryParams.Depth, content: req.QueryParams.Content, fields: req.QueryParams.Fields, ctxt: req.Ctxt} + err = appInitialize(app, appInfo, path, nil, &opts, GET) + + if err != nil { + allResp := ResponseError(TYPE_GET, payload, AppErr) + return allResp.([]GetResponse), err + } + + mdb, err = getAllMdbs(withWriteDisable) + + if err != nil { + allResp := ResponseError(TYPE_GET, payload, ProtoErr) + return allResp.([]GetResponse), err + } + + defer closeAllMdbs(mdb) - resp, err = (*app).processGet(dbs, req.FmtType) + err = (*app).translateGet(mdb[nameSpace]) + + if err != nil { + allResp := ResponseError(TYPE_GET, payload, AppErr) + return allResp.([]GetResponse), err + } + + log.Infof("Process Get for nameSpace:%v ", nameSpace) + + resp, err = (*app).processGet(mdb[nameSpace], req.FmtType) + + if len(resp.Payload) > 0 && err == nil { + // Unmarshal the payload to check if it's an empty object + var jsonObj map[string]interface{} + err := json.Unmarshal(resp.Payload, &jsonObj) + if err != nil { + log.Errorf("Error unmarshalling response payload: %v", err) + return allResp, err + } + + // Check if the payload is an empty JSON object + if len(jsonObj) > 0 { + // Only append if the response is not an empty JSON object + allResp = append(allResp, GetResponse{ + Payload: resp.Payload, + ErrSrc: resp.ErrSrc, + }) + log.Infof("\n ProcessGet Response appending: %v", resp.Payload) + log.Infof("\n ProcessGet Response after appending: %v", allResp) + allErrors = false + } else { + log.Infof("Empty JSON object received, not appending.") + } + + } else { + if err != nil { + if err.Error() != "Resource not found" { + return allResp, err + } + if errorSrc == 0 { + errorSrc = resp.ErrSrc + } + } + } + } + // If all processGet calls resulted in Resource not found, + // update ErrSrc for each response + if allErrors { + for i := range allResp { + allResp[i].ErrSrc = errorSrc + } + } else { + // Since processGet didnt fail for all redis namesSpace + err = nil + } - return resp, err + return allResp, err } -func Action(req ActionRequest) (ActionResponse, error) { +func Action(req ActionRequest) ([]ActionResponse, error) { var payload []byte + var allResp []ActionResponse var resp ActionResponse + var nameSpaces []string + path := req.Path if !isAuthorizedForAction(req) { - return resp, tlerr.AuthorizationError{ + return allResp, tlerr.AuthorizationError{ Format: "User is unauthorized for Action Operation", Path: path, } @@ -512,55 +1128,91 @@ func Action(req ActionRequest) (ActionResponse, error) { app, appInfo, err := getAppModule(path, req.ClientVersion) if err != nil { - resp = ActionResponse{Payload: payload, ErrSrc: ProtoErr} - return resp, err + allResp := ResponseError(TYPE_ACTION, payload, ProtoErr) + return allResp.([]ActionResponse), err } aInfo := *appInfo aInfo.isNative = true - err = appInitialize(app, &aInfo, path, &req.Payload, nil, GET) + err = appInitialize(app, &aInfo, path, &payload, nil, GET) if err != nil { - resp = ActionResponse{Payload: payload, ErrSrc: AppErr} - return resp, err + allResp := ResponseError(TYPE_ACTION, payload, AppErr) + return allResp.([]ActionResponse), err + } + + namespacePayloads, err := (*app).getNamespace(path) + + if err != nil { + log.Infof("Error from getNamespace %v", err) + allResp := ResponseError(TYPE_ACTION, payload, AppErr) + return allResp.([]ActionResponse), err + } + + // Fetching the DBNames to iterate if getNamespace returned * + // if keys is not present in xpath of GetRequest. + if len(namespacePayloads) == 1 && namespacePayloads[0].Namespace == "*" { + nameSpaces = db.GetMultiDbNames() } writeMutex.Lock() defer writeMutex.Unlock() - dbs, err := getAllDbs() + mdb, err := getAllMdbs() if err != nil { - resp = ActionResponse{Payload: payload, ErrSrc: ProtoErr} - return resp, err + allResp := ResponseError(TYPE_ACTION, payload, ProtoErr) + return allResp.([]ActionResponse), err } - defer closeAllDbs(dbs[:]) + defer closeAllMdbs(mdb) - err = (*app).translateAction(dbs) + for _, nameSpace := range nameSpaces { - if err != nil { - resp = ActionResponse{Payload: payload, ErrSrc: AppErr} - return resp, err - } + err = (*app).translateAction(mdb[nameSpace]) + + if err != nil { + allResp := ResponseError(TYPE_ACTION, payload, AppErr) + return allResp.([]ActionResponse), err + } + + resp, err = (*app).processAction(mdb[nameSpace]) - resp, err = (*app).processAction(dbs) + if len(resp.Payload) > 0 && err == nil { + allResp = append(allResp, ActionResponse{ + Payload: resp.Payload, + ErrSrc: resp.ErrSrc, + }) + } + } - return resp, err + return allResp, err } // Bulk - BULK Request API for northbounds // Processes the request in received order // Transaction based + func Bulk(req BulkRequest) (BulkResponse, error) { + type bulkRequestContext struct { + app *appInterface + appInfo *appInfo + namespacePayloads []NamespacePayload + keyStr string + operation int + } + var err error var keys []db.WatchKeys var errSrc ErrSource var appResp SetResponse + var namespacePayloads []NamespacePayload resp := BulkResponse{} + redisMdbInstances := make(map[string]*db.DB) + contexts := make([]bulkRequestContext, len(req.Request)) if !isAuthorizedForBulk(req) { return resp, tlerr.AuthorizationError{ @@ -571,37 +1223,28 @@ func Bulk(req BulkRequest) (BulkResponse, error) { writeMutex.Lock() defer writeMutex.Unlock() - d, err := db.NewDB(getDBOptions(db.ConfigDB)) - - if err != nil { - return resp, err - } - - defer d.DeleteDB() - - //Start the transaction without any keys or tables to watch will be added later using AppendWatchTx - err = d.StartTx(nil, nil) - - if err != nil { - return resp, err - } + resp.Response = make([]BulkResponseEntry, len(req.Request)) for i := range req.Request { + var keyStr string // Declare early to avoid goto skipping declaration + path := req.Request[i].Entry.Path operation := req.Request[i].Operation + payload := req.Request[i].Entry.Payload + resp.Response[i].Operation = operation - log.Infof("Bulk Request operation: %v received with path = %v", req.Request[i].Operation, path) + log.Infof("Bulk Request operation: %v received with path = %v", operation, path) app, appInfo, err := getAppModule(path, req.Request[i].Entry.ClientVersion) if err != nil { errSrc = ProtoErr goto BulkError } + if operation == DELETE { opts := appOptions{deleteEmptyEntry: req.Request[i].Entry.DeleteEmptyEntry} err = appInitialize(app, appInfo, path, nil, &opts, operation) } else { - payload := req.Request[i].Entry.Payload err = appInitialize(app, appInfo, path, &payload, nil, operation) } @@ -610,126 +1253,207 @@ func Bulk(req BulkRequest) (BulkResponse, error) { goto BulkError } - switch operation { - case DELETE: - keys, err = (*app).translateDelete(d) - if err != nil && isBulkNotFoundError(err) { - if !req.Request[i].ResourceCheckOnDelete { - //GNMI DELETE and YANG-PATCH REMOVE will come here - log.V(2).Infof("Ignoring Delete error: %+v", err) - appResp.Err = nil // so that northbounds can ignore - resp.Response = append(resp.Response, BulkResponseEntry{Operation: req.Request[i].Operation, - Entry: appResp}) - continue - } - } - case REPLACE: - keys, err = (*app).translateReplace(d) - case UPDATE: - keys, err = (*app).translateUpdate(d) - if err != nil && isBulkNotFoundError(err) { - //TODO: Right approach is to invoke CREATE, but REPLACE will solve the purpose as - //resource does not exists, REPLACE will behave like CREATE. - //REPLACE is chosen because PATH format and payload is same as UPDATE - log.V(2).Infof("Since UPDATE Failed, Changing operation type to REPLACE") - operation = REPLACE - payload := req.Request[i].Entry.Payload - err = appInitialize(app, appInfo, path, &payload, nil, operation) - if err != nil { - errSrc = AppErr - goto BulkError - } - keys, err = (*app).translateReplace(d) - } - case CREATE: - keys, err = (*app).translateCreate(d) - default: - log.Warningf("Unknown operation '%v'", operation) - err = tlerr.NotSupported("Unknown operation '%v'", operation) - } - + namespacePayloads, err = (*app).getNamespace(path) if err != nil { errSrc = AppErr goto BulkError } - err = d.AppendWatchTx(keys, appInfo.tablesToWatch) - - if err != nil { - errSrc = AppErr - goto BulkError + if operation == DELETE && len(namespacePayloads) == 1 && namespacePayloads[0].Namespace == "*" { + allNamespaces := db.GetMultiDbNames() + key := namespacePayloads[0].Key + namespacePayloads = nil + for _, ns := range allNamespaces { + namespacePayloads = append(namespacePayloads, NamespacePayload{ + Namespace: ns, + Payloads: nil, + Key: key, + }) + } } - switch operation { - case DELETE: - appResp, err = (*app).processDelete(d) - if err != nil && isBulkNotFoundError(err) { - if !req.Request[i].ResourceCheckOnDelete { - //GNMI DELETE and YANG-PATCH REMOVE will come here - log.V(2).Infof("Ignoring Delete error: %+v", err) - appResp.Err = nil // so that northbounds can ignore - resp.Response = append(resp.Response, BulkResponseEntry{Operation: req.Request[i].Operation, - Entry: appResp}) - continue - } - } - case REPLACE: - appResp, err = (*app).processReplace(d) - case UPDATE: - appResp, err = (*app).processUpdate(d) - if err != nil && isBulkNotFoundError(err) { - //TODO: Right approach is to invoke CREATE, but REPLACE will solve the purpose as - //resource does not exists, REPLACE will behave like CREATE. - //REPLACE is chosen because PATH format and payload is same as UPDATE - log.V(2).Infof("Since UPDATE Failed, Changing operation type to REPLACE") - operation = REPLACE - payload := req.Request[i].Entry.Payload - err = appInitialize(app, appInfo, path, &payload, nil, operation) - if err != nil { - errSrc = AppErr - goto BulkError - } - keys, err = (*app).translateReplace(d) - if err != nil { - errSrc = AppErr - goto BulkError - } - err = d.AppendWatchTx(keys, appInfo.tablesToWatch) - if err != nil { - errSrc = AppErr - goto BulkError + for _, nsPayload := range namespacePayloads { + nameSpace := nsPayload.Namespace + payloads := nsPayload.Payloads + + keyStr = nsPayload.Key + var payloadBytes []byte + + d, err := initializeMDBInstance(nameSpace, redisMdbInstances) + if err != nil { + errSrc = ProtoErr + goto BulkError + } + defer d.DeleteDB() + + if operation == DELETE { + keys, err = (*app).translateDelete(d) + } else { + if len(payloads) == 0 { + log.Infof("Payloads for namespace '%s' are empty, using top-level payload", nameSpace) + + var topLevelPayload map[string]interface{} + err := json.Unmarshal(payload, &topLevelPayload) + if err != nil { + log.Errorf("Failed to unmarshal top-level payload: %v", err) + errSrc = ProtoErr + goto BulkError + } + + payloads = append(payloads, topLevelPayload) + } + + for _, p := range payloads { + payloadBytes, err = json.Marshal(p) + if err != nil { + errSrc = AppErr + goto BulkError + } + err = appInitialize(app, appInfo, path, &payloadBytes, nil, operation) + if err != nil { + errSrc = AppErr + goto BulkError + } + } + + switch operation { + case CREATE: + keys, err = (*app).translateCreate(d) + case UPDATE: + keys, err = (*app).translateUpdate(d) + if err != nil && isBulkNotFoundError(err) { + log.V(2).Infof("Since UPDATE Failed, Changing operation type to REPLACE") + operation = REPLACE + err = appInitialize(app, appInfo, path, &payloadBytes, nil, operation) + if err != nil { + errSrc = AppErr + goto BulkError + } + keys, err = (*app).translateReplace(d) + } + case REPLACE: + keys, err = (*app).translateReplace(d) + default: + err = tlerr.NotSupported("Unknown operation '%v'", operation) + } + } + + if err != nil { + errSrc = AppErr + goto BulkError + } + + err = d.AppendWatchTx(keys, appInfo.tablesToWatch) + if err != nil { + errSrc = AppErr + goto BulkError + } + + contexts[i] = bulkRequestContext{ + app: app, + appInfo: appInfo, + namespacePayloads: namespacePayloads, + keyStr: keyStr, + operation: operation, + } + + err = (*app).processPreparePhase(d, keyStr) + if err != nil { + errSrc = AppErr + goto BulkError + } + + switch operation { + case DELETE: + appResp, err = (*app).processDelete(d) + case CREATE: + appResp, err = (*app).processCreate(d) + case UPDATE: + appResp, err = (*app).processUpdate(d) + if err != nil && isBulkNotFoundError(err) { + log.V(2).Infof("Since UPDATE Failed again, fallback to REPLACE") + operation = REPLACE + err = appInitialize(app, appInfo, path, &payloadBytes, nil, operation) + if err != nil { + errSrc = AppErr + goto BulkError + } + keys, err = (*app).translateReplace(d) + if err != nil { + errSrc = AppErr + goto BulkError + } + err = d.AppendWatchTx(keys, appInfo.tablesToWatch) + if err != nil { + errSrc = AppErr + goto BulkError + } + appResp, err = (*app).processReplace(d) } + case REPLACE: appResp, err = (*app).processReplace(d) } - case CREATE: - appResp, err = (*app).processCreate(d) - default: - log.Warningf("Unknown operation '%v'", operation) - err = tlerr.NotSupported("Unknown operation '%v'", operation) - } - if err != nil { - errSrc = AppErr - goto BulkError + if err != nil { + errSrc = AppErr + goto BulkError + } + + if _, exists := redisMdbInstances[nameSpace]; !exists { + redisMdbInstances[nameSpace] = d + } + + resp.Response[i].Entry = appResp } - resp.Response = append(resp.Response, BulkResponseEntry{Operation: req.Request[i].Operation, Entry: appResp}) + continue BulkError: - if err != nil { - log.Infof("BulkError: %+v", err) - d.AbortTx() + log.Infof("BulkError: %+v", err) + appResp.Err = err + appResp.ErrSrc = errSrc + resp.Response[i].Entry = appResp + + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + appResp.Err = abortErr appResp.ErrSrc = errSrc - appResp.Err = err - resp.Response = append(resp.Response, BulkResponseEntry{Operation: req.Request[i].Operation, - Entry: appResp}) - return resp, err + resp.Response[i].Entry = appResp + return resp, abortErr + } + + return resp, err + } + + // COMMIT PHASE + cerr := commitTransactions(redisMdbInstances, namespacePayloads) + + // POST-COMMIT or ROLLBACK + for _, ctx := range contexts { + app := ctx.app + namespacePayloads := ctx.namespacePayloads + + if cerr != nil { + for ns, redisDbInstance := range redisMdbInstances { + for _, payload := range namespacePayloads { + if payload.Namespace == ns && payload.Commited { + log.Infof("Rollback key:%v, Namespace: %s", payload.Key, payload.Namespace) + err = (*app).rollback(redisDbInstance) + if err != nil { + log.Infof("Rollback operation failed!") + } + } + } + } } } - err = d.CommitTx() + err = processPostPhase() + if err != nil { + log.Infof("Cleanup of backup entries operation failed!") + } - return resp, err + return resp, cerr } // GetModels - Gets all the models supported by Translib @@ -740,33 +1464,56 @@ func GetModels() ([]ModelData, error) { } // Creates connection will all the redis DBs. To be used for get request -func getAllDbs(opts ...func(*db.Options)) ([db.MaxDB]*db.DB, error) { +func getAllMdbs(opts ...func(*db.Options)) (map[string][db.MaxDB]*db.DB, error) { var dbs [db.MaxDB]*db.DB var err error - for dbNum := db.DBNum(0); dbNum < db.MaxDB; dbNum++ { - if len(dbNum.Name()) == 0 { - continue - } - dbs[dbNum], err = db.NewDB(getDBOptions(dbNum, opts...)) - if err != nil { - closeAllDbs(dbs[:]) - break - } + mdbNames := db.GetMultiDbNames() + if len(mdbNames) == 0 { + return nil, errors.New("get all db names failed") } - return dbs, err + mdb := make(map[string][db.MaxDB]*db.DB) + for _, nameSpace := range mdbNames { + + for dbNum := db.DBNum(0); dbNum < db.MaxDB; dbNum++ { + if len(dbNum.Name()) == 0 { + continue + } + // Pass the nameSpace to SetMDBName and other opts to getDBOptions + dbs[dbNum], err = db.NewDB(getDBOptions(dbNum, append(opts, SetMDBName(nameSpace))...)) + if err != nil { + closeAllDbs(dbs[:]) + break + } + } + mdb[nameSpace] = dbs + } + return mdb, err } // Closes the dbs, and nils out the arr. func closeAllDbs(dbs []*db.DB) { for dbsi, d := range dbs { if d != nil { - d.DeleteDB() + if err := d.DeleteDB(); err != nil { + log.Infof("Failed to delete DB %d: %v", dbsi, err) + } + dbs[dbsi] = nil } } } +// Closes the multiple dbs for multi_asic, and nils out the arr. +func closeAllMdbs(mdb map[string][db.MaxDB]*db.DB) { + for name, db := range mdb { + if db[:] != nil { + closeAllDbs(db[:]) + } + delete(mdb, name) + } +} + // Compare - Implement Compare method for priority queue for SubscribeResponse struct func (val SubscribeResponse) Compare(other queue.Item) int { o := other.(*SubscribeResponse) @@ -783,9 +1530,22 @@ func getDBOptions(dbNo db.DBNum, opts ...func(*db.Options)) db.Options { for _, setopt := range opts { setopt(&o) } + + // If MDBName is not set, use the default nameSpace value + if o.MDBName == "" { + o.MDBName = "host" + } + return o } +// Define a new function to set the MDBName in Options +func SetMDBName(nameSpace string) func(*db.Options) { + return func(o *db.Options) { + o.MDBName = nameSpace + } +} + func withWriteDisable(o *db.Options) { o.IsWriteDisabled = true } @@ -823,6 +1583,7 @@ func appInitialize(app *appInterface, appInfo *appInfo, path string, payload *[] if payload != nil { input = *payload } + log.Infof("AppInfo :%v, payload:%v", appInfo, payload) if appInfo.isNative { data := appData{path: path, payload: input} @@ -831,11 +1592,13 @@ func appInitialize(app *appInterface, appInfo *appInfo, path string, payload *[] } else { reqBinder := getRequestBinder(&path, payload, opCode, &(appInfo.ygotRootType)) ygotStruct, ygotTarget, err := reqBinder.unMarshall() + if err != nil { log.Info("Error in request binding: ", err) return err } data := appData{path: path, payload: input, ygotRoot: ygotStruct, ygotTarget: ygotTarget, ygSchema: reqBinder.targetNodeSchema} + log.Info("App data", data) data.setOptions(opts) (*app).initialize(data) } diff --git a/translib/translib_test.go b/translib/translib_test.go index 9ceb1e1a8..7de8adae3 100644 --- a/translib/translib_test.go +++ b/translib/translib_test.go @@ -53,7 +53,3 @@ func equals(tb testing.TB, exp, act interface{}) { tb.FailNow() } } - -func Test_Create(t *testing.T) { - -} diff --git a/translib/yanglib_app.go b/translib/yanglib_app.go index e88640d62..35269e998 100644 --- a/translib/yanglib_app.go +++ b/translib/yanglib_app.go @@ -515,3 +515,26 @@ func GetYangPath() string { func GetYangModuleSetID() string { return GetYangBundleVersion().String() } + +func (app *yanglibApp) getNamespace(path string) ([]NamespacePayload, error) { + + var nameSpaceList []NamespacePayload + + nameSpaceList = append(nameSpaceList, NamespacePayload{ + Namespace: "host", + Payloads: []map[string]interface{}{}, + Key: "", + }) + + glog.Infof("yanglibApp:getNamespace: nameSpaceList:%v ", nameSpaceList) + + return nameSpaceList, nil +} + +func (app *yanglibApp) processPreparePhase(d *db.DB, ckey string) error { + return nil +} + +func (app *yanglibApp) rollback(d *db.DB) error { + return nil +} diff --git a/translib/yanglib_app_test.go b/translib/yanglib_app_test.go index 111d808e2..327de2f9e 100644 --- a/translib/yanglib_app_test.go +++ b/translib/yanglib_app_test.go @@ -136,8 +136,9 @@ func getYanglibData(name, rev, attr string) (map[string]interface{}, error) { data := make(map[string]interface{}) response, err := Get(GetRequest{Path: u}) - if err == nil { - err = json.Unmarshal(response.Payload, &data) + //issue with index out of range + if err == nil && len(response) > 0 { + err = json.Unmarshal(response[0].Payload, &data) } return data, err From 0eb415758c88bef3833c635d568db744d2c2b20e Mon Sep 17 00:00:00 2001 From: SONIC-ADMIN Date: Tue, 30 Dec 2025 13:08:50 +0530 Subject: [PATCH 5/9] MultiDbCodeChangesWithRollback --- translib/translib.go | 52 ++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/translib/translib.go b/translib/translib.go index 70be9382b..f8f126520 100644 --- a/translib/translib.go +++ b/translib/translib.go @@ -37,14 +37,14 @@ import ( "context" "encoding/json" "errors" - //"fmt" + "fmt" "github.com/Azure/sonic-mgmt-common/translib/db" "github.com/Azure/sonic-mgmt-common/translib/tlerr" "github.com/Workiva/go-datastructures/queue" log "github.com/golang/glog" "github.com/openconfig/ygot/ygot" - //"os" - //"path/filepath" + "os" + "path/filepath" "sync" ) @@ -174,10 +174,7 @@ func ResponseError(optype string, payload []byte, errorType ErrSource) interface } func commitTransactions(redisMdbInstances map[string]*db.DB, nsMaps []NamespacePayload) error { - total := len(redisMdbInstances) - i := 0 for ns, redisDbInstance := range redisMdbInstances { - i++ if err := redisDbInstance.CommitTx(); err != nil { return err @@ -190,12 +187,6 @@ func commitTransactions(redisMdbInstances map[string]*db.DB, nsMaps []NamespaceP } } - // Purposefully fail on last iteration - if i == total { - // err := fmt.Errorf("Intentional failure on last iteration: %s", ns) - // return tlerr.InvalidArgsError{Format: err.Error()} - } - } return nil @@ -237,28 +228,27 @@ func initializeMDBInstance(mdbName string, redisMdbInstances map[string]*db.DB) func processPostPhase() error { log.Infof("Cleanup: deleting all backup files from /tmp") - /* - // Match all files with pattern: /tmp/common_backup_*.json - backupFiles, err := filepath.Glob("/var/tmp/common_backup_*.json") - if err != nil { - log.Infof("Failed to list backup files: %v", err) - return err - } - if len(backupFiles) == 0 { - log.Infof("No backup files found to delete.") - return nil - } + // Match all files with pattern: /tmp/common_backup_*.json + backupFiles, err := filepath.Glob("/var/tmp/common_backup_*.json") + if err != nil { + log.Infof("Failed to list backup files: %v", err) + return err + } - for _, file := range backupFiles { - err := os.Remove(file) - if err != nil { - log.Infof("Failed to delete backup file: %s, error: %v", file, err) - return err - } - log.Infof("Deleted backup file: %s", file) + if len(backupFiles) == 0 { + log.Infof("No backup files found to delete.") + return nil + } + + for _, file := range backupFiles { + err := os.Remove(file) + if err != nil { + log.Infof("Failed to delete backup file: %s, error: %v", file, err) + return err } - */ + log.Infof("Deleted backup file: %s", file) + } return nil } From d72052094bc7863ece259440badd14e9cc96083f Mon Sep 17 00:00:00 2001 From: SONIC-ADMIN Date: Tue, 30 Dec 2025 14:43:50 +0530 Subject: [PATCH 6/9] MultiDbCodeChangesWithRollback --- models/yang/common/openconfig-alarms.yang | 10 ++-------- translib/translib.go | 1 - 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/models/yang/common/openconfig-alarms.yang b/models/yang/common/openconfig-alarms.yang index c7d71f195..5bcc56314 100644 --- a/models/yang/common/openconfig-alarms.yang +++ b/models/yang/common/openconfig-alarms.yang @@ -42,13 +42,7 @@ module openconfig-alarms { Section 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info)."; - oc-ext:openconfig-version "0.3.2"; - - revision "2019-07-09" { - description - "Clarify relative base for leaves using timeticks64."; - reference "0.3.2"; - } + oc-ext:openconfig-version "0.3.1"; revision "2018-11-21" { description @@ -125,7 +119,7 @@ module openconfig-alarms { type oc-types:timeticks64; description "The time at which the alarm was raised by the system. - This value is expressed relative to the Unix Epoch."; + This value is expressed as nanoseconds since the Unix Epoch"; } leaf severity { diff --git a/translib/translib.go b/translib/translib.go index f8f126520..592f13a43 100644 --- a/translib/translib.go +++ b/translib/translib.go @@ -37,7 +37,6 @@ import ( "context" "encoding/json" "errors" - "fmt" "github.com/Azure/sonic-mgmt-common/translib/db" "github.com/Azure/sonic-mgmt-common/translib/tlerr" "github.com/Workiva/go-datastructures/queue" From 85c7b8d58f0c50615b568e81ff65a0953b50c6d1 Mon Sep 17 00:00:00 2001 From: SONIC-ADMIN Date: Tue, 30 Dec 2025 16:06:13 +0530 Subject: [PATCH 7/9] MultiDbCodeChangesWithRollback --- translib/transformer/xfmr_aps.go | 2 +- translib/transformer/xfmr_atten.go | 2 +- translib/transformer/xfmr_channel_monitor.go | 2 +- translib/transformer/xfmr_wavelength_router.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/translib/transformer/xfmr_aps.go b/translib/transformer/xfmr_aps.go index c899e38b9..c3c8f7618 100644 --- a/translib/transformer/xfmr_aps.go +++ b/translib/transformer/xfmr_aps.go @@ -380,7 +380,7 @@ var aps_name_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([] key = pathInfo.Var("name") log.Infof("aps_name_get_namespace_xfmr: key: %v", key) - if len(key) > 0 { + if len(key) > 0 && key != "*" { dbName := db.GetMDBNameFromEntity(key) log.Infof("aps_name_get_namespace_xfmr: dbName: %v", dbName) diff --git a/translib/transformer/xfmr_atten.go b/translib/transformer/xfmr_atten.go index 25fc01d8d..82619a1c4 100644 --- a/translib/transformer/xfmr_atten.go +++ b/translib/transformer/xfmr_atten.go @@ -163,7 +163,7 @@ var attn_name_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([ key = pathInfo.Var("name") log.Infof("attn_name_get_namespace_xfmr: key: %v", key) - if len(key) > 0 { + if len(key) > 0 && key != "*" { dbName := db.GetMDBNameFromEntity(key) log.Infof("attn_name_get_namespace_xfmr: dbName: %v", dbName) diff --git a/translib/transformer/xfmr_channel_monitor.go b/translib/transformer/xfmr_channel_monitor.go index 38c0ab745..9dfd492ca 100644 --- a/translib/transformer/xfmr_channel_monitor.go +++ b/translib/transformer/xfmr_channel_monitor.go @@ -153,7 +153,7 @@ var ocm_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]Names key = pathInfo.Var("name") log.Infof("ocm_get_namespace_xfmr: key: %v", key) - if len(key) > 0 { + if len(key) > 0 && key != "*" { dbName := db.GetMDBNameFromEntity(key) log.Infof("ocm_get_namespace_xfmr: dbName: %v", dbName) diff --git a/translib/transformer/xfmr_wavelength_router.go b/translib/transformer/xfmr_wavelength_router.go index 053bd625d..13267a238 100644 --- a/translib/transformer/xfmr_wavelength_router.go +++ b/translib/transformer/xfmr_wavelength_router.go @@ -195,7 +195,7 @@ var media_channel_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams log.Infof("media_channel_get_namespace_xfmr: key: %v", keyStr) - if len(keyStr) > 0 { + if len(keyStr) > 0 && keyStr != "*" { keyUint64, err := strconv.ParseUint(keyStr, 10, 32) if err != nil { From 20ad3d9178897b25d31c7fbc5642c63231d38ecf Mon Sep 17 00:00:00 2001 From: maheswari Date: Tue, 19 May 2026 11:08:11 +0530 Subject: [PATCH 8/9] Changed target branch to otn-dev --- cvl/cvl_test.go | 9 +- .../annotations/openconfig-system-annot.yang | 1940 +---------------- .../openconfig-test-xfmr-annot.yang | 173 -- .../yang/openconfig-platform-transceiver.yang | 352 ++- models/yang/openconfig-test-xfmr.yang | 678 ------ models/yang/sonic/import.mk | 2 +- models/yang/sonic/sonic-test-xfmr.yang | 344 --- translib/db/db_config.go | 4 +- translib/db/db_util.go | 14 +- translib/transformer/testxfmryang_test.go | 365 +++- translib/transformer/vlan_openconfig_test.go | 24 +- translib/transformer/xfmr_aps.go | 36 +- translib/transformer/xfmr_atten.go | 35 +- translib/transformer/xfmr_channel_monitor.go | 81 +- .../transformer/xfmr_optical_amplifier.go | 80 +- translib/transformer/xfmr_otdr.go | 35 +- translib/transformer/xfmr_otn_openconfig.go | 115 - translib/transformer/xfmr_pfm.go | 6 +- translib/transformer/xfmr_terminal_device.go | 42 +- .../transformer/xfmr_testxfmr_callbacks.go | 25 + translib/transformer/xfmr_tlmt.go | 116 +- .../transformer/xfmr_wavelength_router.go | 107 +- translib/transformer/xlate.go | 1 - translib/transformer/xlate_utils.go | 4 +- translib/transformer/xspec.go | 44 +- 25 files changed, 1174 insertions(+), 3458 deletions(-) delete mode 100644 models/yang/annotations/openconfig-test-xfmr-annot.yang delete mode 100644 models/yang/openconfig-test-xfmr.yang delete mode 100644 models/yang/sonic/sonic-test-xfmr.yang diff --git a/cvl/cvl_test.go b/cvl/cvl_test.go index 4c883132f..ab1be6d40 100644 --- a/cvl/cvl_test.go +++ b/cvl/cvl_test.go @@ -27,6 +27,7 @@ import ( "os/exec" "reflect" "sort" + "strconv" "strings" "github.com/Azure/sonic-mgmt-common/cvl" @@ -387,8 +388,12 @@ func init() { var err error configDb = make(map[string]*db.DB) - if IsMultiAsic() { - MdbNames = append(MdbNames, "asic0") + if NumAsic == 1 { + MdbNames = append(MdbNames, "host") + } else { + for i := 0; i < NumAsic; i++ { + MdbNames = append(MdbNames, "asic"+strconv.Itoa(i)) + } } for _, dbName := range MdbNames { diff --git a/models/yang/annotations/openconfig-system-annot.yang b/models/yang/annotations/openconfig-system-annot.yang index ce2af79ca..83ea4f6ce 100644 --- a/models/yang/annotations/openconfig-system-annot.yang +++ b/models/yang/annotations/openconfig-system-annot.yang @@ -2,1980 +2,126 @@ module openconfig-system-annot { yang-version "1"; - namespace "http://openconfig.net/yang/annotation/oc-sys-annot"; + namespace "http://openconfig.net/yang/openconfig-system-annot"; prefix "oc-sys-annot"; - import openconfig-procmon { prefix oc-proc; } - import openconfig-alarms { prefix oc-alarms; } - import openconfig-inet-types { prefix oc-inet; } - import openconfig-yang-types { prefix oc-yang; } - import openconfig-extensions { prefix oc-ext; } - import openconfig-aaa { prefix oc-aaa; } - import openconfig-system-logging { prefix oc-log; } - import openconfig-system-management { prefix oc-sys-mgmt; } - import openconfig-types { prefix oc-types; } - import openconfig-system-terminal { prefix oc-sys-term; } - import openconfig-messages { prefix oc-messages; } import openconfig-system { prefix oc-sys; } import sonic-extensions {prefix sonic-ext; } import openconfig-system-grpc { prefix oc-sys-grpc; } import gnsi-pathz { prefix gnsi-pathz; } import openconfig-gnsi-credentialz { prefix oc-gnsi-credz; } - deviation /oc-sys:system { - deviate add { - sonic-ext:table-name "SYSTEM"; - } - } - - deviation /oc-sys:system/oc-sys:telnet-server { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:config/oc-sys:enable { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:config/oc-sys:timeout { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:config/oc-sys:rate-limit { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:config/oc-sys:session-limit { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:state/oc-sys:rate-limit { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:state/oc-sys:session-limit { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:state/oc-sys:enable { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:telnet-server/oc-sys:state/oc-sys:timeout { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ssh-server { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:config/oc-sys:timeout { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:config/oc-sys:enable { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:config/oc-sys:protocol-version { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:config/oc-sys:rate-limit { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:config/oc-sys:session-limit { - deviate add { - } - } - deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:state { deviate add { - sonic-ext:db-name "STATE_DB"; + sonic-ext:db-name "STATE_DB"; sonic-ext:subtree-transformer "ssh_server_state_xfmr"; } } - deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:state/oc-sys:session-limit { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:state/oc-sys:timeout { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:state/oc-sys:enable { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:state/oc-sys:protocol-version { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ssh-server/oc-sys:state/oc-sys:rate-limit { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys-grpc:grpc-servers { + deviation /oc-sys:system/oc-sys-grpc:grpc-servers { deviate add { sonic-ext:key-transformer "grpc_server_key_xfmr"; sonic-ext:subtree-transformer "grpc_server_xfmr"; } } - deviation /oc-sys:system/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:state/oc-sys:domain-name { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:state/oc-sys:login-banner { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:state/oc-sys:motd-banner { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:state/oc-sys:current-datetime { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:state/oc-sys:boot-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:state/oc-sys:hostname { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:clock { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:clock/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:clock/oc-sys:state/oc-sys:timezone-name { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:clock/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:clock/oc-sys:config/oc-sys:timezone-name { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:memory { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:memory/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:memory/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:memory/oc-sys:state/oc-sys:reserved { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:memory/oc-sys:state/oc-sys:physical { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns/oc-sys:state/oc-sys:search { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns/oc-sys:servers { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:port { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:port { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry { + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state { deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "CREDENTIALS"; + sonic-ext:key-name "GLOME_CONFIG"; } } - deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:config { + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state/oc-gnsi-credz:active-glome-key-version { deviate add { + sonic-ext:field-name "key_version"; } } - deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:config/oc-sys:hostname { + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state/oc-gnsi-credz:active-glome-key-created-on { deviate add { + sonic-ext:field-name "last_updated"; } } - deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:config/oc-sys:alias { + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state/oc-gnsi-credz:enabled { deviate add { + sonic-ext:field-name "enabled"; } } - deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:config/oc-sys:ipv4-address { + deviation /oc-sys:system/oc-gnsi-credz:console { deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:subtree-transformer "console_counters_xfmr"; } } - deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:config/oc-sys:ipv6-address { + deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:state { deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:subtree-transformer "authz_policy_xfmr"; } } - deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:state { + deviation /oc-sys:system/gnsi-pathz:gnmi-pathz-policies { deviate add { + sonic-ext:key-transformer "pathz_policies_key_xfmr"; + sonic-ext:subtree-transformer "pathz_policies_xfmr"; } } - deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:state/oc-sys:alias { + deviation /oc-sys:system/oc-sys:alarms { deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "CURALARM_TABLE"; + sonic-ext:get-namespace "oc_sys_get_namespace_xfmr"; } } - deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:state/oc-sys:ipv4-address { + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm { deviate add { + sonic-ext:key-transformer "oc_system_alarm_key_xfmr"; } } - deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:state/oc-sys:ipv6-address { + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state { deviate add { + sonic-ext:db-name "STATE_DB"; + sonic-ext:table-name "CURALARM_TABLE"; + sonic-ext:key-transformer "oc_system_alarm_key_xfmr"; + sonic-ext:get-namespace "oc_sys_get_namespace_xfmr"; } } - deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:state/oc-sys:hostname { + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:type-id { deviate add { + sonic-ext:field-name "type-id"; } } - deviation /oc-sys:system/oc-sys:dns/oc-sys:host-entries/oc-sys:host-entry/oc-sys:hostname { + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:resource { deviate add { + sonic-ext:field-name "resource"; } } - deviation /oc-sys:system/oc-sys:dns/oc-sys:config { + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:text { deviate add { + sonic-ext:field-name "text"; } } - deviation /oc-sys:system/oc-sys:dns/oc-sys:config/oc-sys:search { + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:time-created { deviate add { + sonic-ext:field-name "time-created"; } } - deviation /oc-sys:system/oc-sys:ntp { + deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:severity { deviate add { + sonic-ext:field-name "severity"; } } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:config/oc-sys:ntp-source-address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:config/oc-sys:enable-ntp-auth { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:config/oc-sys:enabled { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:state/oc-sys:enabled { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:state/oc-sys:ntp-source-address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:state/oc-sys:auth-mismatch { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:state/oc-sys:enable-ntp-auth { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:key-id { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:config/oc-sys:key-value { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:config/oc-sys:key-id { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:config/oc-sys:key-type { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:state/oc-sys:key-type { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:state/oc-sys:key-value { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:ntp-keys/oc-sys:ntp-key/oc-sys:state/oc-sys:key-id { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:port { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:version { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:association-type { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:iburst { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:prefer { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:iburst { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:association-type { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:poll-interval { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:prefer { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:offset { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:root-delay { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:stratum { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:version { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:root-dispersion { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:ntp/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:port { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:config/oc-sys:motd-banner { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:config/oc-sys:hostname { - deviate add { - sonic-ext:field-name "hostname"; - } - } - - deviation /oc-sys:system/oc-sys:config/oc-sys:domain-name { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:config/oc-sys:login-banner { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:min-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:max-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:instant { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:avg { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:min { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:max { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:hardware-interrupt/oc-sys:interval { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:interval { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:min-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:max-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:instant { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:avg { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:min { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:user/oc-sys:max { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:max-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:instant { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:avg { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:min { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:max { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:interval { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:kernel/oc-sys:min-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:min { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:max { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:interval { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:min-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:max-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:instant { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:idle/oc-sys:avg { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:avg { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:min { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:max { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:interval { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:min-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:max-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:software-interrupt/oc-sys:instant { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:min-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:max-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:instant { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:avg { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:min { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:max { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:nice/oc-sys:interval { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:index { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:instant { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:avg { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:min { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:max { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:interval { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:min-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:total/oc-sys:max-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:min { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:max { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:interval { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:min-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:max-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:instant { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:state/oc-sys:wait/oc-sys:avg { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:cpus/oc-sys:cpu/oc-sys:index { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:alarms { - deviate add { - sonic-ext:db-name "STATE_DB"; - sonic-ext:table-name "CURALARM_TABLE"; - sonic-ext:get-namespace "oc_sys_get_namespace_xfmr"; - } - } - - deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm { - deviate add { - sonic-ext:key-transformer "oc_system_alarm_key_xfmr"; - } - } - - deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:id { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state { - deviate add { - sonic-ext:db-name "STATE_DB"; - sonic-ext:table-name "CURALARM_TABLE"; - sonic-ext:key-transformer "oc_system_alarm_key_xfmr"; - sonic-ext:get-namespace "oc_sys_get_namespace_xfmr"; - } - } - - deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:type-id { - deviate add { - sonic-ext:field-name "type-id"; - } - } - - deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:id { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:resource { - deviate add { - sonic-ext:field-name "resource"; - } - } - - deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:text { - deviate add { - sonic-ext:field-name "text"; - } - } - - deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:time-created { - deviate add { - sonic-ext:field-name "time-created"; - } - } - - deviation /oc-sys:system/oc-sys:alarms/oc-sys:alarm/oc-sys:state/oc-sys:severity { - deviate add { - sonic-ext:field-name "severity"; - } - } - - deviation /oc-sys:system/oc-sys:processes { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:processes/oc-sys:process { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:pid { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:cpu-usage-user { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:cpu-utilization { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:name { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:memory-utilization { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:memory-usage { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:start-time { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:cpu-usage-system { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:args { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:pid { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:processes/oc-sys:process/oc-sys:state/oc-sys:uptime { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:config/oc-sys:accounting-method { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:state/oc-sys:accounting-method { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:event-type { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:config/oc-sys:event-type { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:config/oc-sys:record { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:state/oc-sys:event-type { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:accounting/oc-sys:events/oc-sys:event/oc-sys:state/oc-sys:record { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:state/oc-sys:source-address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:state/oc-sys:port { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:state/oc-sys:secret-key { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:config/oc-sys:source-address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:config/oc-sys:port { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:tacacs/oc-sys:config/oc-sys:secret-key { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:source-address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:retransmit-attempts { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:auth-port { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:acct-port { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:counters { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:counters/oc-sys:retried-access-requests { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:counters/oc-sys:access-accepts { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:counters/oc-sys:access-rejects { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:counters/oc-sys:timeout-access-requests { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:state/oc-sys:secret-key { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:config/oc-sys:auth-port { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:config/oc-sys:acct-port { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:config/oc-sys:secret-key { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:config/oc-sys:source-address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:radius/oc-sys:config/oc-sys:retransmit-attempts { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:timeout { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:name { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:config/oc-sys:address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:messages-sent { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:messages-received { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:connection-opens { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:connection-closes { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:timeout { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:connection-timeouts { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:errors-received { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:connection-failures { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:name { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:servers/oc-sys:server/oc-sys:state/oc-sys:connection-aborts { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:name { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:config/oc-sys:name { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:config/oc-sys:type { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:state/oc-sys:type { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:server-groups/oc-sys:server-group/oc-sys:state/oc-sys:name { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state { - deviate add { - sonic-ext:db-name "STATE_DB"; - sonic-ext:table-name "CREDENTIALS"; - sonic-ext:key-name "GLOME_CONFIG"; - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state/oc-gnsi-credz:active-glome-key-version { - deviate add { - sonic-ext:field-name "key_version"; - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc-sys:state/oc-gnsi-credz:active-glome-key-created-on { - deviate add { - sonic-ext:field-name "last_updated"; - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:glome/oc- sys:state/oc-gnsi-credz:enabled { - deviate add { - sonic-ext:field-name "enabled"; - } - } - - deviation /oc-sys:system/oc-gnsi-credz:console { - deviate add { - sonic-ext:db-name "STATE_DB"; - sonic-ext:subtree-transformer "console_counters_xfmr"; - } - } -   - deviation /oc-sys:system/gnsi-pathz:gnmi-pathz-policies { - deviate add { - sonic-ext:key-transformer "pathz_policies_key_xfmr"; - sonic-ext:subtree-transformer "pathz_policies_xfmr"; - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:state/oc-sys:admin-password { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:state/oc-sys:admin-password-hashed { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:state/oc-sys:admin-username { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:config/oc-sys:admin-password-hashed { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:admin-user/oc-sys:config/oc-sys:admin-password { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:username { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:config/oc-sys:ssh-key { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:config/oc-sys:role { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:config/oc-sys:username { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:config/oc-sys:password { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:config/oc-sys:password-hashed { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state/oc-sys:ssh-key { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state/oc-sys:role { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state/oc-sys:username { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state/oc-sys:password { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:users/oc-sys:user/oc-sys:state/oc-sys:password-hashed { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:config/oc-sys:authentication-method { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authentication/oc-sys:state/oc-sys:authentication-method { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:config/oc-sys:authorization-method { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:state { - deviate add { - sonic-ext:db-name "STATE_DB"; -        sonic-ext:subtree-transformer "authz_policy_xfmr"; - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:state/oc-sys:authorization-method { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events/oc-sys:event { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events/oc-sys:event/oc-sys:event-type { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events/oc-sys:event/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events/oc-sys:event/oc-sys:config/oc-sys:event-type { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events/oc-sys:event/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:aaa/oc-sys:authorization/oc-sys:events/oc-sys:event/oc-sys:state/oc-sys:event-type { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:config/oc-sys:service { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:config/oc-sys:enabled { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:state/oc-sys:enabled { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:state/oc-sys:service { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:debug-entries/oc-sys:debug-service/oc-sys:service { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:config/oc-sys:severity { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:message { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:message/oc-sys:msgid { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:message/oc-sys:msg { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:message/oc-sys:priority { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:message/oc-sys:app-name { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:message/oc-sys:procid { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:messages/oc-sys:state/oc-sys:severity { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:console { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:severity { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:config/oc-sys:severity { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:config/oc-sys:facility { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:state/oc-sys:severity { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:state/oc-sys:facility { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:selectors/oc-sys:selector/oc-sys:facility { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:console/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:facility { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:severity { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:config/oc-sys:facility { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:config/oc-sys:severity { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:state/oc-sys:severity { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:selectors/oc-sys:selector/oc-sys:state/oc-sys:facility { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:host { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:config { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:config/oc-sys:host { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:config/oc-sys:source-address { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:config/oc-sys:remote-port { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:state { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:state/oc-sys:remote-port { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:state/oc-sys:host { - deviate add { - } - } - - deviation /oc-sys:system/oc-sys:logging/oc-sys:remote-servers/oc-sys:remote-server/oc-sys:state/oc-sys:source-address { - deviate add { - } - } - } diff --git a/models/yang/annotations/openconfig-test-xfmr-annot.yang b/models/yang/annotations/openconfig-test-xfmr-annot.yang deleted file mode 100644 index c76098642..000000000 --- a/models/yang/annotations/openconfig-test-xfmr-annot.yang +++ /dev/null @@ -1,173 +0,0 @@ -module openconfig-test-xfmr-annot { - - yang-version "1"; - - namespace "http://openconfig.net/yang/annotation/oc-test-xfmr-annot"; - prefix "oc-test-xfmr-annot"; - - import openconfig-extensions { prefix oc-ext; } - import openconfig-test-xfmr { prefix oc-test-xfmr; } - import sonic-extensions { prefix sonic-ext; } - - deviation /oc-test-xfmr:test-xfmr { - deviate add { - sonic-ext:pre-transformer "test_pre_xfmr"; - sonic-ext:post-transformer "test_post_xfmr"; - sonic-ext:get-namespace "test_get_namespace_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group { - deviate add { - sonic-ext:table-name "TEST_SENSOR_GROUP"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:config/oc-test-xfmr:group-colors { - deviate add { - sonic-ext:field-name "colors"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:state/oc-test-xfmr:group-colors { - deviate add { - sonic-ext:field-name "colors"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:state/oc-test-xfmr:counters { - deviate add { - sonic-ext:table-name "TEST_SENSOR_GROUP_COUNTERS"; - sonic-ext:db-name "COUNTERS_DB"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types { - deviate add { - sonic-ext:table-name "NONE"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type { - deviate add { - sonic-ext:table-transformer "test_sensor_type_tbl_xfmr"; - sonic-ext:key-transformer "test_sensor_type_key_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type/oc-test-xfmr:config/oc-test-xfmr:type { - deviate add { - sonic-ext:field-transformer "test_sensor_type_field_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type/oc-test-xfmr:config/oc-test-xfmr:exclude-filter { - deviate add { - sonic-ext:field-transformer "exclude_filter_field_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type/oc-test-xfmr:state/oc-test-xfmr:type { - deviate add { - sonic-ext:field-transformer "test_sensor_type_field_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type/oc-test-xfmr:state/oc-test-xfmr:exclude-filter { - deviate add { - sonic-ext:field-transformer "exclude_filter_field_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type/oc-test-xfmr:sensor-a-light-sensors { - deviate add { - sonic-ext:table-name "NONE"; - sonic-ext:get-validate "light_sensor_validate"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-types/oc-test-xfmr:test-sensor-type/oc-test-xfmr:sensor-a-light-sensors/oc-test-xfmr:sensor-a-light-sensor { - deviate add { - sonic-ext:table-name "TEST_SENSOR_A_LIGHT_SENSOR_TABLE"; - sonic-ext:key-transformer "sensor_a_light_sensor_key_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-components/oc-test-xfmr:test-sensor-component { - deviate add { - sonic-ext:table-name "TEST_SENSOR_COMPONENT_TABLE"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-zones { - deviate add { - sonic-ext:table-name "NONE"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sensor-groups/oc-test-xfmr:test-sensor-group/oc-test-xfmr:test-sensor-zones/oc-test-xfmr:test-sensor-zone { - deviate add { - sonic-ext:table-name "TEST_SENSOR_ZONE_TABLE"; - sonic-ext:key-transformer "test_sensor_zone_key_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set { - deviate add { - sonic-ext:table-name "TEST_SET_TABLE"; - sonic-ext:key-transformer "test_set_key_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set/oc-test-xfmr:config/oc-test-xfmr:type { - deviate add { - sonic-ext:field-transformer "test_set_type_field_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set/oc-test-xfmr:config/oc-test-xfmr:name { - deviate add { - sonic-ext:field-transformer "test_set_name_field_xfmr"; - } - } - - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set/oc-test-xfmr:config/oc-test-xfmr:description { - deviate add { - sonic-ext:field-transformer "test_set_description_field_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set/oc-test-xfmr:state/oc-test-xfmr:name { - deviate add { - sonic-ext:field-transformer "test_set_name_field_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set/oc-test-xfmr:state/oc-test-xfmr:type { - deviate add { - sonic-ext:field-transformer "test_set_type_field_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:test-sets/oc-test-xfmr:test-set/oc-test-xfmr:state/oc-test-xfmr:description { - deviate add { - sonic-ext:field-transformer "test_set_description_field_xfmr"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:interfaces { - deviate add { - sonic-ext:subtree-transformer "test_port_bindings_xfmr"; - sonic-ext:virtual-table "true"; - } - } - - deviation /oc-test-xfmr:test-xfmr/oc-test-xfmr:global-sensor { - deviate add { - sonic-ext:table-name "TEST_SENSOR_GLOBAL"; - sonic-ext:key-name "global_sensor"; - } - } -} - diff --git a/models/yang/openconfig-platform-transceiver.yang b/models/yang/openconfig-platform-transceiver.yang index c70a4fdda..2c2cee442 100644 --- a/models/yang/openconfig-platform-transceiver.yang +++ b/models/yang/openconfig-platform-transceiver.yang @@ -17,6 +17,7 @@ module openconfig-platform-transceiver { import openconfig-types { prefix oc-types; } import openconfig-extensions { prefix oc-ext; } import openconfig-yang-types { prefix oc-yang; } + import openconfig-alarm-types { prefix oc-alarm-types; } // meta @@ -65,7 +66,55 @@ module openconfig-platform-transceiver { specify a physical-channel within a TRANSCEIVER component (i.e. gray optic) that it is associated with."; - oc-ext:openconfig-version "0.9.0"; + oc-ext:openconfig-version "0.16.0"; + + revision "2024-10-09" { + description + "Add status flags for transceiver host lanes and media channels."; + reference "0.16.0"; + } + + revision "2024-09-21" { + description + "Clearly define how physical channel power leaves are used."; + reference "0.15.0"; + } + + revision "2023-08-30" { + description + "Clarify transceiver module threshold for input-power."; + reference "0.14.0"; + } + + revision "2023-08-30" { + description + "Add transceiver module temperature thresholds"; + reference "0.13.0"; + } + + revision "2023-06-27" { + description + "Add tx bias and voltage thresholds"; + reference "0.12.0"; + } + + revision "2023-05-03" { + description + "Increase max length of vendor-rev to 4."; + reference "0.11.0"; + } + + revision "2023-02-10" { + description + "Fixing linting issues."; + reference "0.10.1"; + } + + revision "2023-01-12" { + description + "Add laser power and temperature thresholds"; + reference "0.10.0"; + } revision "2021-07-29" { description @@ -167,7 +216,11 @@ module openconfig-platform-transceiver { Values include the instantaneous, average, minimum, and maximum statistics. If avg/min/max statistics are not supported, the target is expected to just supply the - instant value"; + instant value. In some cases, such as when the physical + channel has a leafref to an optical channel component and the + module-functional-type is TYPE_DIGITAL_COHERENT_OPTIC this + grouping will NOT be used as the data will be within the + optical-channel"; uses oc-types:avg-min-max-instant-stats-precision2-dBm; } @@ -184,7 +237,12 @@ module openconfig-platform-transceiver { Values include the instantaneous, average, minimum, and maximum statistics. If avg/min/max statistics are not supported, the target is expected to just supply the - instant value"; + instant value. When the physical channel has a leafref to + an optical channel component and the module-functional-type is + TYPE_DIGITAL_COHERENT_OPTIC this represents the aggregate + total optical power value (signal and noise) whereas + optical power value within the optical-channel represents + the signal power"; uses oc-types:avg-min-max-instant-stats-precision2-dBm; } @@ -196,7 +254,11 @@ module openconfig-platform-transceiver { with up to two decimal precision. Values include the instantaneous, average, minimum, and maximum statistics. If avg/min/max statistics are not supported, the target is - expected to just supply the instant value"; + expected to just supply the instant value. In some cases, + such as when the physical channel has a leafref to an optical + channel component and the module-functional-type is + TYPE_DIGITAL_COHERENT_OPTIC this grouping will NOT be used + as the data will be within the optical-channel"; uses oc-types:avg-min-max-instant-stats-precision2-mA; } @@ -214,7 +276,12 @@ module openconfig-platform-transceiver { "The frequency in MHz of the individual physical channel (e.g. ITU C50 - 195.0THz and would be reported as 195,000,000 MHz in this model). This attribute is not - configurable on most client ports."; + configurable on most client ports In some cases, such as when + the physical channel has a leafref to an optical channel + component and the module-functional-type is + TYPE_DIGITAL_COHERENT_OPTIC this grouping will NOT be used + as the data will be within the optical-channel."; + } } @@ -347,6 +414,29 @@ module openconfig-platform-transceiver { uses oc-opt-types:avg-min-max-instant-stats-precision2-pct; } + leaf tx-failure { + type boolean; + description + "Transmitter failure flag. + In earlier standards, including SFF-8436, SFF-8472, and QSFP-DD CMIS 4.0, + this flag was named Tx Fault."; + reference "QSFP-DD CMIS 5.0 Table 8-77, SFF-8472 Table 9-11, SFF-8436 Table 19"; + } + + leaf rx-los { + type boolean; + description + "Receiver loss-of-signal flag."; + reference "QSFP-DD CMIS 5.0 Table 8-78, SFF-8472 Table 9-11, SFF-8436 Table 19"; + } + + leaf rx-cdr-lol { + type boolean; + description + "Receiver clock-and-data-recovery loss-of-lock flag."; + reference "QSFP-DD CMIS 5.0 Table 8-78"; + } + uses physical-channel-state-extended { when "../../../state/module-functional-type = 'oc-opt-types:TYPE_STANDARD_OPTIC'" { description @@ -413,6 +503,121 @@ module openconfig-platform-transceiver { } } + grouping host-lane-config { + description + "Configuration data for electrical host lanes."; + + leaf lane-number { + type uint8 { + range 1..max; + } + description + "Number identifying an electrical host lane carrying one serial + signal. Lanes are numbered starting with 1."; + reference "CMIS 5.0 section 2.3.4"; + } + } + + grouping host-lane-state { + description + "Operational state data for electrical host lanes."; + + leaf tx-los { + type boolean; + description + "Transmitter loss-of-signal flag."; + reference "CMIS 5.0 Table 8-77, SFF-8436 Table 19"; + } + + leaf tx-cdr-lol { + type boolean; + description + "Transmitter clock-and-data-recovery loss-of-lock flag."; + reference "CMIS 5.0 Table 8-77"; + } + } + + grouping host-lane-top { + description + "Top-level grouping for electrical host lanes."; + + container host-lanes { + description + "Enclosing container for host lanes."; + + list lane { + key "lane-number"; + description + "List of electrical host lanes, keyed by lane number. + The host lanes of a transceiver constitute its electrical interface + with the host system."; + reference "CMIS 5.0 section 4.1"; + + leaf lane-number { + type leafref { + path "../config/lane-number"; + } + description + "Reference to the host lane number."; + } + + container config { + description + "Configuration data for host lanes."; + + uses host-lane-config; + } + + container state { + config false; + description + "Operational state data for host lanes."; + + uses host-lane-config; + uses host-lane-state; + } + } + } + } + + grouping transceiver-threshold-top { + description + "Top-level grouping for transceiver alarm thresholds for + various sensors."; + + container thresholds { + description + "Enclosing container for transceiver alarm thresholds."; + + list threshold { + key "severity"; + config false; + description + "List of transceiver alarm thresholds, indexed by + alarm severity."; + + leaf severity { + type leafref { + path "../state/severity"; + } + config false; + description + "The severity applied to the group of thresholds. + An implementation's highest severity threshold + should be mapped to OpenConfig's `CRITICAL` + severity level."; + } + + container state { + config false; + description + "Operational alarm thresholds for the transceiver."; + + uses transceiver-threshold-state; + } + } + } + } grouping port-transceiver-config { description @@ -550,10 +755,10 @@ module openconfig-platform-transceiver { leaf vendor-rev { type string { - length 1..2; + length 1..4; } description - "Transceiver vendor's revision number. 2-octet field that + "Transceiver vendor's revision number. Field of 1 to 4 octets that contains ASCII characters, left-aligned and padded on the right with ASCII spaces (20h)"; } @@ -687,6 +892,137 @@ module openconfig-platform-transceiver { uses optical-power-state; } + grouping transceiver-threshold-state { + description + "Grouping for all alarm threshold configs for a particular + severity level."; + leaf severity { + type identityref { + base oc-alarm-types:OPENCONFIG_ALARM_SEVERITY; + } + description + "The type of alarm to which the thresholds apply."; + } + leaf laser-temperature-upper { + type decimal64 { + fraction-digits 1; + } + units celsius; + description + "The upper temperature threshold for the laser temperature sensor. + This leaf value is compared to the instant value of + laser-temperature."; + } + leaf laser-temperature-lower { + type decimal64 { + fraction-digits 1; + } + units celsius; + description + "The lower temperature threshold for the laser temperature sensor. + This leaf value is compared to the instant value of + laser-temperature."; + } + leaf output-power-upper{ + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "The upper power threshold for the laser output power. This threshold + applies to every physical-channel on the transceiver and does not + apply to the aggregate transceiver optical-output-power. This leaf + value is compared to the instant value of optical-output-power."; + } + leaf output-power-lower{ + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "The lower power threshold for the laser output power. This threshold + applies to every physical-channel on the transceiver and does not + apply to the aggregate transceiver optical-output-power. This leaf + value is compared to the instant value of optical-output-power."; + } + leaf input-power-upper{ + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "The upper power threshold for the laser input power. This threshold + applies to every physical-channel on the transceiver and does not + apply to the aggregate transceiver optical-input-power. This leaf + value is compared to the instant value of optical-input-power."; + } + leaf input-power-lower{ + type decimal64 { + fraction-digits 2; + } + units dBm; + description + "The lower power threshold for the laser input power. This threshold + applies to every physical-channel on the transceiver and does not + apply to the aggregate transceiver optical-input-power. This leaf + value is compared to the instant value of optical-input-power."; + } + leaf laser-bias-current-upper{ + description + "The upper threshold for the laser bias current. This leaf value is + compared to the instant value of last-bias-current."; + type decimal64 { + fraction-digits 2; + } + units mA; + } + leaf laser-bias-current-lower{ + description + "The lower threshold for the laser bias current. This leaf value is + compared to the instant value of last-bias-current."; + type decimal64 { + fraction-digits 2; + } + units mA; + } + leaf supply-voltage-upper{ + description + "The upper threshold for the transceiver supply voltage. This leaf + value is compared to the instant value of supply-voltage."; + type decimal64 { + fraction-digits 2; + } + units volts; + } + leaf supply-voltage-lower{ + description + "The lower threshold for the transceiver supply voltage. This leaf + value is compared to the instant value of supply-voltage."; + type decimal64 { + fraction-digits 2; + } + units volts; + } + leaf module-temperature-lower { + type decimal64 { + fraction-digits 1; + } + units celsius; + description + "The lower temperature threshold for the transceiver module. This + leaf value is compared to the instant value of module-temperature."; + } + leaf module-temperature-upper { + type decimal64 { + fraction-digits 1; + } + units celsius; + description + "The upper temperature threshold for the transceiver module. This + leaf value is compared to the instant value of module-temperature."; + } + } + grouping port-transceiver-top { description "Top-level grouping for client port transceiver data"; @@ -715,6 +1051,8 @@ module openconfig-platform-transceiver { // physical channels are associated with a transceiver // component uses physical-channel-top; + uses host-lane-top; + uses transceiver-threshold-top; } } diff --git a/models/yang/openconfig-test-xfmr.yang b/models/yang/openconfig-test-xfmr.yang deleted file mode 100644 index 30fac6865..000000000 --- a/models/yang/openconfig-test-xfmr.yang +++ /dev/null @@ -1,678 +0,0 @@ -module openconfig-test-xfmr { - - yang-version "1"; - - // namespace - namespace "http://openconfig.net/yang/test-xmfr"; - - prefix "oc-test-xfmr"; - - import openconfig-extensions { prefix oc-ext; } - - // meta - organization "OpenConfig working group"; - - contact - "OpenConfig working group www.openconfig.net"; - - description - "Data model which creates the configuration to exercise - and test transformer infrastructure that does yang-model - to/from Redis/ABNF schema data-translation."; - - oc-ext:openconfig-version "0.2.0"; - - revision "2023-04-30" { - description - "OpenConfig public release"; - reference "0.2.0"; - } - - // OpenConfig specific extensions for module metadata. - oc-ext:regexp-posix; - oc-ext:catalog-organization "openconfig"; - oc-ext:origin "openconfig"; - - identity TEST_SET_TYPE { - description - "Base identity for types of ACL sets"; - } - - identity TEST_SET_IPV4 { - base TEST_SET_TYPE; - description - "IP-layer test set with IPv4 addresses"; - } - - identity TEST_SET_IPV6 { - base TEST_SET_TYPE; - description - "IP-layer test set with IPv6 addresses"; - } - - grouping test-sensor-group-top { - description - "Top level grouping for test-sensor-group configuration and operational - state data"; - - container test-sensor-groups { - description - "Top level container for test-sensor-groups."; - - list test-sensor-group { - key "id"; - description - "List of test sensory groups on the local - system, where a sensor grouping represents a resuable - grouping of multiple types and exclude filters."; - - leaf id { - type leafref { - path "../config/id"; - } - description - "Reference to the name or identifier of the - test sensor grouping"; - } - - container config { - description - "Configuration parameters relating to the - test sensor grouping"; - uses test-sensor-group-config; - } - - container state { - config false; - description - "State information relating to the test - sensor group"; - uses test-sensor-group-config; - uses test-sensor-group-counters; - } - - container test-sensor-types { - description - "Top level container to hold a set of sensor - types grouped together"; - - list test-sensor-type { - key "type"; - description - "List of types of sensors which together - comprise a test sensor grouping. Filters for each type - to exclude items are also provided."; - - leaf type { - type leafref { - path "../config/type"; - } - description - "Reference to the type of interest"; - } - - container config { - description - "Configuration parameters to configure a set - of sensor types as a sensor grouping"; - uses test-sensor-type-config; - } - - container state { - config false; - description - "Configuration parameters to configure a set - of sensor types as a sensor grouping"; - uses test-sensor-type-config; - } - - container sensor-a-light-sensors { - description - "Top level container to hold a set of sensor - a type light sensors grouped together"; - - list sensor-a-light-sensor { - key "tag"; - description - "List of sensor a type light sensors together - comprise a test sensor a grouping."; - - leaf tag { - type leafref { - path "../config/tag"; - } - description - "Reference to the id of interest"; - } - - container config { - description - "Configuration parameters to configure a set - of ligt sensors as a sensor a grouping"; - uses sensor-a-light-sensor-config; - } - - container state { - config false; - description - "Parameters of a set ligt sensors - as a sensor a grouping"; - uses sensor-a-light-sensor-config; - } - } - } - } - } - uses test-sensor-components-top; - uses test-sensor-zones-top; - } - } - } - // identity statements - - // typedef statements - - // grouping statements - - grouping test-set-top { - description - "Access list entries variables top level container"; - - container test-sets { - description - "Access list entries variables enclosing container"; - - list test-set { - key "name type"; - description - "List of test sets"; - - leaf name { - type leafref { - path "../config/name"; - } - description - "Reference to the name list key"; - } - - leaf type { - type leafref { - path "../config/type"; - } - description - "Reference to the type list key"; - } - - container config { - description - "Test set config"; - uses test-set-config; - } - - container state { - config false; - description - "Test set state information"; - uses test-set-config; - } - } - } - } - - grouping interfaces-top { - description - "Top-level grouping for interface-specific test set data"; - - container interfaces { - description - "Enclosing container for the list of interfaces on which - test set exists"; - - list interface { - key "id"; - description - "List of interfaces on which test set exists"; - - leaf id { - type leafref { - path "../config/id"; - } - description - "Reference to the interface id list key"; - } - - container config { - description - "Configuration for test-set per-interface data"; - - uses interfaces-config; - } - - container state { - - config false; - - description - "Operational state for test-set per-interface data"; - - uses interfaces-config; - } - - uses interface-ingress-test-set-top; - } - } - } - - grouping interface-ingress-test-set-top { - description - "Top-level grouping for per-interface ingress test set data"; - - container ingress-test-sets { - description - "Enclosing container the list of ingress test sets on the interface"; - - list ingress-test-set { - key "set-name type"; - description - "List of ingress test set on the interface"; - - leaf set-name { - type leafref { - path "../config/set-name"; - } - description - "Reference to set name list key"; - } - - leaf type { - type leafref { - path "../config/type"; - } - description - "Reference to type list key"; - } - - container config { - description - "Configuration data "; - - uses interface-ingress-test-set-config; - } - - container state { - - config false; - - description - "Operational state data for interface ingress test sets"; - - uses interface-ingress-test-set-config; - } - - } - } - } - - //////////////////////////// - - grouping test-sensor-group-config { - description - "Config parameters related to the test sensor groups"; - leaf id { - type string; - description - "Name or identifier for the test sensor group itself. - Will be referenced by other configuration specifying a - sensor group"; - } - - leaf-list group-colors { - type string; - description - "Colors thta can be applied to a test sensor group."; - } - - leaf color-hold-time { - type uint32; - units seconds; - default 10; - description - "Number of seconds a color can be held on a test sonsor group."; - } - - } - - grouping test-sensor-group-counters { - description - "Definition of test sensor group counters"; - - container counters { - description - "Test sensor group counters"; - - leaf frame-in { - type uint32; - description - "The number frames received."; - } - - leaf frame-out { - type uint32; - description - "The number of frames transmitted out."; - } - } - } - - grouping test-sensor-type-config { - description - "Configuration parameters relating to the - grouping of sensor types comprising a - sensor grouping"; - leaf type { - type string { - pattern "sensora_[a-zA-Z0-9]*|sensorb_[a-zA-Z0-9]*"; - } - description - "Sensor type name"; - } - - leaf exclude-filter { - type string; - description - "Filter to exclude certain values out of the state values"; - } - } - - grouping sensor-a-light-sensor-config { - description - "Configuration parameters relating to the - grouping of sensor a light sensors"; - leaf tag { - type string { - pattern "lightsensor_[0-9]*"; - } - description - "light sensor tag-id"; - } - - leaf light-intensity-measure { - type uint32; - default 5; - description - "Light intenity needed for sensing"; - } - } - - grouping test-set-config { - description - "Test set config"; - - leaf name { - type string; - description - "The name of the test set"; - } - - leaf type { - type identityref { - base TEST_SET_TYPE; - } - description - "The type determines the type test set"; - } - - leaf description { - type string; - description - "Description, or comment, for the test set"; - } - - } - - /////////////////// - grouping test-sensor-component-config { - description - "Configuration data for sensor-components"; - - leaf name { - type string; - description - "Device name for the sensor component. "; - } - leaf type { - type enumeration { - enum TYPE1 { - description - "Component Type 1."; - } - enum TYPE2 { - description - "Component Type 2."; - } - enum TYPE3 { - description - "Component Type 3."; - } - } - } - leaf version { - type string; - description - "Version of the Component. "; - } - leaf description { - type string; - description - "Description, or comment, for the test sensor component"; - } - } - - grouping test-sensor-component-state { - description - "Operational State data for sensor components"; - leaf mfg-name { - type string; - description - "System-supplied identifier for the manufacturer of the component."; - } - - leaf mfg-date { - type string; - description - "System-supplied representation of the component's - manufacturing date."; - } - - leaf hardware-version { - type string; - description - "For hardware components, this is the hardware revision of - the component."; - } - - leaf firmware-version { - type string; - description - "For hardware components, this is the version of associated - firmware that is running on the component, if applicable."; - } - } - - grouping test-sensor-components-top { - container test-sensor-components { - description - "Enclosing container for test sensor component references"; - - list test-sensor-component { - key "name type version"; - description - "List of sensor component references"; - - leaf name { - type leafref { - path "../config/name"; - } - description - "Reference to the name of component"; - } - - leaf type { - type leafref { - path "../config/type"; - } - description - "Reference to the type of component"; - } - - leaf version { - type leafref { - path "../config/version"; - } - description - "Reference to the version of component"; - } - - container config { - description - "Configuration parameters to configure a sensor component"; - uses test-sensor-component-config; - } - - container state { - config false; - description - "Operational state parameters of a sensor component"; - uses test-sensor-component-config; - uses test-sensor-component-state; - } - } - } - } - - grouping test-sensor-zones-top { - container test-sensor-zones { - description - "Top level container to hold a set of sensor - zones grouped together"; - - list test-sensor-zone { - key "zone"; - description - "List of zones of sensors which together - comprise a test sensor grouping."; - - leaf zone { - type leafref { - path "../config/zone"; - } - description - "Reference to the sensor zone"; - } - - container config { - description - "Configuration parameters to configure zone of a sensor grouping"; - leaf zone { - type string; - description - "Reference to the sensor zone"; - } - leaf description { - type string; - description - "global sensor description"; - } - } - - container state { - config false; - description - "State data of the configured zones of a sensor grouping"; - leaf zone { - type string; - description - "Reference to the sensor zone"; - } - } - } - } - } - - - - grouping interfaces-config { - description - "Configuration data for interface references"; - - leaf id { - type string { - pattern "Eth_" + ".*"; - } - description - "identifier for the interface"; - } - } - - grouping interface-ingress-test-set-config { - description - "Configuration data for per-interface ingress test-set"; - - leaf set-name { - type leafref { - path "../../../../../../test-sets/test-set/config/name"; - } - description - "Reference to the test set name applied on ingress"; - } - - leaf type { - type leafref { - path "../../../../../../test-sets/test-set[name=current()/../set-name]" + - "/config/type"; - } - description - "Reference to the test set type applied on ingress"; - } - - } - - grouping test-global-sensor-config { - container global-sensor { - description - "Configuration data for global sensor."; - - leaf mode { - type string; - description - "global sensor mode"; - } - - leaf description { - type string; - description - "global sensor description"; - } - } - } - /////////////////// - - // data definition statements - - container test-xfmr { - description - "Top level configuration and state for the test-xfmr system."; - - uses test-sensor-group-top; - uses test-set-top; - uses interfaces-top; - uses test-global-sensor-config; - } - // augment statements - - // rpc statements - - // notification statements - -} - diff --git a/models/yang/sonic/import.mk b/models/yang/sonic/import.mk index e28360c30..042297599 100644 --- a/models/yang/sonic/import.mk +++ b/models/yang/sonic/import.mk @@ -12,4 +12,4 @@ SONICYANG_IMPORTS += sonic-portchannel.yang SONICYANG_IMPORTS += sonic-vlan.yang SONICYANG_IMPORTS += sonic-mclag.yang SONICYANG_IMPORTS += sonic-types.yang -SONICYANG_IMPORTS += sonic-vrf.yang \ No newline at end of file +SONICYANG_IMPORTS += sonic-vrf.yang diff --git a/models/yang/sonic/sonic-test-xfmr.yang b/models/yang/sonic/sonic-test-xfmr.yang deleted file mode 100644 index df4751924..000000000 --- a/models/yang/sonic/sonic-test-xfmr.yang +++ /dev/null @@ -1,344 +0,0 @@ -module sonic-test-xfmr { - namespace "http://github.com/Azure/sonic-test-xfmr"; - prefix sonic-test-xfmr; - yang-version 1; - - import sonic-extension { prefix sonic-ext; } - - organization - "SONiC"; - - contact - "SONiC"; - - description - "SONIC transformer test yang"; - - revision 2023-04-30 { - description - "Initial revision of Sonic transformer test yang."; - } - - container sonic-test-xfmr { - - container TEST_SENSOR_GROUP { - - list TEST_SENSOR_GROUP_LIST { - key "id"; - - leaf id { - type string; - } - - leaf-list colors { - type string; - } - - leaf color-hold-time { - type uint32; - default 10; - description "Hold time"; - } - } - } - - container TEST_SENSOR_GROUP_COUNTERS { - config false; - - list TEST_SENSOR_GROUP_COUNTERS_LIST { - key "id"; - - leaf id { - type leafref { - path "../../../TEST_SENSOR_GROUP/TEST_SENSOR_GROUP_LIST/id"; - } - } - - leaf frame-in { - type uint32; - } - - leaf frame-out { - type uint32; - } - } - } - - container TEST_SENSOR_A_TABLE { - - list TEST_SENSOR_A_TABLE_LIST { - key "id type"; - - leaf id { - type leafref { - path "../../../TEST_SENSOR_GROUP/TEST_SENSOR_GROUP_LIST/id"; - } - } - - leaf type { - type string { - pattern "sensor_type_a_[a-zA-Z0-9]*"; - } - } - - leaf exclude_filter { - type string; - } - - leaf description_a { - type string; - } - } - } - - container TEST_SENSOR_A_LIGHT_SENSOR_TABLE { - - list TEST_SENSOR_A_LIGHT_SENSOR_TABLE_LIST { - key "id type tag"; - - leaf id { - type leafref { - path "../../../TEST_SENSOR_A_TABLE/TEST_SENSOR_A_TABLE_LIST/id"; - } - } - - leaf type { - type leafref { - path "../../../TEST_SENSOR_A_TABLE/TEST_SENSOR_A_TABLE_LIST/type"; - } - } - - leaf tag { - type string { - pattern "light_sensor_[0-9]*"; - } - } - - leaf light-intensity-measure { - type uint32; - default 5; - } - - } - } - - container TEST_SENSOR_B_TABLE { - - list TEST_SENSOR_B_TABLE_LIST { - key "id type"; - - leaf id { - type leafref { - path "../../../TEST_SENSOR_GROUP/TEST_SENSOR_GROUP_LIST/id"; - } - } - - leaf type { - type string { - pattern "sensor_type_b_[a-zA-Z0-9]*"; - } - } - - leaf exclude_filter { - type string; - } - - leaf description_b { - type string; - } - } - } - - container TEST_SENSOR_COMPONENT_TABLE { - - list TEST_SENSOR_COMPONENT_TABLE_LIST { - key "name type version"; - - leaf name { - type string; - } - - leaf type { - type string; - } - - leaf version { - type string; - } - - leaf description { - type string; - } - } - } - - container TEST_SENSOR_ZONE_TABLE { - list TEST_SENSOR_ZONE_TABLE_LIST { - key "id zone"; - - leaf id { - type string; - } - - leaf zone { - type string; - } - - leaf description { - type string; - } - } - } - - container TEST_SET_TABLE { - - list TEST_SET_TABLE_LIST { - key "name"; - - leaf name { - type string; - } - - leaf type { - type enumeration { - enum IPV4; - enum IPV6; - } - } - - leaf-list ports { - type string; - } - - leaf description { - type string; - } - - } - } - - container TEST_SENSOR_MODE_TABLE { - config false; - sonic-ext:db-name "COUNTERS_DB"; - list TEST_SENSOR_MODE_TABLE_LIST { - key "mode id"; - - leaf mode { - type string; - } - - leaf id { - type uint32; - } - - leaf description { - type string; - } - } - } - - container TEST_SENSOR_GLOBAL { - container global_sensor { - leaf mode { - type string; - } - leaf description { - type string; - } - leaf reset_time { - type uint32; - default 5; - } - } - container global_sensor_timer { - leaf timer_mode { - type string; - } - leaf timer_description { - type string; - } - leaf reset_time { - type uint32; - default 5; - } - } - list TEST_SENSOR_GLOBAL_LIST { - key "device_name device_id"; - leaf device_name { - type string; - } - leaf device_id { - type uint32; - } - leaf device_status { - type enumeration { - enum ON; - enum OFF; - } - } - - } - - } - - container TEST_INTERFACE_MODE_TABLE { - list TEST_INTERFACE_MODE_TABLE_LIST { - key "name"; - - leaf name { - type string; - } - leaf description { - type string; - } - } - list TEST_INTERFACE_MODE_TABLE_IPADDR_LIST { - key "name mode"; - - leaf name { - type string; - } - leaf mode { - type string; - } - leaf description { - type string; - } - } - } - - container TEST_CABLE_LENGTH { - - description "TEST_CABLE_LENGTH to test nested list yang support"; - - list TEST_CABLE_LENGTH_LIST { - key "name"; - - leaf name { - type string { - length 1..32 { - error-message "Invalid length for the cable length list name."; - error-app-tag cable-length-invalid-list-name-length; - } - } - } - list TEST_CABLE_LENGTH { - key "port"; - leaf port { - type leafref { - path "../../../../TEST_INTERFACE_MODE_TABLE/TEST_INTERFACE_MODE_TABLE_LIST/name"; - } - } - leaf length { - type string { - pattern '[0-9]+m' { - error-message "Invalid cable length."; - error-app-tag cable-length-invalid-length; - } - } - } - } - } - } - } -} diff --git a/translib/db/db_config.go b/translib/db/db_config.go index 7874f3494..4b0bc1b55 100644 --- a/translib/db/db_config.go +++ b/translib/db/db_config.go @@ -173,6 +173,6 @@ func getDbPassword(dbName string) string { return password } -func GetDbConfigMap() map[string]interface{} { - return dbConfigMap +func GetMdbConfigMap() map[string]map[string]interface{} { + return multiDbsConfigMap } diff --git a/translib/db/db_util.go b/translib/db/db_util.go index aa1043c2a..e851857ca 100644 --- a/translib/db/db_util.go +++ b/translib/db/db_util.go @@ -65,13 +65,19 @@ func fetchDbNameFromGlobalJson() string { } func GetMultiDbNames() []string { + // Case 1: NumAsic is 1 → return host only + if NumAsic == 1 { + return []string{"host"} + } + + // Case 2: NumAsic > 1 → return asic DBs only dbNames := []string{"host"} cmnDbName := fetchDbNameFromGlobalJson() - if isMultiAsic() { - for num := 0; num < NumAsic; num++ { - dbNames = append(dbNames, cmnDbName+strconv.Itoa(num)) - } + + for num := 0; num < NumAsic; num++ { + dbNames = append(dbNames, cmnDbName+strconv.Itoa(num)) } + return dbNames } diff --git a/translib/transformer/testxfmryang_test.go b/translib/transformer/testxfmryang_test.go index 2cb608326..f0317ae5a 100644 --- a/translib/transformer/testxfmryang_test.go +++ b/translib/transformer/testxfmryang_test.go @@ -25,17 +25,24 @@ import ( "testing" "time" + "github.com/Azure/sonic-mgmt-common/cvl" "github.com/Azure/sonic-mgmt-common/translib/db" "github.com/Azure/sonic-mgmt-common/translib/tlerr" ) +type verifyDbResultData struct { + test string + db_key string + db_result map[string]interface{} +} + func Test_node_exercising_subtree_xfmr_and_virtual_table(t *testing.T) { var /*pre_req_map, */ expected_map, cleanuptbl map[string]interface{} var url, url_body_json string t.Log("\n\n+++++++++++++ Performing Set on Yang Node Exercising Subtree-Xfmr and Virtual Table ++++++++++++") url = "/openconfig-test-xfmr:test-xfmr/interfaces" - url_body_json = "{ \"openconfig-test-xfmr:interface\": [ { \"id\": \"Eth_0\", \"config\": { \"id\": \"Eth_0\" }, \"ingress-test-sets\": { \"ingress-test-set\": [ { \"set-name\": \"TestSet_01\", \"type\": \"TEST_SET_IPV4\", \"config\": { \"set-name\": \"TestSet_01\", \"type\": \"TEST_SET_IPV4\" } } ] } } ]}" + url_body_json = "{\"openconfig-test-xfmr:interface\": [ { \"id\": \"Eth_0\", \"config\": { \"id\": \"Eth_0\" }, \"ingress-test-sets\": { \"ingress-test-set\": [ { \"set-name\": \"TestSet_01\", \"type\": \"TEST_SET_IPV4\", \"config\": { \"set-name\": \"TestSet_01\", \"type\": \"TEST_SET_IPV4\" } } ] } } ]}" expected_map = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_01_TEST_SET_IPV4": map[string]interface{}{"ports@": "Eth_0", "type": "IPV4"}}} cleanuptbl = map[string]interface{}{"TEST_SET_TABLE": map[string]interface{}{"TestSet_01_TEST_SET_IPV4": ""}} t.Run("Test set on node exercising subtree-xfmr and virtual table.", processSetRequest(url, url_body_json, "POST", false, nil)) @@ -134,14 +141,11 @@ func Test_node_exercising_tableName_key_and_field_xfmr(t *testing.T) { func Test_node_exercising_pre_xfmr_node(t *testing.T) { t.Log("\n\n+++++++++++++ Performing set on node exercising pre-xfmr ++++++++++++") - err_str := "REPLACE not supported at this node." - expected_err := tlerr.NotSupportedError{Format: err_str} - //expected_err := tlerr.NotSupported("REPLACE not supported at this node.") - url := "/openconfig-test-xfmr:test-xfmr/test-sets" - url_body_json := "{ \"openconfig-test-xfmr:test-sets\": { \"test-set\": [ { \"name\": \"TestSet_03\", \"type\": \"TEST_SET_IPV4\", \"config\": { \"name\": \"TestSet_03\", \"type\": \"TEST_SET_IPV4\", \"description\": \"testSet_03 description\" } } ] }}" + expected_err := tlerr.NotSupportedError{Format: "REPLACE not supported at this node."} + url := "/openconfig-test-xfmr:test-xfmr" + url_body_json := "{\"openconfig-test-xfmr:test-xfmr\":{ \"test-sets\": { \"test-set\": [ { \"name\": \"TestSet_03\", \"type\": \"TEST_SET_IPV4\", \"config\": { \"name\": \"TestSet_03\", \"type\": \"TEST_SET_IPV4\", \"description\": \"testSet_03 description\" } } ] }}}" t.Run("Test set on node exercising pre-xfmr.", processSetRequest(url, url_body_json, "PUT", true, expected_err)) t.Log("\n\n+++++++++++++ Done Performing set on node exercising pre-xfmr ++++++++++++") - } func Test_node_with_child_tableXfmr_keyXfmr_fieldNameXfmrs_nonConfigDB_data(t *testing.T) { @@ -205,26 +209,306 @@ func Test_node_with_child_tableXfmr_keyXfmr_fieldNameXfmrs_nonConfigDB_data(t *t unloadDB(hostDBName, db.ConfigDB, cleanuptbl) } -func Test_delete_on_node_with_default_value(t *testing.T) { +func Test_node_exercising_tableXfmr_virtual_table_and_validate_handler(t *testing.T) { + /* verify if replace at a higher level yang node happens correctly when replacing nodes having table-xfmr, virtual-table and validate handler annotation in child yang hierachy */ + prereq_ni_instance := map[string]interface{}{"TEST_VRF": map[string]interface{}{"default": map[string]interface{}{"enabled": "true"}, + "Vrf_01": map[string]interface{}{"enabled": "false"}, "Vrf_02": map[string]interface{}{"enabled": "false", "description": "Vrf_02 descrip"}, + "Vrf_03": map[string]interface{}{"enabled": "true"}}} + prereq_bgp := map[string]interface{}{"TEST_BGP_NETWORK_CFG": map[string]interface{}{"Vrf_01|22": map[string]interface{}{"backdoor": "true", "policy-name": "abcd"}, + "Vrf_01|33": map[string]interface{}{"backdoor": "false", "policy-name": "xyzefgh"}, + "Vrf_02|101": map[string]interface{}{"backdoor": "false"}}} + prereq_ospfv2_router := map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true", "write-multiplier": "2"}, + "Vrf_02": map[string]interface{}{"enabled": "true"}, + "Vrf_03": map[string]interface{}{"write-multiplier": "5"}}} + prereq_ospfv2_router_distribution := map[string]interface{}{"TEST_OSPFV2_ROUTER_DISTRIBUTION": map[string]interface{}{"Vrf_01|66": map[string]interface{}{"priority": "3"}, + "Vrf_01|98": map[string]interface{}{"priority": "56", "table-id": "4"}, "Vrf_03|79": map[string]interface{}{"priority": "7", "table-id": "74"}}} + + cleanuptbl := map[string]interface{}{"TEST_VRF": map[string]interface{}{"default": "", "Vrf_01": "", "Vrf_02": "", "Vrf_03": ""}, + "TEST_BGP_NETWORK_CFG": map[string]interface{}{"Vrf_01|22": "", "Vrf_01|33": "", "Vrf_02|101": "", "Vrf_02|55": ""}, + "TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": "", "Vrf_02": "", "Vrf_03": ""}, + "TEST_OSPFV2_ROUTER_DISTRIBUTION": map[string]interface{}{"Vrf_01|66": "", "Vrf_01|98": "", "Vrf_02|81": "", "Vrf_03|79": ""}} + + //Setup + loadDB(hostDBName, db.ConfigDB, prereq_ni_instance) + loadDB(hostDBName, db.ConfigDB, prereq_bgp) + loadDB(hostDBName, db.ConfigDB, prereq_ospfv2_router) + loadDB(hostDBName, db.ConfigDB, prereq_ospfv2_router_distribution) + + t.Log("+++++++++++++++++ Test replace at high level in yang hierachy involing table-xfmr, virtual-table and validate handler annotations +++++++++++++++") + url := "/openconfig-test-xfmr:test-xfmr/test-ni-instances/test-ni-instance" + //TODOswag + url_body_json := "{\"openconfig-test-xfmr:test-ni-instance\":[{\"ni-name\":\"default\"," + + "\"config\":{\"ni-name\":\"default\",\"enabled\":true}},{\"ni-name\":\"vrf-02" + + "\",\"config\":{\"ni-name\":\"vrf-02\",\"enabled\":true},\"test-protocols\":" + + "{\"test-protocol\":[{\"name\":\"ospfv2\",\"config\":{\"name\":\"ospfv2\"}," + + "\"ospfv2\":{\"global\":{\"config\":{\"enabled\":true}," + + "\"route-distribution-lists\":{\"route-distribution-list\":[{\"distribution" + + "-id\":81,\"config\":{\"distribution-id\":81,\"priority\":9,\"table-id\":67}" + + "}]}}}}]}},{\"ni-name\":\"vrf-01\",\"config\":{\"ni-name\":\"vrf-01\",\"enab" + + "led\":true,\"description\":\"01 descrip\"},\"test-protocols\":{\"test-pro" + + "tocol\":[{\"name\":\"bgp\",\"config\":{\"name\":\"bgp\"},\"bgp\":{\"network-cf" + + "gs\":{\"network-cfg\":[{\"network-id\":22,\"config\":{\"network-id\":22,\"poli" + + "cy-name\":\"defgh\",\"backdoor\":false}},{\"network-id\":33,\"config\":{\"netw" + + "ork-id\":33,\"policy-name\":\"fgh\"}}]}}},{\"name\":\"ospfv2\",\"config\":{" + + "\"name\":\"ospfv2\"},\"ospfv2\":{\"global\":{\"config\":{\"enabled\":true,\"w" + + "rite-multiplier\":3},\"route-distribution-lists\":{\"route-distribution-list" + + "\":[{\"distribution-id\":66,\"config\":{\"distribution-id\":66,\"priorit" + + "y\":6}}]}}}}]}}]}" + + empty_expected := map[string]interface{}{} + expected_ni_instance_default := map[string]interface{}{"TEST_VRF": map[string]interface{}{"default": map[string]interface{}{"enabled": "true"}}} + expected_ni_instance_vrf_01 := map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true", "description": "01 descrip"}}} + expected_ni_instance_vrf_02 := map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_02": map[string]interface{}{"enabled": "true"}}} + expected_bgp_vrf_01_22 := map[string]interface{}{"TEST_BGP_NETWORK_CFG": map[string]interface{}{"Vrf_01|22": map[string]interface{}{"backdoor": "false", "policy-name": "defgh"}}} + expected_bgp_vrf_01_33 := map[string]interface{}{"TEST_BGP_NETWORK_CFG": map[string]interface{}{"Vrf_01|33": map[string]interface{}{"policy-name": "fgh"}}} + expected_ospfv2_router_vrf_01 := map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true", "write-multiplier": "3"}}} + expected_ospfv2_router_vrf_02 := map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_02": map[string]interface{}{"enabled": "true"}}} + expected_ospfv2_router_distribution_vrf_01_66 := map[string]interface{}{"TEST_OSPFV2_ROUTER_DISTRIBUTION": map[string]interface{}{"Vrf_01|66": map[string]interface{}{"priority": "6"}}} + expected_ospfv2_router_distribution_vrf_02_81 := map[string]interface{}{"TEST_OSPFV2_ROUTER_DISTRIBUTION": map[string]interface{}{"Vrf_02|81": map[string]interface{}{"priority": "9", "table-id": "67"}}} + t.Run("Replace at high level in yang hierachy involing table-xfmr, virtual-table and validate handler annotations.", processSetRequest(url, url_body_json, "PUT", false)) + time.Sleep(1 * time.Second) + verifyDbResultArray := [15]verifyDbResultData{ + {test: "Verify default ni-instance in request payload is present in db with data matching payload.", db_key: "TEST_VRF|default", db_result: expected_ni_instance_default}, + {test: "Verify vrf_01 ni-instance in request payload is present in db with data matching payload.", db_key: "TEST_VRF|Vrf_01", db_result: expected_ni_instance_vrf_01}, + {test: "Verify vrf_02 ni-instance in request payload is present in db with data matching payload.", db_key: "TEST_VRF|Vrf_02", db_result: expected_ni_instance_vrf_02}, + {test: "Verify vrf_03 ni-instance absent in request payload is deleted from db.", db_key: "TEST_VRF|Vrf_03", db_result: empty_expected}, + {test: "Verify bgp instance(vrf-01|22) assocaited with ni-instance in request is present in db with data matching payload.", db_key: "TEST_BGP_NETWORK_CFG|Vrf_01|22", db_result: expected_bgp_vrf_01_22}, + {test: "Verify bgp instance(vrf-01|33) assocaited with ni-instance in request is present in db with data matching payload.", db_key: "TEST_BGP_NETWORK_CFG|Vrf_01|33", db_result: expected_bgp_vrf_01_33}, + {test: "Verify bgp instance(vrf-02|101) absent in request payload is deleted from db.", db_key: "TEST_BGP_NETWORK_CFG|Vrf_02|101", db_result: empty_expected}, + {test: "Verify ospfv2 global/router(vrf-01) assocaited with ni-instance in request is present in db with data matching payload.", db_key: "TEST_OSPFV2_ROUTER|Vrf_01", db_result: expected_ospfv2_router_vrf_01}, + {test: "Verify ospfv2 global/router(vrf-02) assocaited with ni-instance in request is present in db with data matching payload.", db_key: "TEST_OSPFV2_ROUTER|Vrf_02", db_result: expected_ospfv2_router_vrf_02}, + {test: "Verify ospfv2 global/router(vrf-03) absent in request payload is deleted from db.", db_key: "TEST_OSPFV2_ROUTER|Vrf_03", db_result: empty_expected}, + {test: "Verify ospfv2 router distribution(vrf-01|66) assocaited with ni-instance in request is present in db with data matching payload.", db_key: "TEST_OSPFV2_ROUTER_DISTRIBUTION|Vrf_01|66", db_result: expected_ospfv2_router_distribution_vrf_01_66}, + {test: "Verify ospfv2 router distribution(vrf-01|98) absent in request payload is deleted from db.", db_key: "TEST_OSPFV2_ROUTER_DISTRIBUTION|Vrf_01|98", db_result: empty_expected}, + {test: "Verify ospfv2 router distribution(vrf-02|81) assocaited with ni-instance in request is created in db with data matching payload.", db_key: "TEST_OSPFV2_ROUTER_DISTRIBUTION|Vrf_02|81", db_result: expected_ospfv2_router_distribution_vrf_02_81}, + {test: "Verify ospfv2 router distribution(vrf-03|79) absent in request payload is deleted from db.", db_key: "TEST_OSPFV2_ROUTER_DSTRIBUTION|Vrf_03|79", db_result: empty_expected}, + } + time.Sleep(1 * time.Second) + for _, data := range verifyDbResultArray { + t.Run(data.test, verifyDbResult(rclient[hostDBName], data.db_key, data.db_result, false)) + } + //Tear down + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + + /* verify if get like traversal happens correctly when deleting a node having table-xfmr, virtual-table and validate handler annotation in child yang hierachy */ + t.Log("+++++++++++++++++ Test delete in yang hierachy involing table-xfmr, virtual-table and validate handler annotations +++++++++++++++") + //Setup + loadDB(hostDBName, db.ConfigDB, prereq_ni_instance) + loadDB(hostDBName, db.ConfigDB, prereq_bgp) + loadDB(hostDBName, db.ConfigDB, prereq_ospfv2_router) + loadDB(hostDBName, db.ConfigDB, prereq_ospfv2_router_distribution) + url = "/openconfig-test-xfmr:test-xfmr/test-ni-instances/test-ni-instance[ni-name=vrf-01]/test-protocols" + expected_ni_instance_vrf_01 = map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "false"}}} + expected_ni_instance_default = map[string]interface{}{"TEST_VRF": map[string]interface{}{"default": map[string]interface{}{"enabled": "true"}}} + expected_ni_instance_vrf_02 = map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_02": map[string]interface{}{"enabled": "false", "description": "Vrf_02 descrip"}}} + expected_ni_instance_vrf_03 := map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_03": map[string]interface{}{"enabled": "true"}}} + expected_bgp := map[string]interface{}{"TEST_BGP_NETWORK_CFG": map[string]interface{}{"Vrf_02|101": map[string]interface{}{"backdoor": "false"}}} + expected_ospfv2_router_vrf_02 = map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_02": map[string]interface{}{"enabled": "true"}}} + expected_ospfv2_router_vrf_03 := map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_03": map[string]interface{}{"write-multiplier": "5"}}} + expected_ospfv2_router_distribution := map[string]interface{}{"TEST_OSPFV2_ROUTER_DISTRIBUTION": map[string]interface{}{"Vrf_03|79": map[string]interface{}{"priority": "7", "table-id": "74"}}} + t.Run("Delete in yang hierachy involing table-xfmr, virtual-table and validate handler annotations.", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + verifyDbResultList := [13]verifyDbResultData{ + {test: "Verify ni-instance in request URL(vrf-01) is not deleted from db since URL points to child node.", db_key: "TEST_VRF|Vrf_01", db_result: expected_ni_instance_vrf_01}, + {test: "Verify default ni-instance not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_VRF|default", db_result: expected_ni_instance_default}, + {test: "Verify Vrf_02 ni-instance not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_VRF|Vrf_02", db_result: expected_ni_instance_vrf_02}, + {test: "Verify Vrf_03 ni-instance not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_VRF|Vrf_03", db_result: expected_ni_instance_vrf_03}, + {test: "Verify delete of bgp instance(vrf-01|22) assocaited with ni-instance in request URL is deleted from db.", db_key: "TEST_BGP_NETWORK_CFG|Vrf_01|22", db_result: empty_expected}, + {test: "Verify delete of bgp instance(vrf-01|33) assocaited with ni-instance in request URL is deleted from db.", db_key: "TEST_BGP_NETWORK_CFG|Vrf_01|33", db_result: empty_expected}, + {test: "Verify bgp instance(vrf-02|101) not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_BGP_NETWORK_CFG|Vrf_02|101", db_result: expected_bgp}, + {test: "Verify ospfv2-global/router instance(vrf-01) assocaited with ni-instance in request URL is deleted from db.", db_key: "TEST_OSPFV2_ROUTER|Vrf_01", db_result: empty_expected}, + {test: "Verify ospfv2-global/router instance(vrf-02) not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_OSPFV2_ROUTER|Vrf_02", + db_result: expected_ospfv2_router_vrf_02}, + {test: "Verify ospfv2-global/router instance(vrf-03) not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_OSPFV2_ROUTER|Vrf_03", + db_result: expected_ospfv2_router_vrf_03}, + {test: "Verify ospfv2-router-distribution instance(vrf-01|66) assocaited with ni-instance in request URL is deleted from db.", db_key: "TEST_OSPFV2_ROUTER_DISTRIBUTION|Vrf_01|66", + db_result: empty_expected}, + {test: "Verify ospfv2-router-distribution instance(vrf-01|98) assocaited with ni-instance in request URL is deleted from db.", db_key: "TEST_OSPFV2_ROUTER_DISTRIBUTION|Vrf_01|98", + db_result: empty_expected}, + {test: "Verify ospfv2-router-distribution instance(vrf-03|79) not assocaited with ni-instance in request URL is retained in db.", db_key: "TEST_OSPFV2_ROUTER_DISTRIBUTION|Vrf_03|79", + db_result: expected_ospfv2_router_distribution}, + } + for _, data := range verifyDbResultList { + t.Run(data.test, verifyDbResult(rclient[hostDBName], data.db_key, data.db_result, false)) + } + // Teardown + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) +} + +func Test_node_exercising_non_table_owner_annotation(t *testing.T) { + prereq := map[string]interface{}{"DEVICE_ZONE_METADATA": map[string]interface{}{"local-zonehost": map[string]interface{}{"metric": "2", "hold-interval": "97", + "hwsku": "testhwsku", "deployment-id": "834"}}} + cleanuptbl := map[string]interface{}{"DEVICE_ZONE_METADATA": map[string]interface{}{"local-zonehost": ""}} + expected_map := map[string]interface{}{"DEVICE_ZONE_METADATA": map[string]interface{}{"local-zonehost": map[string]interface{}{"metric": "32", "hwsku": "testhwsku", "deployment-id": "834"}}} + url := "/openconfig-test-xfmr:test-xfmr/test-sets/system-zone-device-data/config" + url_body_json := "{\"openconfig-test-xfmr:config\":{\"metric\":32}}" + t.Log("++++++++++++++ Test_replace_on_node_exercising_non_table_owner_annotation +++++++++++++") + // Setup + loadDB(hostDBName, db.ConfigDB, prereq) + t.Run("Replace on node exercising non table owner annotation.", processSetRequest(url, url_body_json, "PUT", false, nil)) + time.Sleep(1 * time.Second) + t.Run("Verify replace on node exercising non table owner annotation.", verifyDbResult(rclient[hostDBName], "DEVICE_ZONE_METADATA|local-zonehost", expected_map, false)) + t.Log("++++++++++++++ Test_delete_on_node_exercising_non_table_owner_annotation +++++++++++++") + //TearDown + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + + t.Log("++++++++++++++ Test_delete_on_node_exercising_non_table_owner_annotation +++++++++++++") + url = "/openconfig-test-xfmr:test-xfmr/test-sets/system-zone-device-data" + expected_map = map[string]interface{}{"DEVICE_ZONE_METADATA": map[string]interface{}{"local-zonehost": map[string]interface{}{"hwsku": "testhwsku", "deployment-id": "834"}}} + // Setup + loadDB(hostDBName, db.ConfigDB, prereq) + t.Run("Delete on node exercising non table owner annotation.", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + t.Run("Verify delete on node exercising non table owner annotation.", verifyDbResult(rclient[hostDBName], "DEVICE_ZONE_METADATA|local-zonehost", expected_map, false)) + // TearDown + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) +} + +func Test_node_exercising_subset_of_fields_in_mapped_table(t *testing.T) { + prereq_ni_instance := map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true"}}} + prereq_ospfv2_router := map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true", "write-multiplier": "2", + "initial-delay": "40", "max-delay": "100"}}} + cleanuptbl := map[string]interface{}{"TEST_VRF": map[string]interface{}{"Vrf_01": ""}, + "TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": ""}} + expected_ospfv2_router := map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true", "write-multiplier": "2", + "initial-delay": "50"}}} + url := "/openconfig-test-xfmr:test-xfmr/test-ni-instances/test-ni-instance[ni-name=vrf-01]/test-protocols/test-protocol[name=ospfv2]/ospfv2/global/timers/config" + url_body_json := "{\"openconfig-test-xfmr:config\":{\"initial-delay\":50}}" + // Setup + loadDB(hostDBName, db.ConfigDB, prereq_ni_instance) + loadDB(hostDBName, db.ConfigDB, prereq_ospfv2_router) + t.Log("++++++++++++++ Test_replace_on_node_exercising_subset_of_fields_in_mapped_table +++++++++++++") + t.Run("Replace on node exercising subset of fields in mapped table.", processSetRequest(url, url_body_json, "PUT", false, nil)) + time.Sleep(1 * time.Second) + t.Run("Verify replace on node exercising subset of fields in mapped table.", verifyDbResult(rclient[hostDBName], "TEST_OSPFV2_ROUTER|Vrf_01", expected_ospfv2_router, false)) + //TearDown + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + + t.Log("++++++++++++++ Test_delete_on_node_exercising_subset_of_fields_in_mapped_table +++++++++++++") + expected_ospfv2_router = map[string]interface{}{"TEST_OSPFV2_ROUTER": map[string]interface{}{"Vrf_01": map[string]interface{}{"enabled": "true", "write-multiplier": "2"}}} + // Setup + loadDB(hostDBName, db.ConfigDB, prereq_ni_instance) + loadDB(hostDBName, db.ConfigDB, prereq_ospfv2_router) + t.Run("Delete on node exercising subset of fields in mapped table.", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + t.Run("Verify delete on node exercising subset of fields in mapped table.", verifyDbResult(rclient[hostDBName], "TEST_OSPFV2_ROUTER|Vrf_01", expected_ospfv2_router, false)) + // TearDown + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) +} + +func test_node_exercising_db_parent_child_nonkey_leafref_relationship(t *testing.T) { + /* oc yang hierarchy parent node's db table mapping has nonkey leafref db child relationship to a + node's db table mapping in the child hierachy & siblings yang nodes having similar relationship */ + prereq := map[string]interface{}{"TEST_NTP": map[string]interface{}{"global": map[string]interface{}{"trusted-key@": "65", "auth-enabled": "true"}}, + "TEST_NTP_AUTHENTICATION_KEY": map[string]interface{}{"65": map[string]interface{}{"key-type": "MD5", "key-value": "0x635352e91dd9ddf2ed9542db848d3b31"}}, + "TEST_NTP_SERVER": map[string]interface{}{"24": map[string]interface{}{"key-id": "65", "min-poll": "3"}}} + cleanuptbl := map[string]interface{}{"TEST_NTP": map[string]interface{}{"global": ""}, "TEST_NTP_AUTHENTICATION_KEY": map[string]interface{}{"68": "", "65": ""}, + "TEST_NTP_SERVER": map[string]interface{}{"24": ""}} + empty_expected := make(map[string]interface{}) + expected_test_ntp := map[string]interface{}{"TEST_NTP": map[string]interface{}{"global": map[string]interface{}{"auth-enabled": "false"}}} + expected_test_ntp_keys := map[string]interface{}{"TEST_NTP_AUTHENTICATION_KEY": map[string]interface{}{"68": map[string]interface{}{"key-type": "MD5", + "key-value": "0x635352e91dd9ddf2ed9542db848d3b31"}}} + + // Setup - Prerequisite + loadDB(hostDBName, db.ConfigDB, prereq) + t.Log("++++++++++++++ Test_replace_on_node_exercising_db_parent_child_nonkey_leafref_relationship_error_case +++++++++++++") + url := "/openconfig-test-xfmr:test-xfmr/test-ntp/test-ntp-keys" + url_body_json := "{\"openconfig-test-xfmr:test-ntp-keys\":{\"test-ntp-key\":[{\"key-id\":67,\"config\":{\"key-id\":67,\"key-type\":\"TEST_NTP_AUTH_MD5\"," + + "\"key-value\":\"0x635352e91dd9ddf2ed9542db848d3b31\"}}]}}" + experr := tlerr.TranslibCVLFailure{Code: 1002, CVLErrorInfo: cvl.CVLErrorInfo{ErrCode: 1002, CVLErrDetails: "Config Validation Semantic Error", + Msg: "Validation failed for Delete operation, given instance is in use", ConstraintErrMsg: "Validation failed for Delete operation, given instance is in use", + TableName: "TEST_NTP_AUTHENTICATION_KEY", Keys: []string{"65"}, Field: "", Value: "", ErrAppTag: ""}} + t.Run("Test replace of child yang node having parent-child non-key leafref relationship with parent yang node(error-case).", processSetRequest(url, url_body_json, + "PUT", true, experr)) + + t.Log("++++++++++++++ Test_replace_on_node_exercising_db_parent_child_nonkey_leafref_relationship +++++++++++++") + t.Run("Test replace on node exersising db parent child nonkey leafref relationship and containing siblings with same relationship.", processSetRequest(url, url_body_json, + "PUT", false)) + url = "/openconfig-test-xfmr:test-xfmr/test-ntp" + url_body_json = "{\"openconfig-test-xfmr:test-ntp\":{\"config\":{\"enable-ntp-auth\": false}, \"test-ntp-keys\":{\"test-ntp-key\":[{\"key-id\":68,\"config\":{\"key-id\":68, \"key-type\":\"TEST_NTP_AUTH_MD5\"," + + " \"key-value\":\"0x635352e91dd9ddf2ed9542db848d3b31\"}}]}}}" + time.Sleep(1 * time.Second) + verifyDbResultArray := [4]verifyDbResultData{ + {test: "Verify replace of yang node having parent-child non-key leafref relationship with sibling yang node matches to request payload.(test-ntp-server|24)", + db_key: "TEST_NTP_SERVER|24", db_result: empty_expected}, + {test: "Verify replace of yang node having parent-child non-key leafref relationship with child yang node matches to request payload.(test-ntp|global)", + db_key: "TEST_NTP|global", db_result: expected_test_ntp}, + {test: "Verify replace of child yang node having parent-child non-key leafref relationship with parent yang node matches to request payload.(test-ntp-key|65)", + db_key: "TEST_NTP_AUTHENTICATION_KEY|65", db_result: empty_expected}, + {test: "Verify replace of child yang node having parent-child non-key leafref relationship with parent yang node matches to request payload.(test-ntp-key|68)", + db_key: "TEST_NTP_AUTHENTICATION_KEY|68", db_result: expected_test_ntp_keys}, + } + for _, data := range verifyDbResultArray { + t.Run(data.test, verifyDbResult(rclient[hostDBName], data.db_key, data.db_result, false)) + } + // Teardown + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + + t.Log("++++++++++++++ Test_delete_on_node_exercising_db_parent_child_nonkey_leafref_relationship +++++++++++++") + url = "/openconfig-test-xfmr:test-xfmr/test-ntp/test-ntp-keys" + experr = tlerr.TranslibCVLFailure{Code: 1002, CVLErrorInfo: cvl.CVLErrorInfo{ErrCode: 1002, CVLErrDetails: "Config Validation Semantic Error", + Msg: "Validation failed for Delete operation, given instance is in use", ConstraintErrMsg: "Validation failed for Delete operation, given instance is in use", + TableName: "TEST_NTP_AUTHENTICATION_KEY", Keys: []string{"65"}, Field: "", Value: "", ErrAppTag: ""}} + // Setup - Prerequisite + loadDB(hostDBName, db.ConfigDB, prereq) + url = "/openconfig-test-xfmr:test-xfmr/test-ntp/test-ntp-keys" + t.Run("Test delete of child yang node having parent-child non-key leafref relationship with parent yang node(error-case).", processDeleteRequest(url, true, experr)) + // Teardown + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) +} +func Test_leaf_node(t *testing.T) { + + /* Test delete on leaf node that has a yang default */ cleanuptbl := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"test_group_1": ""}} url := "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=test_group_1]/config/color-hold-time" prereq := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"test_group_1": map[string]interface{}{"colors@": "red,blue,green", "color-hold-time": "30"}}} - t.Log("++++++++++++++ Test_delete_on_node_with_default_value +++++++++++++") - - // Setup - Prerequisite - None + t.Log("++++++++++++++ Test_delete_on_leaf_node_with_default_value_when_mapped_instance_exists_in_db +++++++++++++") + // Setup unloadDB(hostDBName, db.ConfigDB, cleanuptbl) loadDB(hostDBName, db.ConfigDB, prereq) - - // Payload del_sensor_group_expected := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"test_group_1": map[string]interface{}{"colors@": "red,blue,green", "color-hold-time": "10"}}} + t.Run("Delete on leaf node having default value when mapped instance exists in db.", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + t.Run("Verify delete on leaf node with default value resets to default", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|test_group_1", del_sensor_group_expected, false)) + // Teardown + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + + t.Log("++++++++++++++ Test_delete_on_leaf_node_with_default_value_when_mapped_instance_does_not_exist_db +++++++++++++") //table mapping to container + cleanuptbl = map[string]interface{}{"TRANSPORT_ZONE": map[string]interface{}{"transport-host": ""}} + empty_expected := make(map[string]interface{}) + // Setup + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + url = "/openconfig-test-xfmr:test-xfmr/test-sets/transport-zone" + t.Run("Delete on leaf node having default value when mapped instance doesn't exists in db and is annotated to a container.", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + t.Run("Verify delete on leaf node with default value doesn't reset to default creating an instance in DB when mapped instance is annotated to a container.", + verifyDbResult(rclient[hostDBName], "TRANSPORT_ZONE|transport-host", empty_expected, false)) - t.Run("Delete on node having default value", processDeleteRequest(url, false)) + t.Log("++++++++++++++ Test_delete_on_leaf_node_without_default_value +++++++++++++") + cleanuptbl = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": ""}} + prereq = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "testdescription"}}} + expected_map := map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode"}}} + url = "/openconfig-test-xfmr:test-xfmr/global-sensor/description" + //Setup + loadDB(hostDBName, db.ConfigDB, prereq) + t.Run("Delete on leaf node without default value", processDeleteRequest(url, false)) time.Sleep(1 * time.Second) - t.Run("Verify delete on node with default value", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|test_group_1", del_sensor_group_expected, false)) + t.Run("Verify delete on leaf node without default value", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", expected_map, false)) + // Teardown + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + t.Log("++++++++++++++ Test_replace_targeted_on_leaf_node_updates_its_value +++++++++++++") + //Setup + loadDB(hostDBName, db.ConfigDB, prereq) + url = "/openconfig-test-xfmr:test-xfmr/global-sensor/description" + url_body_json := "{ \"openconfig-test-xfmr:description\": \"NewTestDescription\"}" + expected_map = map[string]interface{}{"TEST_SENSOR_GLOBAL": map[string]interface{}{"global_sensor": map[string]interface{}{"mode": "testmode", "description": "NewTestDescription"}}} + t.Run("Replace targeted on leaf node updates its value", processSetRequest(url, url_body_json, "PUT", false, nil)) + time.Sleep(1 * time.Second) + t.Run("Verify replace targeted on leaf node updates its value.", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GLOBAL|global_sensor", expected_map, false)) // Teardown unloadDB(hostDBName, db.ConfigDB, cleanuptbl) } @@ -349,6 +633,26 @@ func Test_leaflist_node(t *testing.T) { unloadDB(hostDBName, db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Put/Replace on Yang leaf-list Node demonstrating leaf-list contents swap ++++++++++++") + + t.Log("\n\n+++++++++++++ Performing Delete on Yang leaf-list Node - demonstrating specific leaf-list instance deletion & complete leaf-list deletion ++++++++++++++") + url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=sensor_group_01]/config/group-colors[group-colors=blue]" + pre_req_map = map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_01": map[string]interface{}{ + "colors@": "red,blue,green", "color-hold-time": "30"}}} + expected_map = map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_01": map[string]interface{}{"colors@": "red,green", "color-hold-time": "30"}}} + cleanuptbl = map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_01": ""}} + loadDB(hostDBName, db.ConfigDB, pre_req_map) + time.Sleep(1 * time.Second) + t.Run("Test specific leaf-list instance deletion.", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + t.Run("Verify specific leaf-list instance deletion.", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|sensor_group_01", expected_map, false)) + time.Sleep(1 * time.Second) + url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=sensor_group_01]/config/group-colors" + expected_map = map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_01": map[string]interface{}{"color-hold-time": "30"}}} + t.Run("Test complete leaf-list attribute deletion.", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + t.Run("Verify complete leaf-list attribute deletion.", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|sensor_group_01", expected_map, false)) + unloadDB(hostDBName, db.ConfigDB, cleanuptbl) + t.Log("\n\n+++++++++++++ Performing Delete on Yang leaf-list Node instance demonstrating specific leaf-list instance deletion ++++++++++++") } func Test_node_exercising_singleton_container_and_keyname_mapping(t *testing.T) { @@ -1177,8 +1481,8 @@ func Test_sonic_yang_default_value_handling(t *testing.T) { // Test partial key at whole list level func Test_WholeList_PartialKey(t *testing.T) { - /* Delete at whole list returning partial key / parent key. Test if only relevant instances are deleted */ - parent_prereq := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_1": map[string]interface{}{"NULL": "NULL"}}} + /* Delete And Get at a parent yang list node should rerieve/process only those child nodes which are relevant to the parent list key */ + parent_prereq := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_1": map[string]interface{}{"NULL": "NULL"}, "sensor_group_2": map[string]interface{}{"NULL": "NULL"}}} prereq := map[string]interface{}{"TEST_SENSOR_ZONE_TABLE": map[string]interface{}{"sensor_group_1|zoneA": map[string]interface{}{"description": "sensor_group_1 zoneA instance"}, "sensor_group_2|zoneA": map[string]interface{}{"description": "sensor_group_2 zoneA instance"}}} // Setup - Prerequisite @@ -1203,6 +1507,33 @@ func Test_WholeList_PartialKey(t *testing.T) { t.Run("DELETE on whole list with partial/parent key - verify child table instance with parent key gets deleted", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_ZONE_TABLE|sensor_group_1|zoneA", expected_del, false)) t.Run("DELETE on whole list with partial/parent key - verify child table instance not having parent key still exists", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_ZONE_TABLE|sensor_group_2|zoneA", expected_map, false)) + /* Verify if get like traversal is happenning for delete when a yang list node in child hierarchy has partial key of parent */ + t.Log("++++++++++++++ DELETE On Container with Child Node List With PartialKey of Parent List ++++++++++++++") + // Setup - Prerequisite + loadDB(hostDBName, db.ConfigDB, parent_prereq) + loadDB(hostDBName, db.ConfigDB, prereq) + url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=sensor_group_1]/test-sensor-zones" + t.Run("Test_Delete_On_Container_with_Child_Node_List_With_PartialKey_of_Parent_List", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + t.Run("Verify delete on container with child node list with partial key of parent - releavant child instances get deleted.", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_ZONE_TABLE|sensor_group_1|zoneA", expected_del, false)) + t.Run("Verify delete on container with child node list with partial key of parent - non-releavant child instances not deleted.", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_ZONE_TABLE|sensor_group_2|zoneA", expected_map, false)) + time.Sleep(1 * time.Second) + + t.Log("++++++++++++++ DELETE On List Instance With Child Node List With PartialKey Of Parent List ++++++++++++++") + // Setup - Prerequisite + loadDB(hostDBName, db.ConfigDB, parent_prereq) + loadDB(hostDBName, db.ConfigDB, prereq) + url = "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group[id=sensor_group_1]" + expected_parent_map := map[string]interface{}{"TEST_SENSOR_GROUP": map[string]interface{}{"sensor_group_2": map[string]interface{}{"NULL": "NULL"}}} + t.Run("Test_Delete_On_List_Instance_with_Child_Node_List_With_PartialKey_of_Parent_List", processDeleteRequest(url, false)) + time.Sleep(1 * time.Second) + t.Run("Verify delete on list instance with child node list with partial key of parent - parent instance specified in request gets deleted.", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|sensor_group_1", expected_del, false)) + t.Run("Verify delete on list instance with child node list with partial key of parent - other parent list instances stay intact.", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_GROUP|sensor_group_2", expected_parent_map, false)) + t.Run("Verify delete on list instance with child node list with partial key of parent - releavant child instances get deleted.", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_ZONE_TABLE|sensor_group_1|zoneA", expected_del, false)) + t.Run("Verify delete on list instance with child node list with partial key of parent - non-releavant child instances not deleted.s", verifyDbResult(rclient[hostDBName], "TEST_SENSOR_ZONE_TABLE|sensor_group_2|zoneA", expected_map, false)) + + t.Log("++++++++++++++ Done Test_GET_And_Delete_Involving_Node_With_PartialKey_Of_Parent +++++++++++++") + // Teardown unloadDB(hostDBName, db.ConfigDB, parent_prereq) unloadDB(hostDBName, db.ConfigDB, prereq) diff --git a/translib/transformer/vlan_openconfig_test.go b/translib/transformer/vlan_openconfig_test.go index e6b3b9666..d5c961bb6 100644 --- a/translib/transformer/vlan_openconfig_test.go +++ b/translib/transformer/vlan_openconfig_test.go @@ -178,9 +178,9 @@ func Test_openconfig_vlan_interface(t *testing.T) { t.Log("\n\n++++++++++++ CHECK STATE ATTRIBUTES ++++++++++++") cleanuptbl := map[string]interface{}{"VLAN_TABLE": map[string]interface{}{"Vlan10": ""}} - unloadDB(db.ApplDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, cleanuptbl) pre_req_map := map[string]interface{}{"VLAN_TABLE": map[string]interface{}{"Vlan10": map[string]interface{}{"admin_status": "up", "mtu": "9000", "enabled": "true"}}} - loadDB(db.ApplDB, pre_req_map) + loadDB(hostDBName, db.ApplDB, pre_req_map) t.Log("\n\n--- GET VLAN (state level) ---") url = "/openconfig-interfaces:interfaces/interface[name=Vlan10]/state" @@ -194,7 +194,7 @@ func Test_openconfig_vlan_interface(t *testing.T) { t.Run("Test GET VLAN interface state config ", processGetRequest(url, nil, expected_get_json, false)) time.Sleep(1 * time.Second) - unloadDB(db.ApplDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, cleanuptbl) } func Test_openconfig_vlan_member(t *testing.T) { @@ -739,40 +739,40 @@ func Test_openconfig_vlan_interface_ip(t *testing.T) { t.Log("\n\n++++++++++++ CHECK STATE ATTRIBUTES ++++++++++++") cleanuptbl := map[string]interface{}{"INTF_TABLE": map[string]interface{}{"Vlan10": ""}} - unloadDB(db.ApplDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, cleanuptbl) pre_req_map := map[string]interface{}{"INTF_TABLE": map[string]interface{}{"Vlan10": map[string]interface{}{"vlan": "Vlan10"}}} - loadDB(db.ApplDB, pre_req_map) + loadDB(hostDBName, db.ApplDB, pre_req_map) t.Log("\n\n--- GET VLAN (state level) ---") url = "/openconfig-interfaces:interfaces/interface[name=Vlan10]/openconfig-vlan:routed-vlan/state" expected_get_json = "{\"openconfig-vlan:state\":{\"vlan\":\"Vlan10\"}}" t.Run("Test GET VLAN interface state config ", processGetRequest(url, nil, expected_get_json, false)) time.Sleep(1 * time.Second) - unloadDB(db.ApplDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, cleanuptbl) cleanuptbl = map[string]interface{}{"INTF_TABLE": map[string]interface{}{"Vlan10:4.4.5.1/32": ""}} - unloadDB(db.ApplDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, cleanuptbl) pre_req_map = map[string]interface{}{"INTF_TABLE": map[string]interface{}{"Vlan10:4.4.5.1/32": map[string]interface{}{"ip": "4.4.5.1", "prefix-length": 32}}} - loadDB(db.ApplDB, pre_req_map) + loadDB(hostDBName, db.ApplDB, pre_req_map) t.Log("\n\n--- GET VLAN (state level) ---") url = "/openconfig-interfaces:interfaces/interface[name=Vlan10]/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/addresses/address[ip=4.4.5.1]/state" expected_get_json = "{\"openconfig-if-ip:state\":{\"ip\":\"4.4.5.1\",\"prefix-length\":32}}" t.Run("Test GET VLAN interface IPv4 state", processGetRequest(url, nil, expected_get_json, false)) time.Sleep(1 * time.Second) - unloadDB(db.ApplDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, cleanuptbl) cleanuptbl = map[string]interface{}{"INTF_TABLE": map[string]interface{}{"Vlan10:2001:4860:4860::8844/64": ""}} - unloadDB(db.ApplDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, cleanuptbl) pre_req_map = map[string]interface{}{"INTF_TABLE": map[string]interface{}{"Vlan10:2001:4860:4860::8844/64": map[string]interface{}{"ip": "2001:4860:4860::8844", "prefix-length": 64}}} - loadDB(db.ApplDB, pre_req_map) + loadDB(hostDBName, db.ApplDB, pre_req_map) t.Log("\n\n--- GET VLAN (state level) ---") url = "/openconfig-interfaces:interfaces/interface[name=Vlan10]/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv6/addresses/address[ip=2001:4860:4860::8844]/state" expected_get_json = "{\"openconfig-if-ip:state\":{\"ip\":\"2001:4860:4860::8844\",\"prefix-length\":64}}" t.Run("Test GET VLAN interface IPv6 state", processGetRequest(url, nil, expected_get_json, false)) time.Sleep(1 * time.Second) - unloadDB(db.ApplDB, cleanuptbl) + unloadDB(hostDBName, db.ApplDB, cleanuptbl) t.Log("\n\n++++++++++++ CLEAN UP VLAN INTERFACES IP CONFIG ++++++++++++") diff --git a/translib/transformer/xfmr_aps.go b/translib/transformer/xfmr_aps.go index c3c8f7618..6da450f13 100644 --- a/translib/transformer/xfmr_aps.go +++ b/translib/transformer/xfmr_aps.go @@ -486,15 +486,35 @@ var aps_name_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([] // Construct final result var result []NamespacePayload for ns, pwkList := range nsPayloadMap { - for _, pwk := range pwkList { - result = append(result, NamespacePayload{ - Namespace: ns, //asic0 - Payloads: []map[string]interface{}{pwk.payload}, //payload from payloadWithKey struct - Key: pwk.key, // key from payloadWithkey struct - Commited: false, // commited flag as a false - }) + var mergedInstances []interface{} + var firstKey string + var listKey string + + for i, pwk := range pwkList { + if i == 0 { + firstKey = pwk.key + for k := range pwk.payload { + listKey = k + break + } + } + if listVal, ok := pwk.payload[listKey]; ok { + if instances, ok := listVal.([]interface{}); ok { + mergedInstances = append(mergedInstances, instances...) + } + } + } + + mergedMap := map[string]interface{}{ + listKey: mergedInstances, } - } + result = append(result, NamespacePayload{ + Namespace: ns, + Payloads: []map[string]interface{}{mergedMap}, + Key: firstKey, + Commited: false, + }) + } return result, nil } diff --git a/translib/transformer/xfmr_atten.go b/translib/transformer/xfmr_atten.go index 82619a1c4..c83751d92 100644 --- a/translib/transformer/xfmr_atten.go +++ b/translib/transformer/xfmr_atten.go @@ -271,14 +271,35 @@ var attn_name_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([ // Construct final result var result []NamespacePayload for ns, pwkList := range nsPayloadMap { - for _, pwk := range pwkList { - result = append(result, NamespacePayload{ - Namespace: ns, //asic0 - Payloads: []map[string]interface{}{pwk.payload}, //payload from payloadWithKey struct - Key: pwk.key, // key from payloadWithkey struct - Commited: false, // commited flag as a false - }) + var mergedInstances []interface{} + var firstKey string + var listKey string + + for i, pwk := range pwkList { + if i == 0 { + firstKey = pwk.key + for k := range pwk.payload { + listKey = k + break + } + } + if listVal, ok := pwk.payload[listKey]; ok { + if instances, ok := listVal.([]interface{}); ok { + mergedInstances = append(mergedInstances, instances...) + } + } } + + mergedMap := map[string]interface{}{ + listKey: mergedInstances, + } + + result = append(result, NamespacePayload{ + Namespace: ns, + Payloads: []map[string]interface{}{mergedMap}, + Key: firstKey, + Commited: false, + }) } return result, nil diff --git a/translib/transformer/xfmr_channel_monitor.go b/translib/transformer/xfmr_channel_monitor.go index 9dfd492ca..6039cbddc 100644 --- a/translib/transformer/xfmr_channel_monitor.go +++ b/translib/transformer/xfmr_channel_monitor.go @@ -59,36 +59,28 @@ var DbToYang_ocm_name_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[ return rmap, nil } -var YangToDb_ocm_channel_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { - - log.V(3).Info("YangToDb_ocm_key_xfmr: root: ", inParams.ygRoot, - ", uri: ", inParams.uri) - pathInfo := NewPathInfo(inParams.uri) +var YangToDb_ocm_lower_frequency_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { - name := pathInfo.Var("name") - lower := pathInfo.Var("lower-frequency") - upper := pathInfo.Var("upper-frequency") - key := name + "|" + lower + "|" + upper + rmap := make(map[string]string) + rmap["NULL"] = "NULL" - return key, nil + return rmap, nil } -var DbToYang_ocm_channel_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { +var DbToYang_ocm_lower_frequency_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { rmap := make(map[string]interface{}) key := inParams.key TableKeys := strings.Split(key, "|") - if len(TableKeys) >= 3 { + if len(TableKeys) >= 2 { rmap["lower-frequency"] = TableKeys[1] - rmap["upper-frequency"] = TableKeys[2] } - log.V(3).Info("DbToYang_ocm_channel_key_xfmr : rmap ", rmap) return rmap, nil } -var YangToDb_ocm_lower_frequency_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { +var YangToDb_ocm_upper_frequency_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { rmap := make(map[string]string) rmap["NULL"] = "NULL" @@ -96,36 +88,44 @@ var YangToDb_ocm_lower_frequency_field_xfmr FieldXfmrYangToDb = func(inParams Xf return rmap, nil } -var DbToYang_ocm_lower_frequency_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { +var DbToYang_ocm_upper_frequency_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { rmap := make(map[string]interface{}) key := inParams.key TableKeys := strings.Split(key, "|") if len(TableKeys) >= 2 { - rmap["lower-frequency"] = TableKeys[1] + rmap["upper-frequency"] = TableKeys[2] } return rmap, nil } -var YangToDb_ocm_upper_frequency_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { +var YangToDb_ocm_channel_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { - rmap := make(map[string]string) - rmap["NULL"] = "NULL" + log.V(3).Info("YangToDb_ocm_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + pathInfo := NewPathInfo(inParams.uri) - return rmap, nil + name := pathInfo.Var("name") + lower := pathInfo.Var("lower-frequency") + upper := pathInfo.Var("upper-frequency") + key := name + "|" + lower + "|" + upper + + return key, nil } -var DbToYang_ocm_upper_frequency_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { +var DbToYang_ocm_channel_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { rmap := make(map[string]interface{}) key := inParams.key TableKeys := strings.Split(key, "|") - if len(TableKeys) >= 2 { + if len(TableKeys) >= 3 { + rmap["lower-frequency"] = TableKeys[1] rmap["upper-frequency"] = TableKeys[2] } + log.V(3).Info("DbToYang_ocm_channel_key_xfmr : rmap ", rmap) return rmap, nil } @@ -258,14 +258,35 @@ var ocm_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]Names // Construct final result var result []NamespacePayload for ns, pwkList := range nsPayloadMap { - for _, pwk := range pwkList { - result = append(result, NamespacePayload{ - Namespace: ns, //asic0 - Payloads: []map[string]interface{}{pwk.payload}, //payload from payloadWithKey struct - Key: pwk.key, // key from payloadWithkey struct - Commited: false, // commited flag as a false - }) + var mergedInstances []interface{} + var firstKey string + var listKey string + + for i, pwk := range pwkList { + if i == 0 { + firstKey = pwk.key + for k := range pwk.payload { + listKey = k + break + } + } + if listVal, ok := pwk.payload[listKey]; ok { + if instances, ok := listVal.([]interface{}); ok { + mergedInstances = append(mergedInstances, instances...) + } + } } + + mergedMap := map[string]interface{}{ + listKey: mergedInstances, + } + + result = append(result, NamespacePayload{ + Namespace: ns, + Payloads: []map[string]interface{}{mergedMap}, + Key: firstKey, + Commited: false, + }) } return result, nil diff --git a/translib/transformer/xfmr_optical_amplifier.go b/translib/transformer/xfmr_optical_amplifier.go index 318699b7c..cdadd0c70 100644 --- a/translib/transformer/xfmr_optical_amplifier.go +++ b/translib/transformer/xfmr_optical_amplifier.go @@ -363,27 +363,6 @@ var DbToYang_oa_counter_laser_bias_key_xfmr KeyXfmrDbToYang = func(inParams Xfmr return rmap, err } -var YangToDb_osc_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { - - log.V(3).Infof("YangToDb_osc_interface_xfmr: root: ", inParams.ygRoot, - ", uri: ", inParams.uri) - pathInfo := NewPathInfo(inParams.uri) - - osckey := pathInfo.Var("interface") - log.V(3).Infof("YangToDb_osc_interface_xfmr:osckey:", osckey) - - return osckey, nil -} - -var DbToYang_osc_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { - - rmap := make(map[string]interface{}, 1) - log.V(3).Info("DbToYang_osc_interface_xfmr: ", inParams.key) - rmap["interface"] = inParams.key - - return rmap, nil -} - var YangToDb_osc_interface_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { rmap := make(map[string]string) @@ -472,6 +451,30 @@ var DbToYang_osc_laser_bias_current_counter_key_xfmr KeyXfmrDbToYang = func(inPa return rmap, err } +var YangToDb_osc_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + if log.V(3) { + log.Info("YangToDb_osc_key_xfmr: root: ", inParams.ygRoot, + ", uri: ", inParams.uri) + } + pathInfo := NewPathInfo(inParams.uri) + osckey := pathInfo.Var("interface") + + return osckey, nil +} + +var DbToYang_osc_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + res_map := make(map[string]interface{}, 1) + var err error + + if log.V(3) { + log.Info("DbToYang_osc_key_xfmr: ", inParams.key) + } + + res_map["interface"] = inParams.key + + return res_map, err +} + func getAmplifierRootObj(s *ygot.GoStruct) *ocbinds.OpenconfigOpticalAmplifier_OpticalAmplifier { deviceObj := (*s).(*ocbinds.Device) return deviceObj.OpticalAmplifier @@ -633,14 +636,35 @@ var oa_name_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]N // Construct final result var result []NamespacePayload for ns, pwkList := range nsPayloadMap { - for _, pwk := range pwkList { - result = append(result, NamespacePayload{ - Namespace: ns, - Payloads: []map[string]interface{}{pwk.payload}, - Key: pwk.key, - Commited: false, - }) + var mergedInstances []interface{} + var firstKey string + var listKey string + + for i, pwk := range pwkList { + if i == 0 { + firstKey = pwk.key + for k := range pwk.payload { + listKey = k + break + } + } + if listVal, ok := pwk.payload[listKey]; ok { + if instances, ok := listVal.([]interface{}); ok { + mergedInstances = append(mergedInstances, instances...) + } + } } + + mergedMap := map[string]interface{}{ + listKey: mergedInstances, + } + + result = append(result, NamespacePayload{ + Namespace: ns, + Payloads: []map[string]interface{}{mergedMap}, + Key: firstKey, + Commited: false, + }) } return result, nil diff --git a/translib/transformer/xfmr_otdr.go b/translib/transformer/xfmr_otdr.go index 272e2fdfa..f900bed26 100644 --- a/translib/transformer/xfmr_otdr.go +++ b/translib/transformer/xfmr_otdr.go @@ -492,14 +492,35 @@ var otdr_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]Name // --- Construct final NamespacePayload result --- var result []NamespacePayload for ns, pwkList := range nsPayloadMap { - for _, pwk := range pwkList { - result = append(result, NamespacePayload{ - Namespace: ns, - Payloads: []map[string]interface{}{pwk.payload}, - Key: pwk.key, - Commited: false, - }) + var mergedInstances []interface{} + var firstKey string + var listKey string + + for i, pwk := range pwkList { + if i == 0 { + firstKey = pwk.key + for k := range pwk.payload { + listKey = k + break + } + } + if listVal, ok := pwk.payload[listKey]; ok { + if instances, ok := listVal.([]interface{}); ok { + mergedInstances = append(mergedInstances, instances...) + } + } } + + mergedMap := map[string]interface{}{ + listKey: mergedInstances, + } + + result = append(result, NamespacePayload{ + Namespace: ns, + Payloads: []map[string]interface{}{mergedMap}, + Key: firstKey, + Commited: false, + }) } return result, nil diff --git a/translib/transformer/xfmr_otn_openconfig.go b/translib/transformer/xfmr_otn_openconfig.go index fbe4a99b9..032d1bd4b 100644 --- a/translib/transformer/xfmr_otn_openconfig.go +++ b/translib/transformer/xfmr_otn_openconfig.go @@ -2,7 +2,6 @@ package transformer import ( "errors" - "github.com/Azure/sonic-mgmt-common/translib/db" log "github.com/golang/glog" "strings" ) @@ -12,13 +11,6 @@ func init() { XlateFuncBind("DbToYang_oc_name_key_xfmr", DbToYang_oc_name_key_xfmr) XlateFuncBind("YangToDb_oc_name_field_xfmr", YangToDb_oc_name_field_xfmr) XlateFuncBind("DbToYang_oc_name_field_xfmr", DbToYang_oc_name_field_xfmr) - XlateFuncBind("YangToDb_ocm_channel_key_xfmr", YangToDb_ocm_channel_key_xfmr) - XlateFuncBind("DbToYang_ocm_channel_key_xfmr", DbToYang_ocm_channel_key_xfmr) - XlateFuncBind("YangToDb_ocm_lower_frequency_xfmr", YangToDb_ocm_lower_frequency_xfmr) - XlateFuncBind("YangToDb_osc_key_xfmr", YangToDb_osc_key_xfmr) - XlateFuncBind("DbToYang_osc_key_xfmr", DbToYang_osc_key_xfmr) - XlateFuncBind("YangToDb_osc_interface_xfmr", YangToDb_osc_interface_xfmr) - XlateFuncBind("DbToYang_osc_interface_xfmr", DbToYang_osc_interface_xfmr) XlateFuncBind("otn_table_xfmr", otn_table_xfmr) } @@ -62,113 +54,6 @@ var DbToYang_oc_name_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (m return rmap, err } -// OCM Channel KeyXfmrs -var YangToDb_ocm_channel_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { - if log.V(3) { - log.Info("YangToDb_ocm_key_xfmr: root: ", inParams.ygRoot, - ", uri: ", inParams.uri) - } - pathInfo := NewPathInfo(inParams.uri) - name := pathInfo.Var("name") - lower := pathInfo.Var("lower-frequency") - key := name + "|" + lower - - return key, nil -} - -var DbToYang_ocm_channel_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { - rmap := make(map[string]interface{}) - tableKeys := strings.Split(inParams.key, "|") - - if len(tableKeys) >= 2 { - rmap["lower-frequency"] = tableKeys[1] - } - - tableName := "" - if strings.Contains(inParams.uri, "channels/channel") { - tableName = "OTN_OCM_CHANNEL_TABLE" - } - - upperFreq := "" - - // 1. Try Cache - if inParams.dbDataMap != nil && tableName != "" { - if tblData, ok := (*inParams.dbDataMap)[inParams.curDb][tableName]; ok { - if row, ok2 := tblData[inParams.key]; ok2 { - upperFreq = row.Field["upper-frequency"] - } - } - } - - // 2. Direct Redis Fetch (fixes the undefined: db error and the type mismatch) - if upperFreq == "" && tableName != "" { - ts := &db.TableSpec{Name: tableName} - // Using Comp for composite keys allows the driver to handle the '|' separator correctly - rowKey := db.Key{Comp: strings.Split(inParams.key, "|")} - - entry, err := inParams.dbs[inParams.curDb].GetEntry(ts, rowKey) - if err == nil { - upperFreq = entry.Field["upper-frequency"] - } - } - - if upperFreq != "" { - rmap["upper-frequency"] = upperFreq - } else { - log.Warningf("DbToYang_ocm_channel_key_xfmr: Could not resolve upper-frequency for %s", inParams.key) - } - - return rmap, nil -} - -var YangToDb_ocm_lower_frequency_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { - var err error - rmap := make(map[string]string) - - rmap["NULL"] = "NULL" - - return rmap, err -} - -// OSC Interface KeyXfmrs -var YangToDb_osc_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { - if log.V(3) { - log.Info("YangToDb_osc_key_xfmr: root: ", inParams.ygRoot, - ", uri: ", inParams.uri) - } - pathInfo := NewPathInfo(inParams.uri) - osckey := pathInfo.Var("interface") - - return osckey, nil -} - -var DbToYang_osc_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { - res_map := make(map[string]interface{}, 1) - var err error - - if log.V(3) { - log.Info("DbToYang_osc_key_xfmr: ", inParams.key) - } - - res_map["interface"] = inParams.key - - return res_map, err -} - -var YangToDb_osc_interface_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { - res_map := make(map[string]string) - var err error - return res_map, err -} - -var DbToYang_osc_interface_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { - var err error - rmap := make(map[string]interface{}) - rmap["interface"] = inParams.key - - return rmap, err -} - var otn_table_xfmr TableXfmrFunc = func(inParams XfmrParams) ([]string, error) { // Check for nil diff --git a/translib/transformer/xfmr_pfm.go b/translib/transformer/xfmr_pfm.go index c45e76d52..5d31e36c8 100644 --- a/translib/transformer/xfmr_pfm.go +++ b/translib/transformer/xfmr_pfm.go @@ -172,10 +172,10 @@ var DbToYang_pfm_transceiver_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams return rmap, nil } -var pfm_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[string]map[string]db.Value, error) { +var pfm_post_xfmr PostXfmrFunc = func(inParams XfmrParams) error { if inParams.dbDataMap == nil || *inParams.dbDataMap == nil { - return nil, fmt.Errorf("dbDataMap is nil") + return fmt.Errorf("dbDataMap is nil") } retDbDataMap := (*inParams.dbDataMap)[inParams.curDb] @@ -243,5 +243,5 @@ var pfm_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[string]map[strin } log.Infof("pfm_post_xfmr: Updated dbDataMap: %+v", retDbDataMap) - return retDbDataMap, nil + return nil } diff --git a/translib/transformer/xfmr_terminal_device.go b/translib/transformer/xfmr_terminal_device.go index ecdf90730..932951aa0 100644 --- a/translib/transformer/xfmr_terminal_device.go +++ b/translib/transformer/xfmr_terminal_device.go @@ -1096,14 +1096,35 @@ var td_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams) ([]Namesp var result []NamespacePayload for ns, pwkList := range nsPayloadMap { - for _, pwk := range pwkList { - result = append(result, NamespacePayload{ - Namespace: ns, - Payloads: []map[string]interface{}{pwk.payload}, - Key: pwk.key, - Commited: false, - }) + var mergedInstances []interface{} + var firstKey string + var listKey string + + for i, pwk := range pwkList { + if i == 0 { + firstKey = pwk.key + for k := range pwk.payload { + listKey = k + break + } + } + if listVal, ok := pwk.payload[listKey]; ok { + if instances, ok := listVal.([]interface{}); ok { + mergedInstances = append(mergedInstances, instances...) + } + } } + + mergedMap := map[string]interface{}{ + listKey: mergedInstances, + } + + result = append(result, NamespacePayload{ + Namespace: ns, + Payloads: []map[string]interface{}{mergedMap}, + Key: firstKey, + Commited: false, + }) } log.Infof("td_get_namespace_xfmr: Final result: %+v", result) @@ -1119,9 +1140,10 @@ func customOcGetNamespaceFunc(inParams XfmrParams) ([]NamespacePayload, error) { return nameSpaceList, err } -var terminal_device_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[string]map[string]db.Value, error) { +var terminal_device_post_xfmr PostXfmrFunc = func(inParams XfmrParams) error { + if inParams.dbDataMap == nil || *inParams.dbDataMap == nil { - return nil, fmt.Errorf("dbDataMap is nil") + return fmt.Errorf("dbDataMap is nil") } retDbDataMap := (*inParams.dbDataMap)[inParams.curDb] @@ -1154,7 +1176,7 @@ var terminal_device_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[stri } } - return retDbDataMap, nil + return nil } func DbToYang_ethernet_subtree_xfmr(inParams XfmrParams) error { diff --git a/translib/transformer/xfmr_testxfmr_callbacks.go b/translib/transformer/xfmr_testxfmr_callbacks.go index 2bae9c2bd..753b4f8b8 100644 --- a/translib/transformer/xfmr_testxfmr_callbacks.go +++ b/translib/transformer/xfmr_testxfmr_callbacks.go @@ -124,6 +124,31 @@ var test_pre_xfmr PreXfmrFunc = func(inParams XfmrParams) error { return err } +/* +var test_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[string]map[string]db.Value, error) { + + pathInfo := NewPathInfo(inParams.uri) + groupId := pathInfo.Var("id") + + retDbDataMap := (*inParams.dbDataMap)[inParams.curDb] + log.Info("Entering test_post_xfmr Request URI path = ", inParams.requestUri) + if inParams.oper == UPDATE { + xpath, _, _ := XfmrRemoveXPATHPredicates(inParams.requestUri) + if xpath == "/openconfig-test-xfmr:test-xfmr/test-sensor-groups/test-sensor-group/config/color-hold-time" { + holdTime := retDbDataMap["TEST_SENSOR_GROUP"][groupId].Field["color-hold-time"] + key := groupId + "|" + "sensor_type_a_post" + holdTime + subOpCreateMap := make(map[db.DBNum]map[string]map[string]db.Value) + subOpCreateMap[db.ConfigDB] = make(map[string]map[string]db.Value) + subOpCreateMap[db.ConfigDB]["TEST_SENSOR_A_TABLE"] = make(map[string]db.Value) + subOpCreateMap[db.ConfigDB]["TEST_SENSOR_A_TABLE"][key] = db.Value{Field: make(map[string]string)} + subOpCreateMap[db.ConfigDB]["TEST_SENSOR_A_TABLE"][key].Field["description_a"] = "Added instance in post xfmr" + inParams.subOpDataMap[CREATE] = &subOpCreateMap + } + } + return retDbDataMap, nil +} +*/ + var test_post_xfmr PostXfmrFunc = func(inParams XfmrParams) error { pathInfo := NewPathInfo(inParams.uri) diff --git a/translib/transformer/xfmr_tlmt.go b/translib/transformer/xfmr_tlmt.go index 6dccc3a08..08f5778c1 100644 --- a/translib/transformer/xfmr_tlmt.go +++ b/translib/transformer/xfmr_tlmt.go @@ -510,22 +510,22 @@ func deleteTables(inParams XfmrParams) error { return nil } -var telemetry_client_sync_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[string]map[string]db.Value, error) { +var telemetry_client_sync_post_xfmr PostXfmrFunc = func(inParams XfmrParams) error { + // Get current DB map retDbDataMap := (*inParams.dbDataMap)[inParams.curDb] - var sensorGroupId string - var destinationGroupId string - var subscriptionName string - log.V(3).Info(" telemetry_client_sync_post_xfmr:Entering Request URI path = ", inParams.requestUri) + log.V(3).Info(" telemetry_client_sync_post_xfmr: Entering Request URI path = ", inParams.requestUri) + + // DELETE operation if inParams.oper == DELETE { - err := deleteTables(inParams) - if err != nil { - return retDbDataMap, err + if err := deleteTables(inParams); err != nil { + return err } - return retDbDataMap, nil + return nil } + // Ensure TELEMETRY_CLIENT_TBL exists if retDbDataMap[TELEMETRY_CLIENT_TBL] == nil { retDbDataMap[TELEMETRY_CLIENT_TBL] = make(map[string]db.Value) } @@ -533,87 +533,85 @@ var telemetry_client_sync_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (ma // Populating TELEMTRY_CLIENT|Global configurations populateTelemetryGlobal(retDbDataMap) + // SENSOR-GROUPS processing if strings.Contains(inParams.requestUri, "sensor-groups") { - - for sensorGroupId, _ := range retDbDataMap[SENSOR_GROUP_TBL] { + for sensorGroupId := range retDbDataMap[SENSOR_GROUP_TBL] { log.V(3).Infof(" telemetry_client_sync_post_xfmr:sensorGroupId:%v ", sensorGroupId) + sensorPaths := retDbDataMap[SENSOR_GROUP_TBL][sensorGroupId].Field["sensor-paths"] log.V(3).Infof("telemetry_client_sync_post_xfmr:Sensor Group paths: %v", sensorPaths) // Populating TELEMETRY_CLIENT table with sensor-group data processSensorGroup(retDbDataMap, sensorGroupId, sensorPaths) - } } - if strings.Contains(inParams.requestUri, "subscriptions") { + // SUBSCRIPTIONS processing + if strings.Contains(inParams.requestUri, "subscriptions") { log.V(3).Infof(" telemetry_client_sync_post_xfmr:retDbDataMap:%v", retDbDataMap) // Fetching SENSOR_GROUP table keys sensorGroupTs := &db.TableSpec{Name: SENSOR_GROUP_TBL} - sensorGroupKeys, sensorGrpKeyserr := inParams.d.GetKeys(sensorGroupTs) - if sensorGrpKeyserr != nil { - return retDbDataMap, sensorGrpKeyserr + sensorGroupKeys, err := inParams.d.GetKeys(sensorGroupTs) + if err != nil { + return err } - for key := range sensorGroupKeys { - log.V(3).Infof(" telemetry_client_sync_post_xfmr:sensor_group_keys:%v ", sensorGroupKeys[key].Get(0)) - sensorGroupId = sensorGroupKeys[key].Get(0) - sensorGroupEntry, sensorGrpEntryerr := inParams.d.GetEntry(sensorGroupTs, sensorGroupKeys[key]) - if sensorGrpEntryerr != nil { - return retDbDataMap, sensorGrpEntryerr + for _, sgKey := range sensorGroupKeys { + sensorGroupId := sgKey.Get(0) + sensorGroupEntry, err := inParams.d.GetEntry(sensorGroupTs, sgKey) + if err != nil { + return err } - sensorPaths := sensorGroupEntry.Get("sensor-paths") - log.V(3).Infof("telemetry_client_sync_post_xfmr:Sensor Group paths: %v", sensorPaths) - if sensorGroupId != "" && sensorPaths != "" { - // Forming key for TELEMETRY_CLIENT table - tclientKey := "Subscription_" + sensorGroupId - log.V(3).Info(" telemetry_client_sync_post_xfmr:tclientKey ", tclientKey) - - for key, _ := range retDbDataMap[SENSOR_PROFILE_TBL] { - if strings.Contains(key, sensorGroupId) { - - parts := strings.Split(key, "|") - subscriptionName = parts[0] - - processSensorGroup(retDbDataMap, sensorGroupId, sensorPaths) - log.V(3).Infof(" telemetry_client_sync_post_xfmr: sensor_paths:%v", retDbDataMap[TELEMETRY_CLIENT_TBL][tclientKey].Field["paths"]) - - sample_interval := retDbDataMap[SENSOR_PROFILE_TBL][key].Field["sample-interval"] - heartbeat_interval := retDbDataMap[SENSOR_PROFILE_TBL][key].Field["heartbeat-interval"] - log.V(3).Infof(" telemetry_client_sync_post_xfmr: sample_interval:%v, heartbeat_interval:%v", sample_interval, heartbeat_interval) - - // Populating TELEMETRY_CLIENT table with subscription data - err := processSubscriptions(retDbDataMap, sensorGroupId, subscriptionName, sample_interval, heartbeat_interval) - if err != nil { - log.Errorf("Error returned from processSubscriptions :%v", err) - return retDbDataMap, err - } + sensorPaths := sensorGroupEntry.Get("sensor-paths") + tclientKey := "Subscription_" + sensorGroupId + + for profileKey := range retDbDataMap[SENSOR_PROFILE_TBL] { + if strings.Contains(profileKey, sensorGroupId) { + parts := strings.Split(profileKey, "|") + subscriptionName := parts[0] + + processSensorGroup(retDbDataMap, sensorGroupId, sensorPaths) + log.V(3).Infof("telemetry_client_sync_post_xfmr: sensor_paths: %v", retDbDataMap[TELEMETRY_CLIENT_TBL][tclientKey].Field["paths"]) + + sampleInterval := retDbDataMap[SENSOR_PROFILE_TBL][profileKey].Field["sample-interval"] + heartbeatInterval := retDbDataMap[SENSOR_PROFILE_TBL][profileKey].Field["heartbeat-interval"] + + log.V(3).Infof(" telemetry_client_sync_post_xfmr: sample_interval: %v, heartbeat_interval: %v", sampleInterval, heartbeatInterval) + + if err := processSubscriptions( + retDbDataMap, + sensorGroupId, + subscriptionName, + sampleInterval, + heartbeatInterval, + ); err != nil { + log.Errorf("Error returned from processSubscriptions: %v", err) + return err } - } } } - } + // DESTINATION-GROUPS processing if strings.Contains(inParams.requestUri, "destination-groups") { - for key, _ := range retDbDataMap[DESTINATION_TBL] { + for destKey := range retDbDataMap[DESTINATION_TBL] { + parts := strings.Split(destKey, "|") + if len(parts) < 3 { + continue + } - parts := strings.Split(key, "|") - destinationGroupId = parts[0] + destinationGroupId := parts[0] destinationGroupAddress := parts[1] destinationGroupPort := parts[2] - log.V(3).Infof(" telemetry_client_sync_post_xfmr:destinationKeys:%v,%v,%v ", destinationGroupId, destinationGroupAddress, destinationGroupPort) + log.V(3).Infof(" telemetry_client_sync_post_xfmr: destinationKeys: %v, %v, %v", destinationGroupId, destinationGroupAddress, destinationGroupPort) - // Populating TELEMETRY_CLIENT table with destinations processDestinationGroup(retDbDataMap, destinationGroupId, destinationGroupAddress, destinationGroupPort) - } - } - log.V(3).Infof(" telemetry_client_sync_post_xfmr:retDbDataMap:%v", retDbDataMap) - return retDbDataMap, nil + log.V(3).Infof(" telemetry_client_sync_post_xfmr: retDbDataMap:%v", retDbDataMap) + return nil } diff --git a/translib/transformer/xfmr_wavelength_router.go b/translib/transformer/xfmr_wavelength_router.go index 13267a238..fd3e78519 100644 --- a/translib/transformer/xfmr_wavelength_router.go +++ b/translib/transformer/xfmr_wavelength_router.go @@ -311,53 +311,75 @@ var media_channel_get_namespace_xfmr GetNamespaceFunc = func(inParams XfmrParams // Construct final result var result []NamespacePayload for ns, pwkList := range nsPayloadMap { - for _, pwk := range pwkList { - result = append(result, NamespacePayload{ - Namespace: ns, //asic0 - Payloads: []map[string]interface{}{pwk.payload}, //payload from payloadWithKey struct - Key: pwk.key, // key from payloadWithkey struct - Commited: false, // commited flag as a false - }) + var mergedInstances []interface{} + var firstKey string + var listKey string + + for i, pwk := range pwkList { + if i == 0 { + firstKey = pwk.key + for k := range pwk.payload { + listKey = k + break + } + } + if listVal, ok := pwk.payload[listKey]; ok { + if instances, ok := listVal.([]interface{}); ok { + mergedInstances = append(mergedInstances, instances...) + } + } + } + + mergedMap := map[string]interface{}{ + listKey: mergedInstances, } + + result = append(result, NamespacePayload{ + Namespace: ns, + Payloads: []map[string]interface{}{mergedMap}, + Key: firstKey, + Commited: false, + }) } return result, nil } -var media_channel_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[string]map[string]db.Value, error) { - - retDbDataMap := (*inParams.dbDataMap)[inParams.curDb] - pathInfo := NewPathInfo(inParams.uri) - index := pathInfo.Var("index") - lowerFrequency := pathInfo.Var("lower-frequency") - upperFrequency := pathInfo.Var("upper-frequency") +var media_channel_post_xfmr PostXfmrFunc = func(inParams XfmrParams) error { if inParams.dbDataMap == nil || *inParams.dbDataMap == nil { - return nil, fmt.Errorf("dbDataMap is nil") + return fmt.Errorf("dbDataMap is nil") } + + retDbDataMap := (*inParams.dbDataMap)[inParams.curDb] if retDbDataMap == nil { retDbDataMap = make(map[string]map[string]db.Value) (*inParams.dbDataMap)[inParams.curDb] = retDbDataMap } + pathInfo := NewPathInfo(inParams.uri) + index := pathInfo.Var("index") + lowerFrequency := pathInfo.Var("lower-frequency") + upperFrequency := pathInfo.Var("upper-frequency") + if inParams.oper == DELETE { if retDbDataMap["MEDIA_CHANNEL_DISTRIBUTION"] == nil { retDbDataMap["MEDIA_CHANNEL_DISTRIBUTION"] = make(map[string]db.Value) } - if lowerFrequency == "" && upperFrequency == "" && index != "" { + if lowerFrequency != "" && upperFrequency != "" && index != "" { mediaChannelTs := &db.TableSpec{Name: "MEDIA_CHANNEL_DISTRIBUTION"} mediaChannelKeys, err := inParams.d.GetKeys(mediaChannelTs) - log.Infof("media_channel_get_namespace_xfmr: ", mediaChannelKeys) + log.Infof("media_channel_get_namespace_xfmr: %v", mediaChannelKeys) if err != nil { log.Errorf("Error retrieving keys from MEDIA_CHANNEL table: %v", err) - return retDbDataMap, err + return err } - mediaChannelDistributionKeys := []string{} + mediaChannelDistributionKeys := []string{} for key := range mediaChannelKeys { - log.Infof("media_channel_get_namespace_xfmr: ", index, mediaChannelKeys[key].Get(0), mediaChannelKeys[key]) + log.Infof("media_channel_get_namespace_xfmr: %v %v %v", index, mediaChannelKeys[key].Get(0), mediaChannelKeys[key]) if index == mediaChannelKeys[key].Get(0) { mediaChannelDistribution := "" for idx, mediaKeyValue := range mediaChannelKeys[key].Comp { @@ -370,30 +392,55 @@ var media_channel_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[string mediaChannelDistributionKeys = append(mediaChannelDistributionKeys, mediaChannelDistribution) } } - log.Info("media_channel_get_namespace_xfmr: ", mediaChannelDistributionKeys) - tableTs := &db.TableSpec{Name: "MEDIA_CHANNEL_DISTRIBUTION"} - _ = tableTs - for _, DistrubutionKey := range mediaChannelDistributionKeys { + for _, distributionKey := range mediaChannelDistributionKeys { + // Mark specific key for deletion + retDbDataMap["MEDIA_CHANNEL_DISTRIBUTION"][distributionKey] = db.Value{} + } - // Mark specific key for deletion in the return DB map - retDbDataMap["MEDIA_CHANNEL_DISTRIBUTION"][DistrubutionKey] = db.Value{} + log.Infof("media_channel_post_xfmr: marked delete for index=%s in MEDIA_CHANNEL_DISTRIBUTION", index) + + } else if lowerFrequency == "" && upperFrequency == "" && index != "" { + mediaChannelTs := &db.TableSpec{Name: "MEDIA_CHANNEL_DISTRIBUTION"} + mediaChannelKeys, err := inParams.d.GetKeys(mediaChannelTs) + log.Infof("media_channel_get_namespace_xfmr: %v", mediaChannelKeys) + if err != nil { + log.Errorf("Error retrieving keys from MEDIA_CHANNEL table: %v", err) + return err + } + + mediaChannelDistributionKeys := []string{} + for key := range mediaChannelKeys { + log.Infof("media_channel_get_namespace_xfmr: %v %v %v", index, mediaChannelKeys[key].Get(0), mediaChannelKeys[key]) + if index == mediaChannelKeys[key].Get(0) { + mediaChannelDistribution := "" + for idx, mediaKeyValue := range mediaChannelKeys[key].Comp { + if idx == len(mediaChannelKeys[key].Comp)-1 { + mediaChannelDistribution += mediaKeyValue + } else { + mediaChannelDistribution += mediaKeyValue + "|" + } + } + mediaChannelDistributionKeys = append(mediaChannelDistributionKeys, mediaChannelDistribution) + } + } + + for _, distributionKey := range mediaChannelDistributionKeys { + // Mark specific key for deletion + retDbDataMap["MEDIA_CHANNEL_DISTRIBUTION"][distributionKey] = db.Value{} } log.Infof("media_channel_post_xfmr: marked delete for index=%s in MEDIA_CHANNEL_DISTRIBUTION", index) } else { log.Info("media_channel_post_xfmr:Deleting all entries in MEDIA_CHANNEL_DISTRIBUTION table") - - tableTs := &db.TableSpec{Name: "MEDIA_CHANNEL_DISTRIBUTION"} - _ = tableTs // Reset per-table map to indicate delete-all retDbDataMap["MEDIA_CHANNEL_DISTRIBUTION"] = make(map[string]db.Value) } } log.Infof("media_channel_post_xfmr:retDbDataMap:%v", retDbDataMap) - return retDbDataMap, nil + return nil } // Define a new implementation for GetNamespaceFunc diff --git a/translib/transformer/xlate.go b/translib/transformer/xlate.go index 03e5814a7..681a53365 100644 --- a/translib/transformer/xlate.go +++ b/translib/transformer/xlate.go @@ -897,7 +897,6 @@ func SortSncTableDbKeys(tableName string, dbKeyMap map[string]db.Value) []string return ordDbKey } - func IsDependentChildTable(depChildTbl string, parentTbl string, uriModuleNm string) bool { /* This function checks if the input table(depChildTbl) is a dependent child of parentTbl across sonic modules based on CVL provided dependency info. diff --git a/translib/transformer/xlate_utils.go b/translib/transformer/xlate_utils.go index 9d4e48d83..21be8e46a 100644 --- a/translib/transformer/xlate_utils.go +++ b/translib/transformer/xlate_utils.go @@ -619,9 +619,9 @@ func getDBOptions(dbNo db.DBNum, opts ...func(*db.Options)) db.Options { var opt db.Options separator := "" - if dbConfigMap != nil { + if multiDbsConfigMap != nil { dbName := db.GetDBInstName(dbNo) - dbList, ok := dbConfigMap["DATABASES"].(map[string]interface{}) + dbList, ok := multiDbsConfigMap["DATABASES"] if ok { dbSep, ok := dbList[dbName].(map[string]interface{})["separator"] if ok { diff --git a/translib/transformer/xspec.go b/translib/transformer/xspec.go index 9c35a7c67..b2ca57102 100644 --- a/translib/transformer/xspec.go +++ b/translib/transformer/xspec.go @@ -122,7 +122,9 @@ type mdlInfo struct { Ver string } -var dbConfigMap = make(map[string]interface{}) +var multiDbsConfigMap = make(map[string]map[string]interface{}) + +// var dbConfigMap = make(map[string]interface{}) var xYangSpecMap map[string]*yangXpathInfo var xDbSpecMap map[string]*dbInfo var xYangModSpecMap map[string]*moduleAnnotInfo @@ -136,8 +138,8 @@ var sonicLeafRefMap map[string][]string func init() { sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGUSR2) - dbConfigMap = db.GetDbConfigMap() - + // dbConfigMap = db.GetDbConfigMap() + multiDbsConfigMap = db.GetMdbConfigMap() go func() { for { <-sigs @@ -1163,27 +1165,27 @@ func annotDbSpecMapFill(xDbSpecMap map[string]*dbInfo, dbXpath string, entry *ya } } } - - case "cascade-delete": - fieldName := pname[len(pname)-1] - fieldXpath := tableName + "/" + fieldName - if fldXpathData, ok := xDbSpecMap[fieldXpath]; ok { - if fldXpathData.isKey { - if ext.NName() == "ENABLE" || ext.NName() == "enable" { - dbXpathData.cascadeDel = XFMR_ENABLE + + case "cascade-delete": + fieldName := pname[len(pname)-1] + fieldXpath := tableName + "/" + fieldName + if fldXpathData, ok := xDbSpecMap[fieldXpath]; ok { + if fldXpathData.isKey { + if ext.NName() == "ENABLE" || ext.NName() == "enable" { + dbXpathData.cascadeDel = XFMR_ENABLE + } else { + dbXpathData.cascadeDel = XFMR_DISABLE + } } else { - dbXpathData.cascadeDel = XFMR_DISABLE + log.Warningf("cascade-delete annotation is supported for sonic key leaf only. Ignoring the incorrect annotation") } - } else { - log.Warningf("cascade-delete annotation is supported for sonic key leaf only. Ignoring the incorrect annotation") } - } - case "key-transformer": - listName := pname[SONIC_TBL_CHILD_INDEX] - listXpath := tableName + "/" + listName - if listXpathData, ok := xDbSpecMap[listXpath]; ok { - listXpathData.xfmrKey = ext.NName() - } + case "key-transformer": + listName := pname[SONIC_TBL_CHILD_INDEX] + listXpath := tableName + "/" + listName + if listXpathData, ok := xDbSpecMap[listXpath]; ok { + listXpathData.xfmrKey = ext.NName() + } case "get-namespace": dbXpathData.namespaceFunc = ext.NName() From a79f7c7def86dac8a8f6c9d010e89b90a4c3a529 Mon Sep 17 00:00:00 2001 From: maheswari Date: Fri, 10 Jul 2026 12:20:10 +0530 Subject: [PATCH 9/9] Prior validation and configurable rollback support --- translib/Makefile | 3 +- translib/acl_app.go | 4 + translib/app_interface.go | 1 + translib/common_app.go | 82 +++- translib/db/db.go | 55 ++- translib/lldp_app.go | 4 + translib/pfm_app.go | 4 + translib/sys_app.go | 4 + translib/transformer/xfmr_pfm.go | 9 +- translib/translib.go | 656 ++++++++++++++++++++++--------- translib/yanglib_app.go | 4 + 11 files changed, 614 insertions(+), 212 deletions(-) diff --git a/translib/Makefile b/translib/Makefile index 11ddeb451..dcf7b95ae 100644 --- a/translib/Makefile +++ b/translib/Makefile @@ -9,6 +9,7 @@ TOPDIR ?= .. BUILD_DIR ?= $(TOPDIR)/build GO ?= go + export GO TRANSLIB_BLD = $(BUILD_DIR)/translib @@ -56,7 +57,7 @@ all: $(DEFAULT_TARGETS) mkdir -p $@ $(TRANSLIB_TEST_BIN): $(TRANSLIB_MAIN_SRCS) $(TRANSLIB_TEST_SRCS) $(YGOT_BINDS) - $(GO) test -mod=vendor -tags test -cover -coverpkg=../translib,../translib/tlerr -c ../translib -o $@ + $(GO) test -mod=vendor -tags test -cover -coverpkg=../translib,../translib/tlerr -c ../translib -o $@ $(TRANSL_DB_TEST_BIN) : $(TRANSL_DB_ALL_SRCS) $(GO) test -mod=vendor -cover -c ../translib/db -o $@ diff --git a/translib/acl_app.go b/translib/acl_app.go index bbce72ff5..126b8a027 100644 --- a/translib/acl_app.go +++ b/translib/acl_app.go @@ -1808,3 +1808,7 @@ func (app *AclApp) processPreparePhase(d *db.DB, ckey string) error { func (app *AclApp) rollback(d *db.DB) error { return nil } + +func (app *AclApp) processCVLValidate(d *db.DB) error { + return nil +} diff --git a/translib/app_interface.go b/translib/app_interface.go index 5c4047730..5131a9d96 100644 --- a/translib/app_interface.go +++ b/translib/app_interface.go @@ -119,6 +119,7 @@ type appInterface interface { processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (GetResponse, error) processAction(dbs [db.MaxDB]*db.DB) (ActionResponse, error) processSubscribe(req processSubRequest) (processSubResponse, error) + processCVLValidate(d *db.DB) error } // App modules will use this function to register with App interface during boot up diff --git a/translib/common_app.go b/translib/common_app.go index c7f28aeb1..13547606e 100644 --- a/translib/common_app.go +++ b/translib/common_app.go @@ -427,6 +427,45 @@ func (app *CommonApp) processDelete(d *db.DB) (SetResponse, error) { return resp, err } +func (app *CommonApp) processCVLValidate(d *db.DB) error { + if len(app.cmnAppTableMap) == 0 { + log.Infof("processCVLValidate: cmnAppTableMap empty, skipping CVL for namespace=%s", d.Opts.MDBName) + return nil + } + + //shows what tables are about to be validated + for opcode, dbNumMap := range app.cmnAppTableMap { + for _, tblMap := range dbNumMap { + for tblName, keyMap := range tblMap { + log.Infof("processCVLValidate: will validate opcode=%d table=%s keys=%v", + opcode, tblName, func() []string { + keys := make([]string, 0, len(keyMap)) + for k := range keyMap { + keys = append(keys, k) + } + return keys + }()) + } + } + } + + d.SetValidateOnly(true) + defer func() { + log.Infof("processCVLValidate: restoring ValidateOnly=false for namespace=%s", d.Opts.MDBName) + d.SetValidateOnly(false) + }() + + err := app.processCommon(d, app.cmnAppOpcode) + + if err != nil { + log.Warningf("processCVLValidate: failed for namespace %s: %v", d.Opts.MDBName, err) + return err + } + + log.Infof("processCVLValidate: passed for namespace %s", d.Opts.MDBName) + return nil +} + func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (GetResponse, error) { var err error var resp GetResponse @@ -662,6 +701,7 @@ func (app *CommonApp) processCommon(d *db.DB, opcode int) error { // Handle delete first if any available if _, ok := app.cmnAppTableMap[DELETE][db.ConfigDB]; ok { + err = app.cmnAppDelDbOpn(d, DELETE, app.cmnAppTableMap[DELETE][db.ConfigDB]) if err != nil { log.Info("Process delete fail. cmnAppDelDbOpn error:", err) @@ -1118,8 +1158,18 @@ func (app *CommonApp) processTableDeleteForReplace(d *db.DB, parentTblNm string, } } } + existingEntry, exstErr := d.GetEntry(childTblSpec, db.Key{Comp: []string{childTblKey}}) + if exstErr != nil || !existingEntry.IsPopulated() { + log.Infof("processDeleteForReplace: child key %v|%v not in Db, skipping delete", childTblNm, childTblKey) + continue + } err = d.DeleteEntry(childTblSpec, db.Key{Comp: []string{childTblKey}}) if err != nil { + if cvl.CVLRetCode(err.(tlerr.TranslibCVLFailure).Code) == cvl.CVL_SEMANTIC_KEY_NOT_EXIST { + log.Infof("Ignore delete for non-existent child entry table %v key %v in REPLACE flow: %v", childTblNm, childTblKey, err.(tlerr.TranslibCVLFailure).CVLErrorInfo.ConstraintErrMsg) + err = nil + continue + } log.Warning("DELETE for REPLACE case - d.DeleteEntry() failure") return err } @@ -1235,20 +1285,30 @@ func (app *CommonApp) handleChildDeleteForOcReplaceAndDelete(d *db.DB, sortedDel if err != nil { return err } - } - for _, tableKey := range parentKeysList { - log.V(4).Info("Delete parent entry ", cmnAppTs, db.Key{Comp: []string{tableKey}}) - err = d.DeleteEntry(cmnAppTs, db.Key{Comp: []string{tableKey}}) - if err != nil { - if cvl.CVLRetCode(err.(tlerr.TranslibCVLFailure).Code) == cvl.CVL_SEMANTIC_KEY_NOT_EXIST { - log.V(4).Infof("Ignore delete that cannot be processed for table %v key %v that does not exist. err %v", tblNm, tableKey, err.(tlerr.TranslibCVLFailure).CVLErrorInfo.ConstraintErrMsg) - err = nil - } else { - log.Warning("DELETE case - d.DeleteEntry() failure") - return err + + if !d.GetTxValidateOnly() { + for _, tableKey := range parentKeysList { + log.V(4).Info("Delete parent entry ", cmnAppTs, db.Key{Comp: []string{tableKey}}) + existingEntry, exstErr := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tableKey}}) + if exstErr != nil || !existingEntry.IsPopulated() { + log.V(4).Infof("handleChildDeleteForOcReplaceAndDelete: key %v|%v not found in DB, skipping delete", tblNm, tableKey) + continue + } + + err = d.DeleteEntry(cmnAppTs, db.Key{Comp: []string{tableKey}}) + if err != nil { + if cvl.CVLRetCode(err.(tlerr.TranslibCVLFailure).Code) == cvl.CVL_SEMANTIC_KEY_NOT_EXIST { + log.V(4).Infof("Ignore delete that cannot be processed for table %v key %v that does not exist. err %v", tblNm, tableKey, err.(tlerr.TranslibCVLFailure).CVLErrorInfo.ConstraintErrMsg) + err = nil + } else { + log.Warning("DELETE case - d.DeleteEntry() failure") + return err + } + } } } } + } } return err diff --git a/translib/db/db.go b/translib/db/db.go index 517b9d57a..187cd5896 100644 --- a/translib/db/db.go +++ b/translib/db/db.go @@ -391,12 +391,46 @@ type DB struct { onCReg dbOnChangeReg // holds OnChange enabled table names // PubSubRpc - rPubSub *redis.PubSub - + rPubSub *redis.PubSub + txValidateOnly bool + txSkipCVL bool // Non-Session Config DB Lock acquired configDBLocked bool } +func (d *DB) SetValidateOnly(v bool) { + glog.Infof("SetValidateOnly: namespace=%s,txValidateOnly=%v", d.Opts.MDBName, v) + d.txValidateOnly = v + if !v { + glog.Infof("SetValidateOnly: clearing txTsEntryMap and txCmds for clean phase 2") + d.txCmds = d.txCmds[:0] + d.cvlEditConfigData = d.cvlEditConfigData[:0] + d.txTsEntryMap = make(map[string]map[string]Value) + d.txTsEntryHGetAll = make(map[string]map[string]Value) + + //Reset CVL Session to flush stale libyang tree + if d.cv != nil { + if ret := cvl.ValidationSessClose(d.cv); ret != cvl.CVL_SUCCESS { + glog.Errorf("SetValidateOnly: error closing CVL session: %v", cvl.GetErrorString(ret)) + } + d.cv = nil + } + var e error + if d.cv, e = d.NewValidationSession(); e != nil { + glog.Errorf("SetValidateOnly: error reopening CVL Session: %v", e) + } + } + +} + +func (d *DB) SetSkipCVL(v bool) { + glog.Infof("SetSkipCVL: namespace=%s, txSkipCVL=%v", d.Opts.MDBName, v) + d.txSkipCVL = v +} +func (d *DB) GetTxValidateOnly() bool { + return d.txValidateOnly +} + func (d DB) String() string { return fmt.Sprintf("{ client: %v, Opts: %v, txState: %v, tsCmds: %v }", d.client, d.Opts, d.txState, d.txCmds) @@ -1077,6 +1111,10 @@ func (d *DB) doCVL(ts *TableSpec, cvlOps []cmn.CVLOperation, key Key, vals []Val goto doCVLExit } + if d.txSkipCVL { + glog.Info("doCVL: txSkipCVL=true, skipping CVL for Phase 2") + goto doCVLExit + } if len(cvlOps) != len(vals) { glog.Error("doCVL: Incorrect arguments len(cvlOps) != len(vals)") e = errors.New("CVL Incorrect args") @@ -1119,6 +1157,9 @@ func (d *DB) doCVL(ts *TableSpec, cvlOps []cmn.CVLOperation, key Key, vals []Val glog.Info("doCVL: calling ValidateEditConfig: ", d.cvlEditConfigData) } + glog.Infof("doCVL: CALLING ValidateEditConfig — table=%s key=%v numEditConfigData=%d txValidateOnly=%v", + ts.Name, key, len(d.cvlEditConfigData), d.txValidateOnly) + cei, cvlRetCode = d.cv.ValidateEditConfig(d.cvlEditConfigData) if cvl.CVL_SUCCESS != cvlRetCode { @@ -1305,6 +1346,10 @@ func (d *DB) doWrite(ts *TableSpec, op _txOp, k Key, val interface{}) error { if e != nil { goto doWriteExit } + if d.txValidateOnly { + glog.Info("doWrite: txValidateOnly=true, skipping Redis write for key: ", key) + goto doWriteExit + } d.txCmds = append(d.txCmds, _txCmd{ ts: ts, @@ -1936,7 +1981,8 @@ CommitTxExit: d.cvlEditConfigData = d.cvlEditConfigData[:0] d.txTsEntryMap = make(map[string]map[string]Value) d.txTsEntryHGetAll = make(map[string]map[string]Value) - + d.txValidateOnly = false + d.txSkipCVL = false //Close CVL session if d.cv != nil { if ret := cvl.ValidationSessClose(d.cv); ret != cvl.CVL_SUCCESS { @@ -1998,7 +2044,8 @@ AbortTxExit: d.cvlEditConfigData = d.cvlEditConfigData[:0] d.txTsEntryMap = make(map[string]map[string]Value) d.txTsEntryHGetAll = make(map[string]map[string]Value) - + d.txValidateOnly = false + d.txSkipCVL = false //Close CVL session if d.cv != nil { if ret := cvl.ValidationSessClose(d.cv); ret != cvl.CVL_SUCCESS { diff --git a/translib/lldp_app.go b/translib/lldp_app.go index 5a36bfeb1..0436d532d 100644 --- a/translib/lldp_app.go +++ b/translib/lldp_app.go @@ -457,3 +457,7 @@ func (app *lldpApp) processPreparePhase(d *db.DB, ckey string) error { func (app *lldpApp) rollback(d *db.DB) error { return nil } + +func (app *lldpApp) processCVLValidate(d *db.DB) error { + return nil +} diff --git a/translib/pfm_app.go b/translib/pfm_app.go index 2fa5dd506..6fb704790 100644 --- a/translib/pfm_app.go +++ b/translib/pfm_app.go @@ -577,3 +577,7 @@ func (app *PlatformApp) processPreparePhase(d *db.DB, ckey string) error { func (app *PlatformApp) rollback(d *db.DB) error { return nil } + +func (app *PlatformApp) processCVLValidate(d *db.DB) error { + return nil +} diff --git a/translib/sys_app.go b/translib/sys_app.go index a445a4329..4c3ed67bb 100644 --- a/translib/sys_app.go +++ b/translib/sys_app.go @@ -374,3 +374,7 @@ func (app *SysApp) processPreparePhase(d *db.DB, ckey string) error { func (app *SysApp) rollback(d *db.DB) error { return nil } + +func (app *SysApp) processCVLValidate(d *db.DB) error { + return nil +} diff --git a/translib/transformer/xfmr_pfm.go b/translib/transformer/xfmr_pfm.go index 5d31e36c8..77a23e9a9 100644 --- a/translib/transformer/xfmr_pfm.go +++ b/translib/transformer/xfmr_pfm.go @@ -190,7 +190,7 @@ var pfm_post_xfmr PostXfmrFunc = func(inParams XfmrParams) error { if inParams.oper == CREATE { if strings.Contains(inParams.requestUri, "components") { for _, table := range []string{OCH_TBL, TRANSCEIVER_TBL} { - if retDbDataMap[table] == nil { + if retDbDataMap[table] == nil || len(retDbDataMap[table]) == 0 { continue } @@ -240,8 +240,13 @@ var pfm_post_xfmr PostXfmrFunc = func(inParams XfmrParams) error { retDbDataMap[tableTsName] = make(map[string]db.Value) // clears table } } + //DELETE ALL CASE + if tableTsName == "" && keyName == "" { + log.Infof("pfm_post_xfmr: DELETE ALL detected, wiping OC_COMPONENT and TRANSCEIVER tables") + retDbDataMap[OC_COMPONENT_TBL] = make(map[string]db.Value) + retDbDataMap[TRANSCEIVER_TBL] = make(map[string]db.Value) + } } - log.Infof("pfm_post_xfmr: Updated dbDataMap: %+v", retDbDataMap) return nil } diff --git a/translib/translib.go b/translib/translib.go index 592f13a43..e718a378d 100644 --- a/translib/translib.go +++ b/translib/translib.go @@ -49,6 +49,7 @@ import ( // Write lock for all write operations to be synchronized var writeMutex = &sync.Mutex{} +var ENABLE_TRANSLIB_ROLLBACK = "false" type ErrSource int @@ -173,6 +174,7 @@ func ResponseError(optype string, payload []byte, errorType ErrSource) interface } func commitTransactions(redisMdbInstances map[string]*db.DB, nsMaps []NamespacePayload) error { + for ns, redisDbInstance := range redisMdbInstances { if err := redisDbInstance.CommitTx(); err != nil { @@ -251,6 +253,13 @@ func processPostPhase() error { return nil } +type nsWriteContext struct { + nameSpace string + nsPayload NamespacePayload + payloadBytes []byte + d *db.DB +} + // Create - Creates entries in the redis DB pertaining to the path and payload func Create(req SetRequest) (SetResponse, error) { var keys []db.WatchKeys @@ -301,28 +310,32 @@ func Create(req SetRequest) (SetResponse, error) { writeMutex.Lock() defer writeMutex.Unlock() + log.Infof("Create: starting PHASE 1 - CVL validation for all namespaces, total namespaces=%d", len(namespacePayloads)) + + var writeContexts []nsWriteContext + for _, nsPayload := range namespacePayloads { nameSpace := nsPayload.Namespace payloads := nsPayload.Payloads if len(payloads) == 0 { log.Infof("Payloads for namespace '%s' are empty, using top-level payload", nameSpace) - var topLevelPayload map[string]interface{} err := json.Unmarshal(payload, &topLevelPayload) if err != nil { resp.ErrSrc = AppErr - log.Errorf("Failed to unmarshal top-level payload: %v", err) + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } return resp, err } - payloads = append(payloads, topLevelPayload) } - + log.Infof("Create: PHASE1 - CVL Validation for namespace=%s", nameSpace) log.Infof("Namespace: %s", nameSpace) - for _, payload := range payloads { - - payloadBytes, err := json.Marshal(payload) + for _, pl := range payloads { + payloadBytes, err := json.Marshal(pl) if err != nil { resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) @@ -343,7 +356,6 @@ func Create(req SetRequest) (SetResponse, error) { } d, err = initializeMDBInstance(nameSpace, redisMdbInstances) - if err != nil { resp.ErrSrc = ProtoErr abortErr := abortTransactions(redisMdbInstances) @@ -355,7 +367,6 @@ func Create(req SetRequest) (SetResponse, error) { defer d.DeleteDB() keys, err = (*app).translateCreate(d) - if err != nil { resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) @@ -366,7 +377,6 @@ func Create(req SetRequest) (SetResponse, error) { } err = d.AppendWatchTx(keys, appInfo.tablesToWatch) - if err != nil { resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) @@ -376,9 +386,10 @@ func Create(req SetRequest) (SetResponse, error) { return resp, err } - err = (*app).processPreparePhase(d, nsPayload.Key) - + // CVL only + err = (*app).processCVLValidate(d) if err != nil { + log.Errorf("Create: PHASE 1 - CVL failed for namespace=%s, aborting all , error=%v", nameSpace, err) resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) if abortErr != nil { @@ -386,11 +397,43 @@ func Create(req SetRequest) (SetResponse, error) { } return resp, err } + log.Infof("Create: PHASE 1- CVL passed for namespace=%s, queuing for Phase2", nameSpace) - resp, err = (*app).processCreate(d) + writeContexts = append(writeContexts, nsWriteContext{ + nameSpace: nameSpace, nsPayload: nsPayload, + payloadBytes: payloadBytes, d: d, + }) + } + } + log.Infof("Create: PHASE 1 complete -CVL Passed for all namespaces, total=%d, proceeding to PHASE2", len(writeContexts)) + log.Infof("Create: Starting PHASE 2 - actual write for all namespaces") + for _, ctx := range writeContexts { + log.Infof("Create: PHASE2 - writing namespace=%s", ctx.nameSpace) + err = appInitialize(app, appInfo, path, &ctx.payloadBytes, nil, CREATE) + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + // Re-run translate to repopulate cmnAppTableMap for processCreate + _, err = (*app).translateCreate(ctx.d) + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + + if ENABLE_TRANSLIB_ROLLBACK == "true" { + err = (*app).processPreparePhase(ctx.d, ctx.nsPayload.Key) if err != nil { - d.AbortTx() resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) if abortErr != nil { @@ -398,18 +441,26 @@ func Create(req SetRequest) (SetResponse, error) { } return resp, err } - - // Check if the entry with the same nameSpace already exists in the map - if _, exists := redisMdbInstances[nameSpace]; !exists { - redisMdbInstances[nameSpace] = d + } + resp, err = (*app).processCreate(ctx.d) + if err != nil { + ctx.d.AbortTx() + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr } + return resp, err + } + if _, exists := redisMdbInstances[ctx.nameSpace]; !exists { + redisMdbInstances[ctx.nameSpace] = ctx.d } } - + log.Infof("Create: PHASE 2 - all namespaces written successfully, proceeding to commit") cerr := commitTransactions(redisMdbInstances, namespacePayloads) - if cerr != nil { + if cerr != nil && ENABLE_TRANSLIB_ROLLBACK == "true" { for ns, redisDbInstance := range redisMdbInstances { for _, payload := range namespacePayloads { if payload.Namespace == ns && payload.Commited { @@ -423,11 +474,12 @@ func Create(req SetRequest) (SetResponse, error) { } } } - err = processPostPhase() - if err != nil { - log.Infof("Cleanup of backup entries operation failed!") + if ENABLE_TRANSLIB_ROLLBACK == "true" { + err = processPostPhase() + if err != nil { + log.Infof("Cleanup of backup entries operation failed!") + } } - return resp, cerr } @@ -438,9 +490,7 @@ func Update(req SetRequest) (SetResponse, error) { var resp SetResponse var d *db.DB - // Define a map to hold multiple Redis DB instances with mdbName as key var redisMdbInstances map[string]*db.DB - if redisMdbInstances == nil { redisMdbInstances = make(map[string]*db.DB) } @@ -458,20 +508,18 @@ func Update(req SetRequest) (SetResponse, error) { log.Info("Update request received with payload =", string(payload)) app, appInfo, err := getAppModule(path, req.ClientVersion) - if err != nil { resp.ErrSrc = ProtoErr return resp, err } err = appInitialize(app, appInfo, path, &payload, nil, UPDATE) - if err != nil { resp.ErrSrc = AppErr return resp, err } - namespacePayloads, err := (*app).getNamespace(path) + namespacePayloads, err := (*app).getNamespace(path) if err != nil { log.Infof("Error from getNamespace %v", err) resp.ErrSrc = AppErr @@ -481,28 +529,33 @@ func Update(req SetRequest) (SetResponse, error) { writeMutex.Lock() defer writeMutex.Unlock() + var writeContexts []nsWriteContext + + log.Infof("Update: Starting PHASE 1 - CVL validation for all namespaces, total=%d", len(namespacePayloads)) + for _, nsPayload := range namespacePayloads { nameSpace := nsPayload.Namespace payloads := nsPayload.Payloads if len(payloads) == 0 { log.Infof("Payloads for namespace '%s' are empty, using top-level payload", nameSpace) - var topLevelPayload map[string]interface{} err := json.Unmarshal(payload, &topLevelPayload) if err != nil { resp.ErrSrc = AppErr log.Errorf("Failed to unmarshal top-level payload: %v", err) + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } return resp, err } - payloads = append(payloads, topLevelPayload) } - log.Infof("Namespace: %s", nameSpace) - - for _, payload := range payloads { + log.Infof("Update: PHASE 1 - CVL validation for namespace=%s", nameSpace) - payloadBytes, err := json.Marshal(payload) + for _, pl := range payloads { + payloadBytes, err := json.Marshal(pl) if err != nil { resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) @@ -513,7 +566,6 @@ func Update(req SetRequest) (SetResponse, error) { } err = appInitialize(app, appInfo, path, &payloadBytes, nil, UPDATE) - if err != nil { resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) @@ -524,7 +576,6 @@ func Update(req SetRequest) (SetResponse, error) { } d, err = initializeMDBInstance(nameSpace, redisMdbInstances) - if err != nil { resp.ErrSrc = ProtoErr abortErr := abortTransactions(redisMdbInstances) @@ -536,7 +587,6 @@ func Update(req SetRequest) (SetResponse, error) { defer d.DeleteDB() keys, err = (*app).translateUpdate(d) - if err != nil { resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) @@ -547,7 +597,6 @@ func Update(req SetRequest) (SetResponse, error) { } err = d.AppendWatchTx(keys, appInfo.tablesToWatch) - if err != nil { resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) @@ -557,9 +606,9 @@ func Update(req SetRequest) (SetResponse, error) { return resp, err } - err = (*app).processPreparePhase(d, nsPayload.Key) - + err = (*app).processCVLValidate(d) if err != nil { + log.Errorf("Update: PHASE 1 - CVL FAILED for namespace=%s, aborting all, error=%v", nameSpace, err) resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) if abortErr != nil { @@ -567,11 +616,51 @@ func Update(req SetRequest) (SetResponse, error) { } return resp, err } + log.Infof("Update: PHASE 1 - CVL passed for namespace=%s, queuing for Phase 2", nameSpace) + + writeContexts = append(writeContexts, nsWriteContext{ + nameSpace: nameSpace, + nsPayload: nsPayload, + payloadBytes: payloadBytes, + d: d, + }) + } + } + + log.Infof("Update: PHASE 1 complete - CVL passed for all namespaces, total=%d, proceeding to PHASE 2", len(writeContexts)) + + for _, ctx := range writeContexts { + ctx.d.SetSkipCVL(true) + } + + log.Infof("Update: Starting PHASE 2 - actual Redis writes") + + for _, ctx := range writeContexts { + log.Infof("Update: PHASE 2 - writing namespace=%s", ctx.nameSpace) + + err = appInitialize(app, appInfo, path, &ctx.payloadBytes, nil, UPDATE) + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } - resp, err = (*app).processUpdate(d) + _, err = (*app).translateUpdate(ctx.d) + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + if ENABLE_TRANSLIB_ROLLBACK == "true" { + err = (*app).processPreparePhase(ctx.d, ctx.nsPayload.Key) if err != nil { - d.AbortTx() resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) if abortErr != nil { @@ -579,22 +668,30 @@ func Update(req SetRequest) (SetResponse, error) { } return resp, err } - - // Check if the entry with the same nameSpace already exists in the map - if _, exists := redisMdbInstances[nameSpace]; !exists { - redisMdbInstances[nameSpace] = d + } + resp, err = (*app).processUpdate(ctx.d) + if err != nil { + ctx.d.AbortTx() + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr } + return resp, err + } + if _, exists := redisMdbInstances[ctx.nameSpace]; !exists { + redisMdbInstances[ctx.nameSpace] = ctx.d } } - cerr := commitTransactions(redisMdbInstances, namespacePayloads) + log.Infof("Update: PHASE 2 complete - all namespaces written successfully, proceeding to commit") - if cerr != nil { + cerr := commitTransactions(redisMdbInstances, namespacePayloads) + if cerr != nil && ENABLE_TRANSLIB_ROLLBACK == "true" { for ns, redisDbInstance := range redisMdbInstances { for _, payload := range namespacePayloads { if payload.Namespace == ns && payload.Commited { - // Pass the payload.Key for rollback log.Infof("Rollback key:%v,Namespace: %s", payload.Namespace, payload.Key) err = (*app).rollback(redisDbInstance) if err != nil { @@ -604,13 +701,13 @@ func Update(req SetRequest) (SetResponse, error) { } } } - err = processPostPhase() - if err != nil { - log.Infof("Cleanup of backup entries operation failed!") + if ENABLE_TRANSLIB_ROLLBACK == "true" { + err = processPostPhase() + if err != nil { + log.Infof("Cleanup of backup entries operation failed!") + } } - return resp, cerr - } // Replace - Replaces entries in the redis DB pertaining to the path and payload @@ -620,9 +717,7 @@ func Replace(req SetRequest) (SetResponse, error) { var resp SetResponse var d *db.DB - // Define a map to hold multiple Redis DB instances with mdbName as key var redisMdbInstances map[string]*db.DB - if redisMdbInstances == nil { redisMdbInstances = make(map[string]*db.DB) } @@ -637,7 +732,6 @@ func Replace(req SetRequest) (SetResponse, error) { } app, appInfo, err := getAppModule(path, req.ClientVersion) - if err != nil { resp.ErrSrc = ProtoErr return resp, err @@ -647,14 +741,12 @@ func Replace(req SetRequest) (SetResponse, error) { log.Info("Replace request received with payload =", string(payload)) err = appInitialize(app, appInfo, path, &payload, nil, REPLACE) - if err != nil { resp.ErrSrc = AppErr return resp, err } namespacePayloads, err := (*app).getNamespace(path) - if err != nil { log.Infof("Error from getNamespace %v", err) resp.ErrSrc = AppErr @@ -664,28 +756,33 @@ func Replace(req SetRequest) (SetResponse, error) { writeMutex.Lock() defer writeMutex.Unlock() + var writeContexts []nsWriteContext + + log.Infof("Replace: Starting PHASE 1 - CVL validation for all namespaces, total=%d", len(namespacePayloads)) + for _, nsPayload := range namespacePayloads { nameSpace := nsPayload.Namespace payloads := nsPayload.Payloads if len(payloads) == 0 { log.Infof("Payloads for namespace '%s' are empty, using top-level payload", nameSpace) - var topLevelPayload map[string]interface{} err := json.Unmarshal(payload, &topLevelPayload) if err != nil { resp.ErrSrc = AppErr log.Errorf("Failed to unmarshal top-level payload: %v", err) + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } return resp, err } - payloads = append(payloads, topLevelPayload) } - log.Infof("Namespace: %s", nameSpace) - - for _, payload := range payloads { + log.Infof("Replace: PHASE 1 - CVL validation for namespace=%s", nameSpace) - payloadBytes, err := json.Marshal(payload) + for _, pl := range payloads { + payloadBytes, err := json.Marshal(pl) if err != nil { resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) @@ -696,7 +793,6 @@ func Replace(req SetRequest) (SetResponse, error) { } err = appInitialize(app, appInfo, path, &payloadBytes, nil, REPLACE) - if err != nil { resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) @@ -707,7 +803,6 @@ func Replace(req SetRequest) (SetResponse, error) { } d, err = initializeMDBInstance(nameSpace, redisMdbInstances) - if err != nil { resp.ErrSrc = ProtoErr abortErr := abortTransactions(redisMdbInstances) @@ -719,7 +814,6 @@ func Replace(req SetRequest) (SetResponse, error) { defer d.DeleteDB() keys, err = (*app).translateReplace(d) - if err != nil { resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) @@ -730,7 +824,6 @@ func Replace(req SetRequest) (SetResponse, error) { } err = d.AppendWatchTx(keys, appInfo.tablesToWatch) - if err != nil { resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) @@ -740,9 +833,9 @@ func Replace(req SetRequest) (SetResponse, error) { return resp, err } - err = (*app).processPreparePhase(d, nsPayload.Key) - + err = (*app).processCVLValidate(d) if err != nil { + log.Errorf("Replace: PHASE 1 - CVL FAILED for namespace=%s, aborting all, error=%v", nameSpace, err) resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) if abortErr != nil { @@ -750,11 +843,50 @@ func Replace(req SetRequest) (SetResponse, error) { } return resp, err } + log.Infof("Replace: PHASE 1 - CVL passed for namespace=%s, queuing for Phase 2", nameSpace) + + writeContexts = append(writeContexts, nsWriteContext{ + nameSpace: nameSpace, + nsPayload: nsPayload, + payloadBytes: payloadBytes, + d: d, + }) + } + } + + log.Infof("Replace: PHASE 1 complete - CVL passed for all namespaces, total=%d, proceeding to PHASE 2", len(writeContexts)) + for _, ctx := range writeContexts { + ctx.d.SetSkipCVL(true) + } + + log.Infof("Replace: Starting PHASE 2 - actual Redis writes") + + for _, ctx := range writeContexts { + log.Infof("Replace: PHASE 2 - writing namespace=%s", ctx.nameSpace) + + err = appInitialize(app, appInfo, path, &ctx.payloadBytes, nil, REPLACE) + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } - resp, err = (*app).processReplace(d) + _, err = (*app).translateReplace(ctx.d) + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + if ENABLE_TRANSLIB_ROLLBACK == "true" { + err = (*app).processPreparePhase(ctx.d, ctx.nsPayload.Key) if err != nil { - d.AbortTx() resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) if abortErr != nil { @@ -762,22 +894,31 @@ func Replace(req SetRequest) (SetResponse, error) { } return resp, err } + } - // Check if the entry with the same nameSpace already exists in the map - if _, exists := redisMdbInstances[nameSpace]; !exists { - redisMdbInstances[nameSpace] = d + resp, err = (*app).processReplace(ctx.d) + if err != nil { + ctx.d.AbortTx() + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr } + return resp, err + } + if _, exists := redisMdbInstances[ctx.nameSpace]; !exists { + redisMdbInstances[ctx.nameSpace] = ctx.d } } - cerr := commitTransactions(redisMdbInstances, namespacePayloads) + log.Infof("Replace: PHASE 2 complete - all namespaces written successfully, proceeding to commit") - if cerr != nil { + cerr := commitTransactions(redisMdbInstances, namespacePayloads) + if cerr != nil && ENABLE_TRANSLIB_ROLLBACK == "true" { for ns, redisDbInstance := range redisMdbInstances { for _, payload := range namespacePayloads { if payload.Namespace == ns && payload.Commited { - // Pass the payload.Key for rollback log.Infof("Rollback key:%v,Namespace: %s", payload.Namespace, payload.Key) err = (*app).rollback(redisDbInstance) if err != nil { @@ -787,11 +928,12 @@ func Replace(req SetRequest) (SetResponse, error) { } } } - err = processPostPhase() - if err != nil { - log.Infof("Cleanup of backup entries operation failed!") + if ENABLE_TRANSLIB_ROLLBACK == "true" { + err = processPostPhase() + if err != nil { + log.Infof("Cleanup of backup entries operation failed!") + } } - return resp, cerr } @@ -802,9 +944,7 @@ func Delete(req SetRequest) (SetResponse, error) { var keys []db.WatchKeys var d *db.DB - // Define a map to hold multiple Redis DB instances with mdbName as key var redisMdbInstances map[string]*db.DB - if redisMdbInstances == nil { redisMdbInstances = make(map[string]*db.DB) } @@ -820,23 +960,19 @@ func Delete(req SetRequest) (SetResponse, error) { log.Info("Delete request received with path =", path) app, appInfo, err := getAppModule(path, req.ClientVersion) - if err != nil { resp.ErrSrc = ProtoErr return resp, err } opts := appOptions{deleteEmptyEntry: req.DeleteEmptyEntry} - err = appInitialize(app, appInfo, path, nil, &opts, DELETE) - if err != nil { resp.ErrSrc = AppErr return resp, err } namespacePayloads, err := (*app).getNamespace(path) - if err != nil { log.Infof("Error from getNamespace %v", err) resp.ErrSrc = AppErr @@ -844,7 +980,6 @@ func Delete(req SetRequest) (SetResponse, error) { } // Fetching the DBNames to iterate if getNamespace returned * - // if keys is not present in xpath of GetRequest. if len(namespacePayloads) == 1 && namespacePayloads[0].Namespace == "*" { allNamespaces := db.GetMultiDbNames() key := namespacePayloads[0].Key @@ -852,34 +987,31 @@ func Delete(req SetRequest) (SetResponse, error) { for _, ns := range allNamespaces { namespacePayloads = append(namespacePayloads, NamespacePayload{ Namespace: ns, - Payloads: nil, // no payload needed for delete - Key: key, // preserve original key * + Payloads: nil, + Key: key, }) } - } writeMutex.Lock() defer writeMutex.Unlock() - for _, nsPayload := range namespacePayloads { + var writeContexts []nsWriteContext - opts := appOptions{deleteEmptyEntry: req.DeleteEmptyEntry} + log.Infof("Delete: Starting PHASE 1 - CVL validation for all namespaces, total=%d", len(namespacePayloads)) + for _, nsPayload := range namespacePayloads { + opts := appOptions{deleteEmptyEntry: req.DeleteEmptyEntry} err = appInitialize(app, appInfo, path, nil, &opts, DELETE) - if err != nil { resp.ErrSrc = AppErr return resp, err } nameSpace := nsPayload.Namespace + log.Infof("Delete: PHASE 1 - CVL validation for namespace=%s", nameSpace) - log.Infof("Namespace: %s", nameSpace) - - log.Info("Delete operation going to be performed on ", nameSpace) d, err = initializeMDBInstance(nameSpace, redisMdbInstances) - if err != nil { resp.ErrSrc = ProtoErr abortErr := abortTransactions(redisMdbInstances) @@ -891,7 +1023,6 @@ func Delete(req SetRequest) (SetResponse, error) { defer d.DeleteDB() keys, err = (*app).translateDelete(d) - if err != nil { resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) @@ -902,8 +1033,20 @@ func Delete(req SetRequest) (SetResponse, error) { } err = d.AppendWatchTx(keys, appInfo.tablesToWatch) + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + d.Opts.DisableCVLCheck = true + err = (*app).processCVLValidate(d) + d.Opts.DisableCVLCheck = false if err != nil { + log.Errorf("Delete: PHASE 1 - CVL FAILED for namespace=%s, aborting all, error=%v", nameSpace, err) resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) if abortErr != nil { @@ -911,11 +1054,34 @@ func Delete(req SetRequest) (SetResponse, error) { } return resp, err } + log.Infof("Delete: PHASE 1 - CVL passed for namespace=%s, queuing for Phase 2", nameSpace) - log.Infof("Calling processPreparePhase") - err = (*app).processPreparePhase(d, nsPayload.Key) - log.Infof("Return processPreparePhase") + writeContexts = append(writeContexts, nsWriteContext{ + nameSpace: nameSpace, + nsPayload: nsPayload, + d: d, + }) + } + log.Infof("Delete: PHASE 1 complete - CVL passed for all namespaces, total=%d, proceeding to PHASE 2", len(writeContexts)) + + for _, ctx := range writeContexts { + ctx.d.SetSkipCVL(true) + } + + log.Infof("Delete: Starting PHASE 2 - actual Redis writes") + + for _, ctx := range writeContexts { + log.Infof("Delete: PHASE 2 - writing namespace=%s", ctx.nameSpace) + + opts := appOptions{deleteEmptyEntry: req.DeleteEmptyEntry} + err = appInitialize(app, appInfo, path, nil, &opts, DELETE) + if err != nil { + resp.ErrSrc = AppErr + return resp, err + } + + _, err = (*app).translateDelete(ctx.d) if err != nil { resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) @@ -925,10 +1091,22 @@ func Delete(req SetRequest) (SetResponse, error) { return resp, err } - resp, err = (*app).processDelete(d) + if ENABLE_TRANSLIB_ROLLBACK == "true" { + log.Infof("Delete: PHASE 2 - Calling processPreparePhase for namespace=%s", ctx.nameSpace) + err = (*app).processPreparePhase(ctx.d, ctx.nsPayload.Key) + if err != nil { + resp.ErrSrc = AppErr + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + return resp, abortErr + } + return resp, err + } + } + resp, err = (*app).processDelete(ctx.d) if err != nil { - d.AbortTx() + ctx.d.AbortTx() resp.ErrSrc = AppErr abortErr := abortTransactions(redisMdbInstances) if abortErr != nil { @@ -937,18 +1115,18 @@ func Delete(req SetRequest) (SetResponse, error) { return resp, err } - // Check if the entry with the same nameSpace already exists in the map - if _, exists := redisMdbInstances[nameSpace]; !exists { - redisMdbInstances[nameSpace] = d + if _, exists := redisMdbInstances[ctx.nameSpace]; !exists { + redisMdbInstances[ctx.nameSpace] = ctx.d } } + log.Infof("Delete: PHASE 2 complete - all namespaces written successfully, proceeding to commit") + cerr := commitTransactions(redisMdbInstances, namespacePayloads) - if cerr != nil { + if cerr != nil && ENABLE_TRANSLIB_ROLLBACK == "true" { for ns, redisDbInstance := range redisMdbInstances { for _, payload := range namespacePayloads { if payload.Namespace == ns && payload.Commited { - // Pass the payload.Key for rollback log.Infof("Rollback key:%v,Namespace: %s", payload.Namespace, payload.Key) err = (*app).rollback(redisDbInstance) if err != nil { @@ -958,14 +1136,13 @@ func Delete(req SetRequest) (SetResponse, error) { } } } - - err = processPostPhase() - if err != nil { - log.Infof("Cleanup of backup entries operation failed!") + if ENABLE_TRANSLIB_ROLLBACK == "true" { + err = processPostPhase() + if err != nil { + log.Infof("Cleanup of backup entries operation failed!") + } } - return resp, cerr - } // Get - Gets data from the redis DB and converts it to northbound format @@ -1183,7 +1360,6 @@ func Action(req ActionRequest) ([]ActionResponse, error) { // Bulk - BULK Request API for northbounds // Processes the request in received order // Transaction based - func Bulk(req BulkRequest) (BulkResponse, error) { type bulkRequestContext struct { app *appInterface @@ -1191,6 +1367,11 @@ func Bulk(req BulkRequest) (BulkResponse, error) { namespacePayloads []NamespacePayload keyStr string operation int + reqIndex int + nameSpace string + nsPayload NamespacePayload + payloadBytes []byte + d *db.DB } var err error @@ -1201,7 +1382,7 @@ func Bulk(req BulkRequest) (BulkResponse, error) { resp := BulkResponse{} redisMdbInstances := make(map[string]*db.DB) - contexts := make([]bulkRequestContext, len(req.Request)) + var writeContexts []bulkRequestContext if !isAuthorizedForBulk(req) { return resp, tlerr.AuthorizationError{ @@ -1214,6 +1395,8 @@ func Bulk(req BulkRequest) (BulkResponse, error) { resp.Response = make([]BulkResponseEntry, len(req.Request)) + log.Infof("Bulk: Starting PHASE 1 - CVL validation for all namespaces, total=%d", len(req.Request)) + for i := range req.Request { var keyStr string // Declare early to avoid goto skipping declaration @@ -1277,6 +1460,41 @@ func Bulk(req BulkRequest) (BulkResponse, error) { if operation == DELETE { keys, err = (*app).translateDelete(d) + + if err != nil { + errSrc = AppErr + goto BulkError + } + + err = d.AppendWatchTx(keys, appInfo.tablesToWatch) + if err != nil { + errSrc = AppErr + goto BulkError + } + log.Infof("Bulk: PHASE 1 - AppendWatchTx done for namespace=%s", nameSpace) + + d.Opts.DisableCVLCheck = true + err = (*app).processCVLValidate(d) + d.Opts.DisableCVLCheck = false + if err != nil { + log.Errorf("Bulk: PHASE 1 - CVL FAILED for namespace=%s, aborting all, error=%v", nameSpace, err) + errSrc = AppErr + goto BulkError + } + log.Infof("Bulk: PHASE 1 - CVL passed for namespace=%s, queuing for Phase 2", nameSpace) + + writeContexts = append(writeContexts, bulkRequestContext{ + app: app, + appInfo: appInfo, + namespacePayloads: namespacePayloads, + keyStr: keyStr, + operation: operation, + reqIndex: i, + nameSpace: nameSpace, + nsPayload: nsPayload, + payloadBytes: payloadBytes, + d: d, + }) } else { if len(payloads) == 0 { log.Infof("Payloads for namespace '%s' are empty, using top-level payload", nameSpace) @@ -1303,126 +1521,176 @@ func Bulk(req BulkRequest) (BulkResponse, error) { errSrc = AppErr goto BulkError } - } - switch operation { - case CREATE: - keys, err = (*app).translateCreate(d) - case UPDATE: - keys, err = (*app).translateUpdate(d) - if err != nil && isBulkNotFoundError(err) { - log.V(2).Infof("Since UPDATE Failed, Changing operation type to REPLACE") - operation = REPLACE - err = appInitialize(app, appInfo, path, &payloadBytes, nil, operation) - if err != nil { - errSrc = AppErr - goto BulkError + switch operation { + case CREATE: + keys, err = (*app).translateCreate(d) + case UPDATE: + keys, err = (*app).translateUpdate(d) + if err != nil && isBulkNotFoundError(err) { + log.V(2).Infof("Since UPDATE Failed, Changing operation type to REPLACE") + operation = REPLACE + err = appInitialize(app, appInfo, path, &payloadBytes, nil, operation) + if err != nil { + errSrc = AppErr + goto BulkError + } + keys, err = (*app).translateReplace(d) } + case REPLACE: keys, err = (*app).translateReplace(d) + default: + err = tlerr.NotSupported("Unknown operation '%v'", operation) } - case REPLACE: - keys, err = (*app).translateReplace(d) - default: - err = tlerr.NotSupported("Unknown operation '%v'", operation) - } - } - - if err != nil { - errSrc = AppErr - goto BulkError - } - - err = d.AppendWatchTx(keys, appInfo.tablesToWatch) - if err != nil { - errSrc = AppErr - goto BulkError - } - - contexts[i] = bulkRequestContext{ - app: app, - appInfo: appInfo, - namespacePayloads: namespacePayloads, - keyStr: keyStr, - operation: operation, - } - - err = (*app).processPreparePhase(d, keyStr) - if err != nil { - errSrc = AppErr - goto BulkError - } - switch operation { - case DELETE: - appResp, err = (*app).processDelete(d) - case CREATE: - appResp, err = (*app).processCreate(d) - case UPDATE: - appResp, err = (*app).processUpdate(d) - if err != nil && isBulkNotFoundError(err) { - log.V(2).Infof("Since UPDATE Failed again, fallback to REPLACE") - operation = REPLACE - err = appInitialize(app, appInfo, path, &payloadBytes, nil, operation) if err != nil { errSrc = AppErr goto BulkError } - keys, err = (*app).translateReplace(d) + + err = d.AppendWatchTx(keys, appInfo.tablesToWatch) if err != nil { errSrc = AppErr goto BulkError } - err = d.AppendWatchTx(keys, appInfo.tablesToWatch) + + err = (*app).processCVLValidate(d) if err != nil { + log.Errorf("Bulk: PHASE 1 - CVL FAILED for namespace=%s, aborting all, error=%v", nameSpace, err) errSrc = AppErr goto BulkError } - appResp, err = (*app).processReplace(d) + log.Infof("Bulk: PHASE 1 - CVL passed for namespace=%s, queuing for Phase 2", nameSpace) + + writeContexts = append(writeContexts, bulkRequestContext{ + app: app, + appInfo: appInfo, + namespacePayloads: namespacePayloads, + keyStr: keyStr, + operation: operation, + reqIndex: i, + nameSpace: nameSpace, + nsPayload: nsPayload, + payloadBytes: payloadBytes, + d: d, + }) } - case REPLACE: - appResp, err = (*app).processReplace(d) + } + } + + continue + + BulkError: + log.Infof("BulkError: %+v", err) + appResp.Err = err + appResp.ErrSrc = errSrc + resp.Response[i].Entry = appResp + + abortErr := abortTransactions(redisMdbInstances) + if abortErr != nil { + appResp.Err = abortErr + appResp.ErrSrc = errSrc + resp.Response[i].Entry = appResp + return resp, abortErr + } + + return resp, err + } + + log.Infof("Bulk: PHASE 1 complete - CVL passed for all namespaces, total=%d, proceeding to PHASE 2", len(writeContexts)) + + log.Infof("Bulk: Starting PHASE 2 - actual Redis writes") + + for _, ctx := range writeContexts { + log.Infof("Bulk: PHASE 2 - writing namespace=%s", ctx.nameSpace) + + path := req.Request[ctx.reqIndex].Entry.Path + + // Re-init and re-translate for this specific context's payload — + // app is shared across all payload items within the same request + // index, so its internal state must be repopulated per-context + // before writing, otherwise only the last Phase-1 iteration's + // state would get written repeatedly. + if ctx.operation != DELETE { + err = appInitialize(ctx.app, ctx.appInfo, path, &ctx.payloadBytes, nil, ctx.operation) + if err != nil { + errSrc = AppErr + goto BulkError2 } + switch ctx.operation { + case CREATE: + _, err = (*ctx.app).translateCreate(ctx.d) + case UPDATE: + _, err = (*ctx.app).translateUpdate(ctx.d) + case REPLACE: + _, err = (*ctx.app).translateReplace(ctx.d) + } if err != nil { errSrc = AppErr - goto BulkError + goto BulkError2 } + } - if _, exists := redisMdbInstances[nameSpace]; !exists { - redisMdbInstances[nameSpace] = d + if ENABLE_TRANSLIB_ROLLBACK == "true" { + err = (*ctx.app).processPreparePhase(ctx.d, ctx.keyStr) + if err != nil { + errSrc = AppErr + goto BulkError2 } + } - resp.Response[i].Entry = appResp + switch ctx.operation { + case DELETE: + appResp, err = (*ctx.app).processDelete(ctx.d) + case CREATE: + appResp, err = (*ctx.app).processCreate(ctx.d) + case UPDATE: + appResp, err = (*ctx.app).processUpdate(ctx.d) + case REPLACE: + appResp, err = (*ctx.app).processReplace(ctx.d) + } + + if err != nil { + errSrc = AppErr + goto BulkError2 + } + + if _, exists := redisMdbInstances[ctx.nameSpace]; !exists { + redisMdbInstances[ctx.nameSpace] = ctx.d } + resp.Response[ctx.reqIndex].Entry = appResp continue - BulkError: + BulkError2: log.Infof("BulkError: %+v", err) appResp.Err = err appResp.ErrSrc = errSrc - resp.Response[i].Entry = appResp + resp.Response[ctx.reqIndex].Entry = appResp abortErr := abortTransactions(redisMdbInstances) if abortErr != nil { appResp.Err = abortErr appResp.ErrSrc = errSrc - resp.Response[i].Entry = appResp + resp.Response[ctx.reqIndex].Entry = appResp return resp, abortErr } return resp, err } + log.Infof("Bulk: PHASE 2 complete - all namespaces written successfully, proceeding to commit") + // COMMIT PHASE cerr := commitTransactions(redisMdbInstances, namespacePayloads) // POST-COMMIT or ROLLBACK - for _, ctx := range contexts { + for _, ctx := range writeContexts { app := ctx.app namespacePayloads := ctx.namespacePayloads - if cerr != nil { + if cerr != nil && ENABLE_TRANSLIB_ROLLBACK == "true" { for ns, redisDbInstance := range redisMdbInstances { for _, payload := range namespacePayloads { if payload.Namespace == ns && payload.Commited { @@ -1436,12 +1704,12 @@ func Bulk(req BulkRequest) (BulkResponse, error) { } } } - - err = processPostPhase() - if err != nil { - log.Infof("Cleanup of backup entries operation failed!") + if ENABLE_TRANSLIB_ROLLBACK == "true" { + err = processPostPhase() + if err != nil { + log.Infof("Cleanup of backup entries operation failed!") + } } - return resp, cerr } diff --git a/translib/yanglib_app.go b/translib/yanglib_app.go index 35269e998..8b6bbd4dc 100644 --- a/translib/yanglib_app.go +++ b/translib/yanglib_app.go @@ -538,3 +538,7 @@ func (app *yanglibApp) processPreparePhase(d *db.DB, ckey string) error { func (app *yanglibApp) rollback(d *db.DB) error { return nil } + +func (app *yanglibApp) processCVLValidate(d *db.DB) error { + return nil +}