On 10/5/22 07:30, Han Zhou wrote:
> On Tue, Oct 4, 2022 at 10:27 PM Han Zhou <[email protected]> wrote:
>>
>>
>>
>> On Fri, Sep 30, 2022 at 7:02 AM Dumitru Ceara <[email protected]> wrote:
>>>
>>> Propagate the contents of the NB table to the Southbound.
>>>
>>> Signed-off-by: Dumitru Ceara <[email protected]>
>>> ---
>>> Note:
>>> - ovn-trace doesn't support template variables (yet).
>>> ---
>>> northd/automake.mk | 4 ++
>>> northd/en-northd.c | 4 ++
>>> northd/inc-proc-northd.c | 8 ++++-
>>> northd/northd.c | 41 ++++++++++++++++++++++++
>>> northd/northd.h | 2 +
>>> northd/template-var.c | 77
> ++++++++++++++++++++++++++++++++++++++++++++++
>>> northd/template-var.h | 59 +++++++++++++++++++++++++++++++++++
>>> ovn-nb.ovsschema | 16 ++++++++--
>>> ovn-nb.xml | 34 ++++++++++++++++++++
>>> ovn-sb.ovsschema | 11 +++++--
>>> ovn-sb.xml | 20 ++++++++++++
>>> tests/ovn-northd.at | 32 +++++++++++++++++++
>>> 12 files changed, 300 insertions(+), 8 deletions(-)
>>> create mode 100644 northd/template-var.c
>>> create mode 100644 northd/template-var.h
>>>
>>> diff --git a/northd/automake.mk b/northd/automake.mk
>>> index 81582867d..31134bc32 100644
>>> --- a/northd/automake.mk
>>> +++ b/northd/automake.mk
>>> @@ -13,7 +13,9 @@ northd_ovn_northd_SOURCES = \
>>> northd/inc-proc-northd.c \
>>> northd/inc-proc-northd.h \
>>> northd/ipam.c \
>>> - northd/ipam.h
>>> + northd/ipam.h \
>>> + northd/template-var.c \
>>> + northd/template-var.h
>>> northd_ovn_northd_LDADD = \
>>> lib/libovn.la \
>>> $(OVSDB_LIBDIR)/libovsdb.la \
>>> diff --git a/northd/en-northd.c b/northd/en-northd.c
>>> index 7fe83db64..3a4828ec3 100644
>>> --- a/northd/en-northd.c
>>> +++ b/northd/en-northd.c
>>> @@ -80,6 +80,8 @@ void en_northd_run(struct engine_node *node, void
> *data)
>>> EN_OVSDB_GET(engine_get_input("NB_acl", node));
>>> input_data.nbrec_static_mac_binding_table =
>>> EN_OVSDB_GET(engine_get_input("NB_static_mac_binding", node));
>>> + input_data.nbrec_template_var_table =
>>> + EN_OVSDB_GET(engine_get_input("NB_template_var", node));
>>>
>>> input_data.sbrec_sb_global_table =
>>> EN_OVSDB_GET(engine_get_input("SB_sb_global", node));
>>> @@ -113,6 +115,8 @@ void en_northd_run(struct engine_node *node, void
> *data)
>>> EN_OVSDB_GET(engine_get_input("SB_chassis_private", node));
>>> input_data.sbrec_static_mac_binding_table =
>>> EN_OVSDB_GET(engine_get_input("SB_static_mac_binding", node));
>>> + input_data.sbrec_template_var_table =
>>> + EN_OVSDB_GET(engine_get_input("SB_template_var", node));
>>>
>>> northd_run(&input_data, data,
>>> eng_ctx->ovnnb_idl_txn,
>>> diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
>>> index 54e0ad3b0..e301f6714 100644
>>> --- a/northd/inc-proc-northd.c
>>> +++ b/northd/inc-proc-northd.c
>>> @@ -64,7 +64,8 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_northd);
>>> NB_NODE(ha_chassis_group, "ha_chassis_group") \
>>> NB_NODE(ha_chassis, "ha_chassis") \
>>> NB_NODE(bfd, "bfd") \
>>> - NB_NODE(static_mac_binding, "static_mac_binding")
>>> + NB_NODE(static_mac_binding, "static_mac_binding") \
>>> + NB_NODE(template_var, "template_var")
>>>
>>> enum nb_engine_node {
>>> #define NB_NODE(NAME, NAME_STR) NB_##NAME,
>>> @@ -114,7 +115,8 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_northd);
>>> SB_NODE(load_balancer, "load_balancer") \
>>> SB_NODE(bfd, "bfd") \
>>> SB_NODE(fdb, "fdb") \
>>> - SB_NODE(static_mac_binding, "static_mac_binding")
>>> + SB_NODE(static_mac_binding, "static_mac_binding") \
>>> + SB_NODE(template_var, "template_var")
>>>
>>> enum sb_engine_node {
>>> #define SB_NODE(NAME, NAME_STR) SB_##NAME,
>>> @@ -186,6 +188,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
>>> engine_add_input(&en_northd, &en_nb_ha_chassis_group, NULL);
>>> engine_add_input(&en_northd, &en_nb_ha_chassis, NULL);
>>> engine_add_input(&en_northd, &en_nb_static_mac_binding, NULL);
>>> + engine_add_input(&en_northd, &en_nb_template_var, NULL);
>>>
>>> engine_add_input(&en_northd, &en_sb_sb_global, NULL);
>>> engine_add_input(&en_northd, &en_sb_chassis, NULL);
>>> @@ -215,6 +218,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
>>> engine_add_input(&en_northd, &en_sb_load_balancer, NULL);
>>> engine_add_input(&en_northd, &en_sb_fdb, NULL);
>>> engine_add_input(&en_northd, &en_sb_static_mac_binding, NULL);
>>> + engine_add_input(&en_northd, &en_sb_template_var, NULL);
>>> engine_add_input(&en_mac_binding_aging, &en_nb_nb_global, NULL);
>>> engine_add_input(&en_mac_binding_aging, &en_sb_mac_binding, NULL);
>>> engine_add_input(&en_mac_binding_aging, &en_northd, NULL);
>>> diff --git a/northd/northd.c b/northd/northd.c
>>> index 8500d069d..63879ccd0 100644
>>> --- a/northd/northd.c
>>> +++ b/northd/northd.c
>>> @@ -51,6 +51,7 @@
>>> #include "lib/stopwatch-names.h"
>>> #include "stream.h"
>>> #include "timeval.h"
>>> +#include "template-var.h"
>>> #include "util.h"
>>> #include "uuid.h"
>>> #include "ovs-thread.h"
>>> @@ -15113,6 +15114,44 @@ sync_dns_entries(struct northd_input
> *input_data,
>>> }
>>> hmap_destroy(&dns_map);
>>> }
>>> +
>>> +static void
>>> +sync_template_vars(struct northd_input *input_data,
>>> + struct ovsdb_idl_txn *ovnsb_txn)
>>> +{
>>> + struct template_var_table nb_tvs =
> TEMPLATE_VAR_TABLE_INITIALIZER(&nb_tvs);
>
> Sorry, I forgot to mention one more minor problem:
> My gcc complains:
> ../northd/northd.c:15122:40: error: missing braces around initializer
>
>>> +
>>> + const struct nbrec_template_var *nb_tv;
>>> + const struct sbrec_template_var *sb_tv;
>>> + struct template_var *tv;
>>> +
>>> + NBREC_TEMPLATE_VAR_TABLE_FOR_EACH (
>>> + nb_tv, input_data->nbrec_template_var_table) {
>>> + template_var_insert(&nb_tvs, nb_tv);
>>> + }
>>> +
>>> + SBREC_TEMPLATE_VAR_TABLE_FOR_EACH_SAFE (
>>> + sb_tv, input_data->sbrec_template_var_table) {
>>> + tv = template_var_find(&nb_tvs, sb_tv->name,
> sb_tv->chassis_name);
>>> + if (!tv) {
>>> + sbrec_template_var_delete(sb_tv);
>>> + continue;
>>> + }
>>> + if (strcmp(tv->nb->value, sb_tv->value)) {
>>> + sbrec_template_var_set_value(sb_tv, tv->nb->value);
>>> + }
>>> + template_var_remove(&nb_tvs, tv);
>>> + template_var_destroy(tv);
>>> + }
>>> +
>>> + TEMPLATE_VAR_TABLE_FOR_EACH (tv, &nb_tvs) {
>>> + sb_tv = sbrec_template_var_insert(ovnsb_txn);
>>> + sbrec_template_var_set_name(sb_tv, tv->nb->name);
>>> + sbrec_template_var_set_chassis_name(sb_tv,
> tv->nb->chassis_name);
>>> + sbrec_template_var_set_value(sb_tv, tv->nb->value);
>>> + }
>>> + template_var_table_destroy(&nb_tvs);
>>> +}
>>>
>>> static void
>>> destroy_datapaths_and_ports(struct hmap *datapaths, struct hmap *ports,
>>> @@ -15629,6 +15668,8 @@ ovnnb_db_run(struct northd_input *input_data,
>>> sync_port_groups(input_data, ovnsb_txn, &data->port_groups);
>>> sync_meters(input_data, ovnsb_txn, &data->meter_groups);
>>> sync_dns_entries(input_data, ovnsb_txn, &data->datapaths);
>>> + sync_template_vars(input_data, ovnsb_txn);
>>> +
>>> cleanup_stale_fdb_entries(input_data, &data->datapaths);
>>> stopwatch_stop(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
>>>
>>> diff --git a/northd/northd.h b/northd/northd.h
>>> index 60601803f..254688afa 100644
>>> --- a/northd/northd.h
>>> +++ b/northd/northd.h
>>> @@ -36,6 +36,7 @@ struct northd_input {
>>> const struct nbrec_acl_table *nbrec_acl_table;
>>> const struct nbrec_static_mac_binding_table
>>> *nbrec_static_mac_binding_table;
>>> + const struct nbrec_template_var_table *nbrec_template_var_table;
>>>
>>> /* Southbound table references */
>>> const struct sbrec_sb_global_table *sbrec_sb_global_table;
>>> @@ -55,6 +56,7 @@ struct northd_input {
>>> const struct sbrec_chassis_private_table
> *sbrec_chassis_private_table;
>>> const struct sbrec_static_mac_binding_table
>>> *sbrec_static_mac_binding_table;
>>> + const struct sbrec_template_var_table *sbrec_template_var_table;
>>>
>>> /* Indexes */
>>> struct ovsdb_idl_index *sbrec_chassis_by_name;
>>> diff --git a/northd/template-var.c b/northd/template-var.c
>>> new file mode 100644
>>> index 000000000..8a2d118c3
>>> --- /dev/null
>>> +++ b/northd/template-var.c
>>> @@ -0,0 +1,77 @@
>>> +/* Copyright (c) 2022, Red Hat, Inc.
>>> + *
>>> + * 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.
>>> + */
>>> +
>>> +#include <config.h>
>>> +
>>> +#include "template-var.h"
>>> +
>>> +struct template_var_table *
>>> +template_var_table_create(void)
>>> +{
>>> + struct template_var_table *table = xmalloc(sizeof *table);
>>> +
>>> + hmap_init(&table->vars);
>>> + return table;
>>> +}
>>> +
>>> +void
>>> +template_var_table_destroy(struct template_var_table *table)
>>> +{
>>> + struct template_var *tv;
>>> +
>>> + HMAP_FOR_EACH_POP (tv, hmap_node, &table->vars) {
>>> + template_var_destroy(tv);
>>> + }
>>> + hmap_destroy(&table->vars);
>>> +}
>>> +
>>> +void
>>> +template_var_insert(struct template_var_table *table,
>>> + const struct nbrec_template_var *nbrec_tv)
>>> +{
>>> + struct template_var *tv = xmalloc(sizeof *tv);
>>> + tv->nb = nbrec_tv;
>>> + hmap_insert(&table->vars, &tv->hmap_node,
>>> + template_var_hash(nbrec_tv->name,
> nbrec_tv->chassis_name));
>>> +}
>>> +
>>> +struct template_var *
>>> +template_var_find(struct template_var_table *table,
>>> + const char *name, const char *chassis_name)
>>> +{
>>> + struct template_var *tv;
>>> +
>>> + HMAP_FOR_EACH_WITH_HASH (tv, hmap_node,
>>> + template_var_hash(name, chassis_name),
>>> + &table->vars) {
>>> + if (!strcmp(name, tv->nb->name) &&
>>> + !strcmp(chassis_name, tv->nb->chassis_name)) {
>>> + return tv;
>>> + }
>>> + }
>>> + return NULL;
>>> +}
>>> +
>>> +void
>>> +template_var_remove(struct template_var_table *table, struct
> template_var *tv)
>>> +{
>>> + hmap_remove(&table->vars, &tv->hmap_node);
>>> +}
>>> +
>>> +void
>>> +template_var_destroy(struct template_var *tv)
>>> +{
>>> + free(tv);
>>> +}
>>> diff --git a/northd/template-var.h b/northd/template-var.h
>>> new file mode 100644
>>> index 000000000..42bdbf243
>>> --- /dev/null
>>> +++ b/northd/template-var.h
>>> @@ -0,0 +1,59 @@
>>> +/* Copyright (c) 2022, Red Hat, Inc.
>>> + *
>>> + * 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.
>>> + */
>>> +
>>> +#ifndef OVN_NORTHD_TEMPLATE_VAR_H
>>> +#define OVN_NORTHD_TEMPLATE_VAR_H 1
>>> +
>>> +#include "openvswitch/hmap.h"
>>> +#include "lib/ovn-nb-idl.h"
>>> +
>>> +struct template_var {
>>> + struct hmap_node hmap_node;
>>> +
>>> + const struct nbrec_template_var *nb;
>>> +};
>>> +
>>> +struct template_var_table {
>>> + struct hmap vars;
>>> +};
>>> +
>>> +#define TEMPLATE_VAR_TABLE_INITIALIZER(TBL) \
>>> + HMAP_INITIALIZER(&(TBL)->vars)
>>> +
>>> +#define TEMPLATE_VAR_TABLE_FOR_EACH(NODE, TBL) \
>>> + HMAP_FOR_EACH (NODE, hmap_node, &(TBL)->vars)
>>> +
>>> +struct template_var_table *template_var_table_create(void);
>>> +void template_var_table_destroy(struct template_var_table *table);
>>
>> nit: "table" can be omitted, and same for nbrec_tv and tv, etc. below.
>>
Ack.
>>> +
>>> +static inline uint32_t
>>> +template_var_hash(const char *tv_name, const char *tv_chassis)
>>> +{
>>> + return hash_string(tv_name, hash_string(tv_chassis, 0));
>>> +}
>>> +
>>> +void template_var_insert(struct template_var_table *table,
>>> + const struct nbrec_template_var *nbrec_tv);
>>> +
>>> +struct template_var *
>>> +template_var_find(struct template_var_table *table,
>>> + const char *name, const char *chassis_name);
>>> +
>>> +void template_var_remove(struct template_var_table *table,
>>> + struct template_var *tv);
>>> +
>>> +void template_var_destroy(struct template_var *tv);
>>> +
>>> +#endif /* OVN_NORTHD_TEMPLATE_VAR_H 1 */
>>> diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema
>>> index 174364c8b..f8bded220 100644
>>> --- a/ovn-nb.ovsschema
>>> +++ b/ovn-nb.ovsschema
>>> @@ -1,7 +1,7 @@
>>> {
>>> "name": "OVN_Northbound",
>>> - "version": "6.3.0",
>>> - "cksum": "4042813038 31869",
>>> + "version": "6.4.0",
>>> + "cksum": "169316805 32311",
>>> "tables": {
>>> "NB_Global": {
>>> "columns": {
>>> @@ -620,6 +620,16 @@
>>> "mac": {"type": "string"},
>>> "override_dynamic_mac": {"type": "boolean"}},
>>> "indexes": [["logical_port", "ip"]],
>>> - "isRoot": true}
>>> + "isRoot": true},
>>> + "Template_Var": {
>>
>> As discussed in the RFC review, it would be more clear to name this table
> as Chassis_Template_Var, to reflect the fact that the template
> instantantiation is per chassis. (also avoid confusion if in the future we
> introduce some other types of template).
Oops, sorry about this, I completely forgot. I'll change it in V2.
>>
>>> + "columns": {
>>> + "name": {"type": "string"},
>>> + "value": {"type": {"key": "string"}},
>>> + "chassis_name": {"type": "string"},
>>> + "external_ids": {
>>> + "type": {"key": "string", "value": "string",
>>> + "min": 0, "max": "unlimited"}}},
>>> + "indexes": [["name", "chassis_name"]],
>>> + "isRoot": true}
>>> }
>>> }
>>> diff --git a/ovn-nb.xml b/ovn-nb.xml
>>> index f41e9d7c0..bd28ac372 100644
>>> --- a/ovn-nb.xml
>>> +++ b/ovn-nb.xml
>>> @@ -4436,4 +4436,38 @@
>>> </column>
>>> </group>
>>> </table>
>>> +
>>> + <table name="Template_Var">
>>> + <p>
>>> + Each record represents a template variable instantiation. A
> template
>>> + variable has a <code>name</code> and potentially different
> values on
>>> + different hypervisors in the OVN cluster. The mapping between
>>> + variable names and their actual values is done through the
>>> + <code>value</code> and <code>chassis_name</code> fields. For
> example,
>>> + two rows, <code>R1 = (.name=N, .value=V1,
> .chassis_name=C1)</code> and
>>> + <code>R2 = (.name=N, .value=V2, .chassis_name=C2)</code> will
> make
>>> + <code>ovn-controller</code> running on chassis <code>C1</code>
> and
>>> + <code>C2</code> interpret the token <code>N</code> either as
>>> + <code>V1</code> (on <code>C1</code>) or as <code>V2</code> (on
>>> + <code>C2</code>). Records of type <code>Template_Var</code> are
>>> + indexed by the tuple <code>(name, chassis_name)</code>.
>>
>> We may omit this statement about index, which is already reflected in the
> schema definition.
Sure.
>>
>>> Users can
>>> + refer to template variables within ACL matches and Load_Balancer
> VIP
>>> + and backend definitions.
>>
>> If ACL works, QoS and Logical_Router_Policy should also work. It would be
> better to mention in a more generic way and include Load_Balancer, ACL, QoS
> and Logical_Router_Policy as examples.
Sounds good.
>> In addition, since it is mentioned as official support, I'd also expect
> to see in this series at least one test case other than load-balancer using
> this feature.
That's fair, I'll probably expand the last patch and add more e2e test
cases.
>>
>>> + </p>
>>> + <column name="name">
>>> + The name of the template variable.
>>> + </column>
>>> + <column name="value">
>>> + The value it should exmpand to on the chassis specified by
>>> + <code>chassis_name</code>.
>>> + </column>
>>> + <column name="chassis_name">
>>> + The chassis on which this template variable should be expanded.
>>> + </column>
>>> + <group title="Common Columns">
>>> + <column name="external_ids">
>>> + See <em>External IDs</em> at the beginning of this document.
>>> + </column>
>>> + </group>
>>> + </table>
>>> </database>
>>> diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
>>> index 576ebbdeb..f6cc60d0f 100644
>>> --- a/ovn-sb.ovsschema
>>> +++ b/ovn-sb.ovsschema
>>> @@ -1,7 +1,7 @@
>>> {
>>> "name": "OVN_Southbound",
>>> - "version": "20.25.0",
>>> - "cksum": "53184112 28845",
>>> + "version": "20.26.0",
>>> + "cksum": "4176994634 29127",
>>> "tables": {
>>> "SB_Global": {
>>> "columns": {
>>> @@ -565,6 +565,13 @@
>>> "key": {"type": "uuid",
>>> "refTable":
> "Datapath_Binding"}}}},
>>> "indexes": [["logical_port", "ip"]],
>>> + "isRoot": true},
>>> + "Template_Var": {
>>> + "columns": {
>>> + "name": {"type": "string"},
>>> + "value": {"type": {"key": "string"}},
>>> + "chassis_name": {"type": "string"}},
>>> + "indexes": [["name", "chassis_name"]],
>>> "isRoot": true}
>>> }
>>> }
>>> diff --git a/ovn-sb.xml b/ovn-sb.xml
>>> index 315d60853..a76dba063 100644
>>> --- a/ovn-sb.xml
>>> +++ b/ovn-sb.xml
>>> @@ -4801,4 +4801,24 @@ tcp.flags = RST;
>>> The logical datapath to which the logical router port belongs.
>>> </column>
>>> </table>
>>> +
>>> + <table name="Template_Var">
>>> + <p>
>>> + Each record represents a template variable instantiation and is
> populated
>>> + by <code>ovn-northd</code> from the contents of the
>>> + <code>OVN_Northbound.Template_Var</code> table. Records of type
>>> + <code>Template_Var</code> are indexed by the tuple
>>> + <code>(name, chassis_name)</code>.
>>> + </p>
>>> + <column name="name">
>>> + The name of the template variable.
>>> + </column>
>>> + <column name="value">
>>> + The value it should exmpand to on the chassis specified by
>>
>> s/exmpand/expand
Ack.
>>
>> With the above comments addressed:
>> Acked-by: Han Zhou <[email protected]>
>>
I added your ack but because of the table name change there were quite a
few lines I had to touch. It would be nice if you could have another
glance at this patch when I'll be posting v2.
Thanks,
Dumitru
>>> + <code>chassis_name</code>.
>>> + </column>
>>> + <column name="chassis_name">
>>> + The chassis on which this template variable should be expanded.
>>> + </column>
>>> + </table>
>>> </database>
>>> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
>>> index a210fc575..b6843956c 100644
>>> --- a/tests/ovn-northd.at
>>> +++ b/tests/ovn-northd.at
>>> @@ -7898,3 +7898,35 @@ AT_CHECK([grep "lr_in_arp_resolve" R1flows |
> grep priority=90 | sort], [0], [dnl
>>>
>>> AT_CLEANUP
>>> ])
>>> +
>>> +OVN_FOR_EACH_NORTHD([
>>> +AT_SETUP([NB to SB Template_Var propagation])
>>> +AT_KEYWORDS([templates])
>>> +ovn_start
>>> +
>>> +tv1=$(ovn-nbctl create template_var name="tv" value="v1"
> chassis_name="hv1")
>>> +tv2=$(ovn-nbctl create template_var name="tv" value="v2"
> chassis_name="hv2")
>>> +
>>> +AS_BOX([Ensure values are propagated to SB])
>>> +check ovn-nbctl --wait=sb sync
>>> +check_column "v1" sb:Template_Var value name="tv" chassis_name="hv1"
>>> +check_column "v2" sb:Template_Var value name="tv" chassis_name="hv2"
>>> +
>>> +AS_BOX([Ensure SB is reconciled])
>>> +check ovn-sbctl --all destroy Template_Var
>>> +check ovn-nbctl --wait=sb sync
>>> +check_column "v1" sb:Template_Var value name="tv" chassis_name="hv1"
>>> +check_column "v2" sb:Template_Var value name="tv" chassis_name="hv2"
>>> +
>>> +AS_BOX([Ensure SB is reconciled - deletion])
>>> +check ovn-nbctl destroy template_var $tv1
>>> +check ovn-nbctl --wait=sb sync
>>> +check_column "v2" sb:Template_Var value name="tv" chassis_name="hv2"
>>> +
>>> +AS_BOX([Ensure SB is reconciled - cleanup])
>>> +check ovn-nbctl destroy template_var $tv2
>>> +check ovn-nbctl --wait=sb sync
>>> +check_row_count sb:Template_Var 0
>>> +
>>> +AT_CLEANUP
>>> +])
>>>
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev