Leaf-list schema upgrade issue

Hello all,

I have a problem with setting leaf-list during phase0 of schema upgrade.

Executing the following line after phase0, before phase1

maapi_set_elem2(ms, th, "3 4", "/servers-new/little-list");

result in:

TRACE MAAPI_SET_ELEM2 /servers-new/little-listDEBUG internal error -
 --> CONFD_ERR

confderr.log.1 content:

�nonode@nohost�kinit:boot_msg: ~plkpCDB: Upgrade failed: Upgrade transaction failed to validate: /servers:servers-new/little-list is not configured
nonode@nohost�k/confd_maapi: Other err:~n ~p: ~p~n Args2 = ~p~nlhderrorhdbadargk
nonode@nohost` B�3߉�n�Q�DVbrм�ajjhdxds_ramd
                                           tts_add_dynalhdfilek
                                                               xds_ram.erlhdlineb|jhdxdsdensure_insert_dynamicalhdfilekxds.erlhdlinea�jhcs_transddo_sh_createalhdfilekcs_trans.erlhdlineb(�jhcs_transd-sh_create_leaf_list/8-fun-0-lhdfilekcs_trans.erlhdlineb!Wjhdlistsdfoldlalhdfilek lists.erlhdlineb�jhcs_transdsh_create_leaf_listlhdfilekcs_trans.erlhdlineb!djhcs_transdset!lhdfilekcs_trans.erlhdlineb_jhd
                                                                                                                                                                                  confd_maapiddo_set_elem2alhdfilekconfd_maapi.erlhdlineb#�jhd
              confd_maapiddoalhdfilekconfd_maapi.erlhdlineb�jhd
                                                               confd_maapid
handle_libalhdfilekconfd_maapi.erlhdlineb8jhproc_libdinit_palhdfilekproc_lib.erlhdlinea�jjla�m/�����hm3 4lw
                                                                                                           servers-neww
nonode@nohost�kinit:boot_msg: ~plkpCDB: Upgrade failed: Upgrade transaction failed to validate: /servers:servers-new/little-list is not configuredk16-Nov-2020::15:57:34.341hderrorgd

My confd version: 7.3.2

Below minimal set of files to reproduce the issue:

  • servers.yang:
module servers {
  yang-version 1.1;

  namespace "http://tail-f.com/ns/example/servers";
  prefix servers;

  container servers {
    leaf id {
      type uint32;
    }
  }
}
  • servers2.yang
module servers2 {
  yang-version 1.1;

  namespace "http://tail-f.com/ns/example/servers";
  prefix servers;

  container servers-new {
    leaf id {
      type uint32;
    }
    leaf-list little-list {
      min-elements 1;
      max-elements 8;
      type uint16;
    }
  }
}
  • main.c
int main(int argc, char *argv[])
{
    char *confd_addr = "127.0.0.1";
    int confd_port = CONFD_PORT;
    int ms;
    int th;

    struct sockaddr_in addr;

    addr.sin_addr.s_addr = inet_addr(confd_addr);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(confd_port);

    confd_init("leaf-list's are evil", stdout, CONFD_TRACE);

    ms = socket(PF_INET, SOCK_STREAM, 0);

    maapi_connect(ms, (struct sockaddr *)&addr, sizeof(addr));
    maapi_attach_init(ms, &th);
    maapi_set_namespace(ms, th, servers__ns);

    int maapi_ret = maapi_set_elem2(ms, th, "3 4", "/servers-new/little-list");
    fprintf(stderr, "XXX maapi_ret %d\n", maapi_ret);

    exit(0);
}
  • ‘Makefile’
include $(CONFD_DIR)/src/confd/build/include.mk

CONFD_FXS_DIR = $(CONFD_DIR)/etc/confd

CONFD_FLAGS = --addloadpath $(CONFD_FXS_DIR)
START_FLAGS ?=

all:    ssh-keydir
        @echo "Build complete"

server_upgrade: main.c servers2.h
        $(CC) $(CFLAGS) $< $(LIBS) -o $@

######################################################################
clean: iclean
        -rm -rf confd_candidate.db \
                server_upgrade servers2.h 2> /dev/null || true

######################################################################
start:  stop $(CDB_DIR) servers.fxs
        : ### Start the confd daemon using servers.fxs
        cp servers_init.xml $(CDB_DIR)/servers_init.xml
        $(CONFD) -c confd.conf $(CONFD_FLAGS)
        : ### CDB will be initialized with servers_init.xml
        : ### Inspect using "$(MAKE) query"
        : ### Edit entries using command line interface "$(MAKE) cli"
        : ### Then stop confd and start version 2, using "$(MAKE) start-v2"

start-v2: stop server_upgrade servers2.fxs
        @if [ ! -e $(CDB_DIR)/C.cdb ]; then                     \
            echo "Run \"$(MAKE) start\" before start-v2" ;      \
            exit 1 ;                                            \
         fi
        : ### Remove the fxs file which is no longer valid
        rm servers.fxs
        : ### Remove the init file which is no longer valid
        rm $(CDB_DIR)/servers_init.xml
        : ### Start the confd daemon using servers2.fxs version 2.0
        $(CONFD) -c confd.conf --start-phase0 $(CONFD_FLAGS)
        : ### Now run "server_upgrade" to move servers to new catagories
        ./server_upgrade
        : ### Now bring ConfD up to fully operational state
        $(CONFD) --start-phase1
        $(CONFD) --start-phase2
        : ### To see the result query the daemon using "$(MAKE) query"

######################################################################
stop:
        : ### Stopping any confd daemon running
        $(CONFD) --stop    || true

Then run:

$ make all start

and finally

$ make start-v2

I realize that solving this could take time and unless I’ve done something obviously stupid please share your ideas to workaround this problem.

I’ve also tried maapi_set_elem function with confd_value_t composed as a C_LIST. The result was the same: internal error without any further explanation.

Removing

min-elements 1;

from servers2.yang helps: maapi_set_elem2 succeeds.

Unfortunately, it does not satisfy us as this constraint is our requirement and cannot be dropped.

Hello,

i do not have access to my dev machine today, so cannot check details/versions etc.

Please note that leaf-list behavior has been changed for some time (confd 6.4? not sure…) and leaf-lists do NOT behave as other leaves, unless you have special flag enabled in confd-lib, that allows temporary compatibility with old behavior…

leaf-lists behave as lists, in regard to creation of items, deletion of items, etc., thus you should not do maapi_set_elem(), but rather maapi_create() / maapi_delete() - just like you would for regular list entries…

In ConfD User Guide for ConfD 7.3 we can see:

int maapi_create(int sock, int thandle, const char *fmt, ...);
Create a new list entry, a presence container, or a leaf of type empty in the data tree. For example:
maapi_create(sock,th,"/servers/server{www}");

It doesn’t mention leaf-list.

Still, using maapi_create doesn’t help:

$ confd_cmd -dddd -c 'mattach_init; mcreate /servers-new/little-list{0}'
mattach_init ; mcreate "/servers-new/little-list{0}"
TRACE Connected (maapi) to ConfD
TRACE MAAPI_ATTACH  --> CONFD_OK
TRACE MAAPI_CREATE /servers-new/little-list{0}DEBUG internal error -
 --> CONFD_ERR
FAILED: maapi_create(ms, mtid, argv[0]), Error: internal error (18): , in function do_maapi_create, line 1379

To supplement. maapi_create works if min-elements 1; constraint is dropped:

$ confd_cmd -dddd -c 'mattach_init; mcreate /servers-new/little-list{0}'
mattach_init ; mcreate "/servers-new/little-list{0}"
TRACE Connected (maapi) to ConfD
TRACE MAAPI_ATTACH  --> CONFD_OK
TRACE MAAPI_CREATE /servers-new/little-list{0} --> CONFD_OK
TRACE MAAPI_END_USER_SESSION  --> CONFD_OK

Seems like a bug.

One example of a workaround is to replace the min-elements with a *must" statement:

container servers-new {
    leaf id {
      type uint32;
    }
    must "count(little-list) > 1" {
      error-message "At least 1 elem must be configured";
      tailf:dependency "./little-list";
    }
    leaf-list little-list {
      max-elements 8;
      type uint16;
    }
}