<!-- 
RSS generated by JIRA (8.20.10#820010-sha1:ace47f9899e9ee25d7157d59aa17ab06aee30d3d) at Wed Feb 07 20:09:51 UTC 2024

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary append 'field=key&field=summary' to the URL of your request.
-->
<rss version="0.92" >
<channel>
    <title>OpenDaylight JIRA</title>
    <link>https://jira.opendaylight.org</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>8.20.10</version>
        <build-number>820010</build-number>
        <build-date>22-06-2022</build-date>
    </build-info>


<item>
            <title>[MDSAL-456] Inconsistent list handling in Binding datastore operations</title>
                <link>https://jira.opendaylight.org/browse/MDSAL-456</link>
                <project id="10137" key="MDSAL">mdsal</project>
                    <description>&lt;p&gt;Before neon MRI upgrade, the output of oper inventory when no switch is connected was:&lt;/p&gt;
&lt;div class=&quot;preformatted panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;preformattedContent panelContent&quot;&gt;
&lt;pre&gt;GET /restconf/operational/opendaylight-inventory:nodes
200 OK {}&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;After neon MRI upgrade, this did not change when the controller starts for the first time, however when switch connects and disconnects, the above changes to:&lt;/p&gt;
&lt;div class=&quot;preformatted panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;preformattedContent panelContent&quot;&gt;
&lt;pre&gt;GET /restconf/operational/opendaylight-inventory:nodes

404 Request could not be completed because the relevant data model content does not exist
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&#160;&lt;/p&gt;

&lt;p&gt;Because of the above we had to remove some OFP test.&lt;/p&gt;</description>
                <environment></environment>
        <key id="31076">MDSAL-456</key>
            <summary>Inconsistent list handling in Binding datastore operations</summary>
                <type id="10104" iconUrl="https://jira.opendaylight.org/secure/viewavatar?size=xsmall&amp;avatarId=10303&amp;avatarType=issuetype">Bug</type>
                                            <priority id="1" iconUrl="https://jira.opendaylight.org/images/icons/priorities/blocker.svg">Highest</priority>
                        <status id="5" iconUrl="https://jira.opendaylight.org/images/icons/statuses/resolved.png" description="A resolution has been taken, and it is awaiting verification by reporter. From here issues are either reopened, or are closed.">Resolved</status>
                    <statusCategory id="3" key="done" colorName="green"/>
                                    <resolution id="10000">Done</resolution>
                                        <assignee username="rovarga">Robert Varga</assignee>
                                    <reporter username="ecelgp">Luis Gomez</reporter>
                        <labels>
                    </labels>
                <created>Fri, 16 Nov 2018 19:07:40 +0000</created>
                <updated>Fri, 1 May 2020 12:20:17 +0000</updated>
                            <resolved>Wed, 22 Apr 2020 08:22:33 +0000</resolved>
                                    <version>3.0.8</version>
                    <version>4.0.2</version>
                                    <fixVersion>6.0.0</fixVersion>
                                        <due></due>
                            <votes>0</votes>
                                    <watches>2</watches>
                                                                                                                <comments>
                            <comment id="65739" author="ecelgp" created="Fri, 23 Nov 2018 18:44:15 +0000"  >&lt;p&gt;This actually explains, however it is weird it does not work the first time the controller boots up:&lt;br/&gt;
&lt;a href=&quot;https://wiki.opendaylight.org/view/Neon_platform_upgrade#Datastore_lifecycle&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://wiki.opendaylight.org/view/Neon_platform_upgrade#Datastore_lifecycle&lt;/a&gt;&lt;/p&gt;</comment>
                            <comment id="66592" author="ecelgp" created="Mon, 18 Mar 2019 17:48:26 +0000"  >&lt;p&gt;I would say either we close this because the change impact is minimal or we move the issue to yangtools projects for further investigation.&lt;/p&gt;</comment>
                            <comment id="66748" author="vishnoianil@gmail.com" created="Thu, 2 May 2019 00:38:42 +0000"  >&lt;p&gt;&lt;a href=&quot;https://jira.opendaylight.org/secure/ViewProfile.jspa?name=rovarga&quot; class=&quot;user-hover&quot; rel=&quot;rovarga&quot;&gt;rovarga&lt;/a&gt; any thoughts on this issue?&lt;/p&gt;</comment>
                            <comment id="66751" author="rovarga" created="Thu, 2 May 2019 06:20:58 +0000"  >&lt;p&gt;As documented here: &lt;a href=&quot;https://wiki.opendaylight.org/view/Neon_platform_upgrade#DataTree_removes_empty_lists.2C_choices_and_augmentations&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://wiki.opendaylight.org/view/Neon_platform_upgrade#DataTree_removes_empty_lists.2C_choices_and_augmentations&lt;/a&gt; the list will disappear, so the outcome is correct.&lt;/p&gt;</comment>
                            <comment id="66788" author="ecelgp" created="Tue, 14 May 2019 18:14:31 +0000"  >&lt;p&gt;We understand the change in behavior but we do not understand why this change does not apply the first time the controller boots up: if I boot the controller for the first time and the switches are not connected I get 200 OK + empty list, now if I connect a switch and disconnect the same, then I get 404, so it seems to me the API is not consistent or there is a bug during the boot up process.&lt;/p&gt;</comment>
                            <comment id="66789" author="rovarga" created="Tue, 14 May 2019 18:38:04 +0000"  >&lt;p&gt;Ah, now I understand the inconsistency. I suspect this is due to how the topology is initialized. What are the transactions OFP executes during init?&lt;/p&gt;</comment>
                            <comment id="66790" author="ecelgp" created="Tue, 14 May 2019 18:42:41 +0000"  >&lt;p&gt;&lt;a href=&quot;https://jira.opendaylight.org/secure/ViewProfile.jspa?name=Avishnoi&quot; class=&quot;user-hover&quot; rel=&quot;Avishnoi&quot;&gt;Avishnoi&lt;/a&gt;, can you answer Roberts&apos;s question?&lt;/p&gt;</comment>
                            <comment id="66795" author="vishnoianil@gmail.com" created="Wed, 15 May 2019 22:00:51 +0000"  >&lt;p&gt;&lt;a href=&quot;https://jira.opendaylight.org/secure/ViewProfile.jspa?name=rovarga&quot; class=&quot;user-hover&quot; rel=&quot;rovarga&quot;&gt;rovarga&lt;/a&gt; It&apos;s not topology, but inventory. During initialization it initialize the operational datastore with empty list&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
&lt;span class=&quot;code-keyword&quot;&gt;final&lt;/span&gt; WriteTransaction tx = dataBroker.newWriteOnlyTransaction();

&lt;span class=&quot;code-keyword&quot;&gt;try&lt;/span&gt; {
tx.merge(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class), &lt;span class=&quot;code-keyword&quot;&gt;new&lt;/span&gt; NodesBuilder()
.setNode(Collections.emptyList())
.build());
tx.commit().get();
} &lt;span class=&quot;code-keyword&quot;&gt;catch&lt;/span&gt; (ExecutionException | InterruptedException e) {
LOG.error(&lt;span class=&quot;code-quote&quot;&gt;&quot;Creation of node failed.&quot;&lt;/span&gt;, e);
&lt;span class=&quot;code-keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;code-keyword&quot;&gt;new&lt;/span&gt; IllegalStateException(e);
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;After the controller starts and i fetch GET&#160;&lt;a href=&quot;http://&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;http://\&lt;/a&gt;&lt;tt&gt;controller-ip&lt;/tt&gt;:8181/restconf/operational/opendaylight-inventory:nodes&lt;/p&gt;

&lt;p&gt;it shows me&#160;&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
{}&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;than i connect the device and it shows me device list in following json for the same above url&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
{
&lt;span class=&quot;code-quote&quot;&gt;&quot;nodes&quot;&lt;/span&gt;: {
   &lt;span class=&quot;code-quote&quot;&gt;&quot;node&quot;&lt;/span&gt;: ...... &lt;span class=&quot;code-comment&quot;&gt;//all nodes details
&lt;/span&gt;  }
}&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;After devices are added to operational datastore&#160;it shows &quot;nodes&quot; list but&#160;in the previous case (Fresh restart), it was just showing empty list {} ( i thought it should have shown&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
{
&lt;span class=&quot;code-quote&quot;&gt;&quot;nodes&quot;&lt;/span&gt; :{}
}&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Then i disconnect all the switches (it removes individual nodes)&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
@Override
&lt;span class=&quot;code-keyword&quot;&gt;public&lt;/span&gt; ListenableFuture&amp;lt;?&amp;gt; removeDeviceFromOperationalDS(@Nonnull &lt;span class=&quot;code-keyword&quot;&gt;final&lt;/span&gt; KeyedInstanceIdentifier&amp;lt;Node, NodeKey&amp;gt; ii) {

&lt;span class=&quot;code-keyword&quot;&gt;final&lt;/span&gt; WriteTransaction delWtx = dataBroker.newWriteOnlyTransaction();
delWtx.delete(LogicalDatastoreType.OPERATIONAL, ii);
&lt;span class=&quot;code-keyword&quot;&gt;return&lt;/span&gt; delWtx.commit();

}
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;and when i fetch the operational nodes again it throws error (404)&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
{
&lt;span class=&quot;code-quote&quot;&gt;&quot;errors&quot;&lt;/span&gt;: {
&lt;span class=&quot;code-quote&quot;&gt;&quot;error&quot;&lt;/span&gt;: [
{
&lt;span class=&quot;code-quote&quot;&gt;&quot;error-type&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;application&quot;&lt;/span&gt;,
&lt;span class=&quot;code-quote&quot;&gt;&quot;error-tag&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;data-missing&quot;&lt;/span&gt;,
&lt;span class=&quot;code-quote&quot;&gt;&quot;error-message&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;Request could not be completed because the relevant data model content does not exist&quot;&lt;/span&gt;
}
]
}
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&#160;&lt;/p&gt;</comment>
                            <comment id="66797" author="rovarga" created="Thu, 16 May 2019 10:13:50 +0000"  >&lt;p&gt;So if you do not do .setNode(Collection.emptyList()), things should be consistent. The reason why this is happening is that merge() will turned into a write() of nodes, which contains an empty list. We do not examine the contents of written data to eliminate empty lists etc.&lt;/p&gt;</comment>
                            <comment id="66801" author="vishnoianil@gmail.com" created="Sat, 18 May 2019 20:12:50 +0000"  >&lt;p&gt;I think that&apos;s where the inconsistency in behavior is, so&#160;if user is adding element&#160;to that empty list and than removing all of it,&#160;which results in the same empty list, why does it throws error rather than responding with empty list?&lt;/p&gt;</comment>
                            <comment id="66802" author="rovarga" created="Mon, 20 May 2019 13:57:45 +0000"  >&lt;p&gt;Since the list becomes empty, it is removed (along with any of its insignificant parents). The initial state of having the empty list present is wrong, hence the simplest solution is &lt;a href=&quot;https://git.opendaylight.org/gerrit/82167&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://git.opendaylight.org/gerrit/82167&lt;/a&gt; .&lt;/p&gt;</comment>
                            <comment id="66803" author="vishnoianil@gmail.com" created="Mon, 20 May 2019 18:33:52 +0000"  >&lt;p&gt;In my opinion,&#160;we have a API inconsistency here. Either the empty list/ container, should not be allowed while writing to the data store or the empty container/list should not be removed when&#160;all the elements are removed from it, but we are seeing different behavior for&#160;write and delete API&apos;s here. To make thing worst, these workarounds are something user will have to&#160;keep in mind while they program, where they don&apos;t have clear guidline on do&apos;s and don&apos;ts.&#160;&lt;/p&gt;</comment>
                            <comment id="66814" author="rovarga" created="Tue, 21 May 2019 21:18:57 +0000"  >&lt;p&gt;Well yes, but that inconsistency does not lie solely in yangtools, because:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;yangtools is providing DataTree API and an implementation&lt;/li&gt;
	&lt;li&gt;you are talking to mdsal-binding-api, which is a completely unrelated API&lt;/li&gt;
	&lt;li&gt;there is a stack of components (and since it&apos;s Operational store, which is internal, OFP is a privileged application, hence mitigations there are a fair game)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;And the end of the day, this boils down to OFP writing and empty List through Binding APIs, which translates do an empty map, which is retained by InMemoryDataTree.&lt;/p&gt;

&lt;p&gt;From yangtools perspective, it is an operational write, which we are expecting to be consistent &#8211; hence we trust the data to be minimaly-conformant. Unrestricted empty lists are okay from validation perspective, hence there is not much we are doing wrong. Fixing the issue at this level would require an additional check (incurred at every write) and possible NormalizedNode rebuild (if we find an empty list). If at all possible, we want to solve this problem at a different layer.&lt;/p&gt;

&lt;p&gt;Note that lists are addressable in DOM, but not addressable in Binding &#8211; hence Binding has nonnullFoo() bridges, as we are fully expecting people to treat empty and null lists the same (and anyway, that&apos;s an MD-SAL issue).&lt;/p&gt;

&lt;p&gt;That brings a possible solution: empty lists should be pruned completely when translated from binding. That obviously has impacts, so needs to be considered carefully. If you can provide an estimate of breakage this would bring, that would be appreciated.&lt;/p&gt;

&lt;p&gt;Whatever we do, the empty list merged by OFP will become a no-op and therefore, as a matter of efficiency, proposed OFP patch is an obvious simplification and is therefore the right thing to remove it.&lt;/p&gt;

&lt;p&gt;As for DO&apos;s and DON&apos;T&apos;s, there are always going to be some. Some of them are &quot;this is really a bad idea&quot;, and as genius shows, that will not dissuade people. Some of them are &quot;yeah, okay, this really means nothing&quot;, which is the case here (once solved).&lt;/p&gt;</comment>
                            <comment id="66815" author="rovarga" created="Tue, 21 May 2019 21:21:17 +0000"  >&lt;p&gt;Oh, and btw. the end result is better experience for applications &#8211; they have even less to worry about. Existing applications should simplify where possible, i.e. eliminate every single line of code, which is not required.&lt;/p&gt;</comment>
                            <comment id="66905" author="rovarga" created="Tue, 18 Jun 2019 19:54:33 +0000"  >&lt;p&gt;&lt;a href=&quot;https://git.opendaylight.org/gerrit/82558&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://git.opendaylight.org/gerrit/82558&lt;/a&gt; implements the binding-level change: we do not emit empty lists. &lt;a href=&quot;https://jira.opendaylight.org/secure/ViewProfile.jspa?name=ecelgp&quot; class=&quot;user-hover&quot; rel=&quot;ecelgp&quot;&gt;ecelgp&lt;/a&gt; can you give it a test-drive across all of CSIT?&lt;/p&gt;</comment>
                            <comment id="66935" author="ecelgp" created="Tue, 25 Jun 2019 16:20:31 +0000"  >&lt;p&gt;OK, I created distribution with multi-patch: &lt;a href=&quot;https://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/org/opendaylight/integration/integration/distribution/karaf/0.11.0-SNAPSHOT/karaf-0.11.0-20190625.163317-26.zip&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/org/opendaylight/integration/integration/distribution/karaf/0.11.0-SNAPSHOT/karaf-0.11.0-20190625.163317-26.zip&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And run few OFP tests and saw no problem. Should we run more tests?&lt;/p&gt;</comment>
                            <comment id="66944" author="vishnoianil@gmail.com" created="Thu, 27 Jun 2019 00:38:22 +0000"  >&lt;p&gt;&lt;a href=&quot;https://jira.opendaylight.org/secure/ViewProfile.jspa?name=ecelgp&quot; class=&quot;user-hover&quot; rel=&quot;ecelgp&quot;&gt;ecelgp&lt;/a&gt; i think we need to revert&#160;&lt;a href=&quot;https://git.opendaylight.org/gerrit/#/c/77908/&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://git.opendaylight.org/gerrit/#/c/77908/&lt;/a&gt;&#160;and run the test again to confirm the fix?&lt;/p&gt;</comment>
                            <comment id="66947" author="ecelgp" created="Thu, 27 Jun 2019 19:23:08 +0000"  >&lt;p&gt;Yes, the revert patch + MDSAL change works here:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://jenkins.opendaylight.org/releng/view/openflowplugin/job/openflowplugin-csit-3node-gate-clustering-bulkomatic-only-sodium/76/&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://jenkins.opendaylight.org/releng/view/openflowplugin/job/openflowplugin-csit-3node-gate-clustering-bulkomatic-only-sodium/76/&lt;/a&gt;&lt;/p&gt;</comment>
                            <comment id="67263" author="rovarga" created="Sun, 22 Sep 2019 02:08:39 +0000"  >&lt;p&gt;What is actually breaking is this: &lt;a href=&quot;https://github.com/opendaylight/ovsdb/blob/master/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/McastMacsRemoteRemoveCommand.java#L125&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://github.com/opendaylight/ovsdb/blob/master/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/McastMacsRemoteRemoveCommand.java#L125&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I.e. the change here is that we get null vs. empty list, which ends up being compared as non-equal. This will be addressed in Aluminium as part of &lt;a href=&quot;https://jira.opendaylight.org/browse/MDSAL-449&quot; title=&quot;Empty lists/maps have no semantic meaning in Binding&quot; class=&quot;issue-link&quot; data-issue-key=&quot;MDSAL-449&quot;&gt;&lt;del&gt;MDSAL-449&lt;/del&gt;&lt;/a&gt;.&lt;/p&gt;</comment>
                    </comments>
                <issuelinks>
                            <issuelinktype id="10000">
                    <name>Blocks</name>
                                                                <inwardlinks description="is blocked by">
                                        <issuelink>
            <issuekey id="31702">MDSAL-449</issuekey>
        </issuelink>
                            </inwardlinks>
                                    </issuelinktype>
                            <issuelinktype id="10003">
                    <name>Relates</name>
                                            <outwardlinks description="relates to">
                                        <issuelink>
            <issuekey id="23005">YANGTOOLS-585</issuekey>
        </issuelink>
                            </outwardlinks>
                                                        </issuelinktype>
                    </issuelinks>
                <attachments>
                    </attachments>
                <subtasks>
                    </subtasks>
                <customfields>
                                                                            <customfield id="customfield_11400" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                <customfield id="customfield_10000" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>0|i03krr:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                </customfields>
    </item>
</channel>
</rss>