Netconf read during in-service upgrade

Hello,
I would like confd to respond to config reads (using the old schema with which it was started) during in-service upgrade.
From the user guide:

After having set up the MAAPI socket, the first step in the actual upgrade procedure is to call the maapi_init_upgrade() function. Its purpose is to bring ConfD into “upgrade mode”, where no transactions are running, and the northbound agents have entered a state that does not allow new transac- tions to be started.

Its understandable that writes are not supported, but why reads too ? Shouldnt the reads be allowed using the old schema that confd is aware of ?

Right now, doing a read during the upgrade yields this error:

application operation-failed error upgrade-in-progress

Thanks

First, you need to run in the same user session as you call the maapi_init_upgrade() from. You either want to associate with an already existing user session from where you will init the upgrade, or you start a new session from where you init the upgrade.

As the ConfD UG describes in the subchapter preceding your quote, i.e. “Preparing for the Upgrade”:

The upgrade.c program in the example controls the upgrade procedure. It can be run either standalone or via a osCommand specification in the clispec. In both cases it must connect a MAAPI socket and associate it with a user session. When running from the CLI, it must use the user session id provided by the environment variable CONFD_MAAPI_USID for this, otherwise it can start a new user session:

static int set_usess(int sock)
{
    char *user = "admin";
    const char *groups[] = {"admin"};
    char *context = "system";
    struct confd_ip ip;
    /* must use usid from CLI to be allowed to run across upgrade */
    if ((usid_env = getenv("CONFD_MAAPI_USID")) != NULL) {
        return maapi_set_user_session(sock, atoi(usid_env));
    } else {
        ip.af = AF_INET;
        inet_pton(AF_INET, "127.0.0.1", &ip.ip.v4);
        return maapi_start_user_session(sock, user, context, groups, 1,
                                        &ip, CONFD_PROTO_TCP);
    }
}

For a reference implementation, see the ConfD in_service_upgrade example:
$CONFD_DIR/examples.confd/in_service_upgrade/with_helper/upgrade.c

Then after maapi_preform_upgrade() and before maapi_commit_upgrade() you need to attach to the ConfD upgrade transaction using maapi_attach_init() to read/write to/from the old/new schema.

As the ConfD UG describes in the subchapter following your quote, i.e. “Committing the Upgrade”:

When maapi_perform_upgrade() has completed successfully, we must call maapi_commit_upgrade() to tell ConfD to make the upgrade permanent. This will also tell CDB to commit its upgrade transaction, and we may need to take some actions for this before the call:
• If the upgrade requires that an external program modifies some CDB data, it must be done at this point, using maapi_attach_init() as described in the CDB chapter.

From the confd_lib_maapi man page:

int maapi_attach_init(int sock, int *thandle);
This function is used to attach the MAAPI socket to the special transaction available in phase0 used for CDB initialization and upgrade. The function is also used if we need to modify CDB data during in-service data model upgrade (see the “In-service Data Model Upgrade” chapter in the User Guide). The transaction handle, which is used in subsequent calls to MAAPI, is filled in by the function upon successful return. See the CDB chapter in the User Guide.

See $CONFD_DIR/examples.confd/cdb_upgrade/using_maapi/server_upgrade.c
for an example of using maapi_attach_init()

...
    maapi_attach_init(ms, &th);
    maapi_set_namespace(ms, th, servers__ns);

    /* Loop over servers and set default values for new elems */
    maapi_init_cursor(ms, th, &mc, "/servers/server");
    maapi_get_next(&mc);
    while (mc.n != 0) {
        maapi_set_elem2(ms, th,
                        "0.0.0.0", "/servers/server{%x}/proxy", &mc.keys[0]);
        maapi_set_elem2(ms, th,
                        "true", "/servers/server{%x}/enabled", &mc.keys[0]);
        maapi_get_next(&mc);
    }
    maapi_destroy_cursor(&mc);

...
1 Like

Thanks a lot cohult. I forgot to mention that it’s the operational data that I am intending to read which is not stored in CDB, that’s why I did not go down the path mentioned by you as it mentions that it is for modifying data in CDB.

Should this work for operational data as well which is not in CDB?

Also, mapi_attach_init as per the UG needs to be used if we need to modify the data in CDB, so it wasn’t clear if its applicable for read-only queries as well.

With configuration data you typically do something like in the ConfD UG Example 5.13 and Example 5.14 . The upgrade() function of server_upgrade.c for more complex upgrades.
I.e. you read out the old configuration through the CDB API in a CDB session, and you write to the new configuration using MAAPI by attaching to the ConfD init / upgrade transaction.

For operational data you would typically read the old operational data, e.g. to an xml file, using MAAPI before initializing the upgrade, or using the CDB API after maapi_perform_upgrade() and then write the operational data in to the new operational datastore schema again, preferably using the CDB API, after maapi_commit_upgrade(), e.g. from the xml file that you created earlier.

So for example some code using maapi_save_config() or a script that does the following would store the CDB operational data under /arpentries to a backup file that can be modified.

$ confd_load -d -d -F p -o -p "/arpentries" > /tmp/oper.xml
TRACE Connected (maapi) to ConfD
starting user session ctxt=system user=system groups=[system]
TRACE MAAPI_START_USER_SESSION  --> CONFD_OK
TRACE MAAPI_START_TRANS  --> CONFD_OK
TRACE MAAPI_SAVE_CONFIG  --> CONFD_OK
TRACE Connected (stream) to ConfD
TRACE MAAPI_SAVE_CONFIG_RESULT  --> CONFD_OK
TRACE MAAPI_END_USER_SESSION  --> CONFD_OK

And for example some code using cdb_load_file() or a script that does the following would read the operational data back to CDB operational datastore (here using the confd_load tool that come with source code in the ConfD release)

$ confd_load -d -d -l -C /tmp/oper.xml
TRACE Connected (cdb) to ConfD
TRACE CDB_NEW_SESSION  --> CONFD_OK
TRACE Established new CDB session to ConfD
TRACE CDB_LOAD_FILE  --> CONFD_OK
TRACE CDB_END_SESSION  --> CONFD_OK

Thanks Cohult for your reply. Really appreciate your help.

I think I am not putting my issue correctly, let me try reboot my original question.
I am maintaining both config and operational data. Config data is maintained in CDB and operational data is maintained outside CDB in some other datastore by the daemon.

During the in-service upgrade, I am fine with not accessing the config data in CDB, but I would like the operational data be readable from RESTCONF/NETCONF. At no point during my upgrade process, I would want to update any config / operational data.

Were you suggesting to load the operational data which is stored outside of CDB into CDB by first writing it into XML and then loading it into CDB using confd_load ?
Creating a backup XML file doesn’t sound to be a feasible idea since the data can be pretty huge.

I just want the operational data (stored outside of CDB) be readable while in-service upgrade in in progress and not be rejected by confd.

Thanks.

Only the ConfD CDB upgrade transaction is allowed to run during the upgrade. No other northbound read or write transactions are allowed, i.e. over NETCONF, REST, CLI, etc. You can over MAAPI if you attach to the init/upgrade transaction.

When you call the maapi_init_upgrade() function, you bring ConfD into “upgrade mode”, where no transactions are running, and the northbound agents have entered a state that does not allow any new transactions to be started.

Hmm…thats what I understood from the UG. It’s really sad though, was hoping to find a tweak configuration setting wherein we could atleast make read queries serviceable.

Thanks.