Wildcard card in a xpath of must constraint

hi

I have a node, which needs to check if someone else has a reference
when its deleted , .

Basically i want to check if a node under a list is set .
can i wildcard the xpath for the list name so that it checks all the list items if it contains a certain leaf set ?

e.g if i have configs like
listname A leaf “bgp100”
listname B Leaf “bgp200”
listname C Leaf “bgp100”
listname D leaf “bgp100”

and i have config like
“no bgp100”
i would like to check before deleting the node bgp100, i want to check if any of the listA B or C is using the bgp100.

My constraint is , I cannot use leafref as the creation of
list A leaf “bgp100” is not really dependent on the bgp100 config.

Should i write a validation callpoint and loop through all of the list ?
or simply i can use a must constraint
/listname/*/leaf/value ?

Also how do i trigger the must constraint only during deletion ?

Many Thanks.

A YANG example instead of some CLI config would be more helpful.

But from what I can tell from your description, as you want to do the check for a certain operation, delete the standalone leaf, you need to use a validation point.

must expressions validate if a new config is valid. It doesn’t compare the new config with the old config being replaced, i.e. take into account what operation (here delete) is used.

@cohult,

Here is a more detailed explanation.of course this is more simplified version. but it conveys the point i guess

  list vrf  {
    key "idx";
    leaf idx { type uint32; }
    container route-leak {
      list name { 
        key "name" ;   
        leaf  name { type string; }
        container from  {
          list  vrf  {
            key "idx";
            leaf idx { type uint32; } 
          }
        }
      }
    }
  }

Here when you delete a vrf index , we should check if any entry in “from–vrf” in any element in route-leak refers this.

If its referring , we should prohitbit.

Thanks in advance.

I agree that you cannot use must or leafref - what you want is to validate an operation, not the resulting configuration (which is somewhat against YANG principles, by the way). I don’t think you can use standard validation callback either - technically they can be used to compare current and new configurations, but it looks to me that in this case it is not possible or at least it would be difficult.

You may want to have a look at transaction hooks - you can declare a transaction hook on the vrf list and register a remove callback in which you would check if there is a reference to the instance that is being deleted and let the transaction fail if it is. The check might be done using XPath expressions for better performance.

1 Like

I believe one should wait until the prepare phase and do that type of check from there.
Perhaps using get_modifications() from a prepare phase subscriber.
Validation should be done on the data (not operations) in YANG model checks, e.g. must expressions, and validataion code. Operations, tests etc should be done in the prepare phase, e.g. from a prepare phase subscriber.

The reason for that is that aborting the transaction from a transaction-hook will not enable you to provide the proper error message (the transaction hook is not meant to be used for validation), while an abort in the prepare phase will. The examples.confd/cdb_subscription/twophase example that comes with ConfD provide guidance.

1 Like

Great . Thanks Conny

@mvf @cohult
Thanks for the replies.

Im still unsure why a prepare phase is preferred than the validation ? (apart from the error message )
If validation phase is still an option,
Does the validation phase have the view of resulting config ?
Can i write a validation hook

If Prepare phase is the way to go ,
Do i get the view of CDB snapshot just at the cdb_diff_iterate stage,

e.g
if a transaction already contains both config
no vrf A
no rout-leak blah from vrf A.
Does the CDB already reflect both configs at that point ?

I have to correct myself. The validation phase using a validation point is actually what you want here. One of the reasons for that is if someone decides to just validate without committing the configuration, you then too want to run your validation code.

To read the old configuration use the CDB API. To get the new configuration use MAAPI. Note that maapi_diff_iterate() will not show the old value in the validation phase. The “oldv” passed to the iter() function by maapi_diff_iterate() will always be null. You will have to use the CDB API and cdb_get_*() to get the old value(s).

The error message handling is there for both the validation point and the prepare phase subscriber. I was referring to the transaction-hook and how the transaction-hook is not where you want to validate and abort a transaction.

1 Like

@conny @mvf,
ok So valiadtion phase the way to go …
Can i write the validation hooks , using erlang also ?
If so are there any examples ?
Is it the same as transactional hook?

It is not a hook or similar to a transaction-hook. See ConfD UG Chapter “Validation Points” and the confd_lib_dp(3) man page section "“Validation Callbacks”

You can find some sort of Erlang econfd reference here:

$ pwd
/Users/tailf/confd-7.3.2
$ find ./erlang/econfd/examples/ -name "*.yang" |xargs grep validate 
./erlang/econfd/examples//test/smp.yang:    tailf:validate vp1;
./erlang/econfd/examples//test/smp.yang:            tailf:validate vp2;
$ find ./erlang/econfd/examples/ -name "*.erl" |xargs grep vp1
./erlang/econfd/examples//test/test.erl:    ?line V = #confd_valpoint_cb{valpoint = vp1,
$ find ./erlang/econfd/examples/ -name "*.erl" |xargs grep vp2
./erlang/econfd/examples//test/test.erl:    ?line V2 = #confd_valpoint_cb{valpoint = vp2,
1 Like

Thanks @cohult

Just to be clear iun future .
The transaction cycle from the Confd UG

start -> READ -> validate -> write -> Prepared -Commit /Abort.

Where in the sequence the Transactional and Transformational Hooks are called ?

Just set the developer log level to “trace”, execute a transaction, and check the log for what was done for your confd.conf setup and applications. Example:

applying transaction…
entering validate phase for running…
grabbing transaction lock…
grabbing transaction lock ok
creating rollback file…
creating rollback file ok
run transforms and transaction hooks...
run transforms and transaction hooks done
pre validate…
pre validate done
run validation over the changeset…
run validation over the changeset done
run dependency-triggered validation…
run dependency-triggered validation done
leaving validate phase for running
entering write-start phase for running…
cdb: write-start
check data kickers…
check data kickers done
leaving write-start phase for running
entering prepare phase for running…
cdb: prepare
leaving prepare phase for running
entering commit phase for running…
cdb: commit
releasing transaction lock
leaving commit phase for running
applying transaction done

1 Like

Let me summarize some differences between transaction hooks and validation, as applied to this use case:

Validation callbacks in general are the right thing for validation. They are invoked when all changes are complete, pretty much just before they are written to CDB; and as Conny pointed out, they are also invoked when the operator asks for mere validation (e.g. using validate CLI command or test-only NETCONF message). There are some problems with validations in your case though:

  • you need to declare tailf:validate on the from-vrf node, not on the top vrf node, but with dependencies on it - this might somewhat counterintuitive;

  • your validation callback will not be simple to write - you need to compare the list of vrf instances in the transaction with the list of vrf instance in CDB to find which ones have been deleted, and then verify that no from-vrf instance refers to one of them.

The second point is related to that validation callbacks are tailored to validate configurations, but you are trying to validate an operation.

Now for transaction hooks: in a remove callback as described in the other post you immediately know that a vrf instance is being deleted - as a result, your code would be much simpler (in particular, no need to open CDB session). But then again, transaction hooks are supposed to serve a bit different role then to validate, so it comes with a price:

  • as mentioned, they are not invoked for mere validations, and I believe they are not invoked for transactions targeting candidate datastore;

  • there is no guarantee that when a callback “validates” the configuration (or the operation), another callback in the same transaction does not make the configuration invalid, e.g. by configuring from-vrf instance.

And then there are prepare-phase subscribers, as mentioned by Conny. I would say they stay somewhere between those two - both in resulting code complexity as well as in other drawbacks. Not sure if there is any reason to pick that instead of a validation callback (or a transaction hook).

1 Like

One more comment: is it possible to rethink the use case? As said, it goes somewhat against YANG and transactionality principles, plus it has some unclear corner cases: for instance, what constitutes invalid “remove” operation - is it valid to remove a vrf instance and in the same transaction add a reference to it? Is it valid if the operations are done in this order, and invalid if done in the opposite order?