Add a name column for the load balancer. This must be unique among all load balancers. This name has no special meaning or purpose other than to provide convenience for human interaction with the ovn-nb database. This patch provides the command line to create load-balancer and add the unit tests.
Signed-off-by: nickcooper-zhangtonghao <nickcooper-zhangtong...@opencloud.tech> --- ovn/ovn-nb.ovsschema | 5 +- ovn/ovn-nb.xml | 6 ++ ovn/utilities/ovn-nbctl.8.xml | 35 +++++++++ ovn/utilities/ovn-nbctl.c | 163 +++++++++++++++++++++++++++++++++++++++++- tests/ovn-nbctl.at | 44 ++++++++++++ tests/system-ovn.at | 13 ++-- 6 files changed, 255 insertions(+), 11 deletions(-) diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema index 456ae98..87ce15f 100644 --- a/ovn/ovn-nb.ovsschema +++ b/ovn/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", "version": "5.3.1", - "cksum": "1921908091 9353", + "cksum": "360001470 9398", "tables": { "NB_Global": { "columns": { @@ -92,6 +92,7 @@ "isRoot": true}, "Load_Balancer": { "columns": { + "name": {"type": "string"}, "vips": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, @@ -102,7 +103,7 @@ "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, - "isRoot": true}, + "isRoot": false}, "ACL": { "columns": { "priority": {"type": {"key": {"type": "integer", diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml index 5719e74..c3666f5 100644 --- a/ovn/ovn-nb.xml +++ b/ovn/ovn-nb.xml @@ -660,6 +660,12 @@ Each row represents one load balancer. </p> + <column name="name"> + A name for the load balancer. This must be unique among all load balancers. + This name has no special meaning or purpose other than to provide convenience + for human interaction with the ovn-nb database. + </column> + <column name="vips"> <p> A map of virtual IPv4 addresses (and an optional port number with diff --git a/ovn/utilities/ovn-nbctl.8.xml b/ovn/utilities/ovn-nbctl.8.xml index d44f039..fa908b7 100644 --- a/ovn/utilities/ovn-nbctl.8.xml +++ b/ovn/utilities/ovn-nbctl.8.xml @@ -102,6 +102,41 @@ </dd> </dl> + <h1>Logical Switch LB Commands</h1> + <dl> + <dt>[<code>--may-exist</code>] <code>lb-add</code> <var>switch</var> <var>lb</var> <var>vip</var> <var>ips</var> [<var>protocol</var>]</dt> + <dd> + Adds the specified LB to <var>switch</var>. We should assign <var>lb</var> + a virtual IPv4 address (and an optional port number with : as a separator) + and the corresponding endpoint IPv4 addresses (and optional port numbers + with : as separators) separated by commas. The optional argument <var>protocol</var> + must be either <code>tcp</code> or <code>udp</code>. This argument is useful + when a port number is provided as part of the <var>vip</var>. If the <var>protocol</var> + is unspecified and a port number is provided as part of <var>vip</var>, + OVN assumes the <var>protocol</var> to be <code>tcp</code>. It is an error if a load-balancer + named <var>lb</var> already exists, unless <code>--may-exist</code> is specified. + The following example adds a load-balancer with <var>protocol</var> <code>udp</code>: + <p> + <code>lb-add ls0 lb0 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80,192.168.10.30:80 udp</code> + </p> + </dd> + + <dt>[<code>--if-exists</code>] <code>lb-del</code> <var>switch</var> [<var>lb</var>]</dt> + <dd> + Deletes LBs from <var>switch</var>. If only + <var>switch</var> is supplied, all the LBs from the logical + switch are deleted. If <var>lb</var> is also specified, + then the <var>lb</var> will be deleted only from the logical switch. + It is an error if <var>lb</var> does not exist, unless <code>--if-exists</code> + is specified. + </dd> + + <dt><code>lb-list</code> <var>switch</var></dt> + <dd> + Lists the LBs on <var>switch</var>. + </dd> + </dl> + <h1>Logical Switch Port Commands</h1> <dl> <dt>[<code>--may-exist</code>] <code>lsp-add</code> <var>switch</var> <var>port</var></dt> diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c index d6d64ea..fc02918 100644 --- a/ovn/utilities/ovn-nbctl.c +++ b/ovn/utilities/ovn-nbctl.c @@ -331,6 +331,13 @@ ACL commands:\n\ remove ACLs from SWITCH\n\ acl-list SWITCH print ACLs for SWITCH\n\ \n\ +LB commands:\n\ + lb-add SWITCH LB VIP[:PORT] IP[:PORT]... [PROTOCOL]\n\ + add a load-balancer to SWITCH\n\ + lb-del SWITCH [LB]\n\ + remove load-balancers from SWITCH\n\ + lb-list SWITCH [LB] print load-balancers for SWITCH\n\ +\n\ Logical switch port commands:\n\ lsp-add SWITCH PORT add logical port PORT on SWITCH\n\ lsp-add SWITCH PORT PARENT TAG\n\ @@ -1315,7 +1322,154 @@ nbctl_acl_del(struct ctl_context *ctx) } } } - + +static void +nbctl_lb_add(struct ctl_context *ctx) +{ + const struct nbrec_logical_switch *ls; + const char *lb_name = ctx->argv[2]; + const char *lb_vip = ctx->argv[3]; + const char *lb_ips = ctx->argv[4]; + + ls = ls_by_name_or_uuid(ctx, ctx->argv[1], true); + + const char *lb_proto; + if (ctx->argc == 5) { + /* default protocol.*/ + lb_proto = "tcp"; + } else { + lb_proto = ctx->argv[5]; + /* Validate protocol. */ + if (strcmp(lb_proto, "tcp") && strcmp(lb_proto, "udp")) { + ctl_fatal("%s: protocol must be one of \"tcp\", \"udp\".", lb_proto); + } + } + + bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL; + for (int i = 0; i < ls->n_load_balancer; i++) { + const struct nbrec_load_balancer *lb + = ls->load_balancer[i]; + + if (strcmp(lb->name, lb_name)) { + continue; + } + + if (!may_exist) { + ctl_fatal("%s: a load balancer with this name already exists", lb_name); + } + + nbrec_logical_switch_verify_load_balancer(ls); + nbrec_load_balancer_verify_protocol(lb); + nbrec_load_balancer_verify_vips(lb); + nbrec_load_balancer_set_protocol(lb, lb_proto); + + struct smap vips = SMAP_INITIALIZER(&vips); + smap_add(&vips, lb_vip, lb_ips); + nbrec_load_balancer_set_vips(lb, &vips); + smap_destroy(&vips); + + return; + } + + /* Create the load balancer. */ + struct nbrec_load_balancer *lb = nbrec_load_balancer_insert(ctx->txn); + nbrec_load_balancer_set_name(lb, lb_name); + nbrec_load_balancer_set_protocol(lb, lb_proto); + + struct smap vips = SMAP_INITIALIZER(&vips); + smap_add(&vips, lb_vip, lb_ips); + nbrec_load_balancer_set_vips(lb, &vips); + smap_destroy(&vips); + + /* Insert the load balancer into the logical switch. */ + nbrec_logical_switch_verify_acls(ls); + struct nbrec_load_balancer **new_lbs + = xmalloc(sizeof *new_lbs * (ls->n_load_balancer + 1)); + + memcpy(new_lbs, ls->load_balancer, sizeof *new_lbs * ls->n_load_balancer); + new_lbs[ls->n_load_balancer] = lb; + nbrec_logical_switch_set_load_balancer(ls, new_lbs, ls->n_load_balancer + 1); + free(new_lbs); +} + +static void +nbctl_lb_del(struct ctl_context *ctx) +{ + const char *lb_name = ctx->argv[2]; + const struct nbrec_logical_switch *ls; + ls = ls_by_name_or_uuid(ctx, ctx->argv[1], true); + + if (ctx->argc == 2) { + /* If load-balancer is not specified, delete + * all load-balancers. */ + nbrec_logical_switch_verify_load_balancer(ls); + nbrec_logical_switch_set_load_balancer(ls, NULL, 0); + return; + } + + for (size_t i = 0; i < ls->n_load_balancer; i++) { + const struct nbrec_load_balancer *lb + = ls->load_balancer[i]; + + if (strcmp(lb->name, lb_name)) { + continue; + } + + /* Remove the matching rule. */ + struct nbrec_load_balancer **new_lbs + = xmemdup(ls->load_balancer, sizeof *new_lbs * ls->n_load_balancer); + new_lbs[i] = ls->load_balancer[ls->n_load_balancer - 1]; + nbrec_logical_switch_verify_load_balancer(ls); + nbrec_logical_switch_set_load_balancer(ls, new_lbs, + ls->n_load_balancer - 1); + free(new_lbs); + return; + } + + bool must_exist = !shash_find(&ctx->options, "--if-exists"); + if (must_exist) { + ctl_fatal("load balancer %s is not part of any logical switch.", + lb_name); + } +} + +static void +nbctl_lb_list(struct ctl_context *ctx) +{ + const struct nbrec_logical_switch *ls; + + ls = ls_by_name_or_uuid(ctx, ctx->argv[1], true); + + struct smap lbs = SMAP_INITIALIZER(&lbs); + for (int i = 0; i < ls->n_load_balancer; i++) { + const struct nbrec_load_balancer *lb + = ls->load_balancer[i]; + if (ctx->argc == 3 && strcmp(lb->name, ctx->argv[2])) { + continue; + } + + const struct smap_node **nodes = smap_sort(&lb->vips); + if (nodes) { + const struct smap_node *node = nodes[0]; + smap_add_format(&lbs, lb->name, "%-10.8s %-5s %-20s %s", + lb->name, lb->protocol, node->key, node->value); + free(nodes); + } + } + + const struct smap_node **nodes = smap_sort(&lbs); + ds_put_format(&ctx->output, + "Logical Switch: %s\n" + "%-10.8s %-5s %-20s IPs\n", + ls->name, "LB", "PROTO", "VIP"); + for (size_t i = 0; i < smap_count(&lbs); i++) { + const struct smap_node *node = nodes[i]; + ds_put_format(&ctx->output, "%s\n", node->value); + } + smap_destroy(&lbs); + free(nodes); +} + static void nbctl_lr_add(struct ctl_context *ctx) { @@ -2420,6 +2574,13 @@ static const struct ctl_command_syntax nbctl_commands[] = { nbctl_acl_del, NULL, "", RW }, { "acl-list", 1, 1, "SWITCH", NULL, nbctl_acl_list, NULL, "", RO }, + /* load balancer commands. */ + { "lb-add", 4, 5, "SWITCH LB VIP[:PORT] IP[:PORT]... [PROTOCOL]", NULL, + nbctl_lb_add, NULL, "--may-exist", RW }, + { "lb-del", 1, 2, "SWITCH [LB]", NULL, + nbctl_lb_del, NULL, "--if-exists", RW }, + { "lb-list", 1, 2, "SWITCH [LB]", NULL, nbctl_lb_list, NULL, "", RO }, + /* logical switch port commands. */ { "lsp-add", 2, 4, "SWITCH PORT [PARENT] [TAG]", NULL, nbctl_lsp_add, NULL, "--may-exist", RW }, diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at index 5357ced..3ea246e 100644 --- a/tests/ovn-nbctl.at +++ b/tests/ovn-nbctl.at @@ -239,6 +239,50 @@ AT_CLEANUP dnl --------------------------------------------------------------------- +AT_SETUP([ovn-nbctl - LBs]) +OVN_NBCTL_TEST_START + +AT_CHECK([ovn-nbctl ls-add ls0]) +AT_CHECK([ovn-nbctl lb-add ls0 lb0 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80]) +AT_CHECK([ovn-nbctl lb-add ls0 lb1 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80 tcp]) +AT_CHECK([ovn-nbctl lb-add ls0 lb2 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80 udp]) + +AT_CHECK([ovn-nbctl lb-list ls0], [0], [dnl +Logical Switch: ls0 +LB PROTO VIP IPs +lb0 tcp 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80 +lb1 tcp 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80 +lb2 udp 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80 +]) + +dnl List a load-balancer. +AT_CHECK([ovn-nbctl lb-list ls0 lb0], [0], [dnl +Logical Switch: ls0 +LB PROTO VIP IPs +lb0 tcp 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80 +]) + +dnl Delete a load-balancer. +AT_CHECK([ovn-nbctl lb-del ls0 lb0]) +AT_CHECK([ovn-nbctl lb-list ls0], [0], [dnl +Logical Switch: ls0 +LB PROTO VIP IPs +lb1 tcp 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80 +lb2 udp 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80 +]) + +dnl Delete all load-balancers. +AT_CHECK([ovn-nbctl lb-del ls0]) +AT_CHECK([ovn-nbctl lb-list ls0], [0], [dnl +Logical Switch: ls0 +LB PROTO VIP IPs +]) + +OVN_NBCTL_TEST_STOP +AT_CLEANUP + +dnl --------------------------------------------------------------------- + AT_SETUP([ovn-nbctl - basic logical router commands]) OVN_NBCTL_TEST_START diff --git a/tests/system-ovn.at b/tests/system-ovn.at index e267384..109be85 100755 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -348,15 +348,13 @@ ovn-nbctl lsp-add bar bar3 \ -- lsp-set-addresses bar3 "f0:00:0f:01:02:05 172.16.1.4" # Config OVN load-balancer with a VIP. -uuid=`ovn-nbctl create load_balancer vips:30.0.0.1="172.16.1.2,172.16.1.3,172.16.1.4"` -ovn-nbctl set logical_switch foo load_balancer=$uuid +ovn-nbctl lb-add foo lb0 30.0.0.1 172.16.1.2,172.16.1.3,172.16.1.4 # Create another load-balancer with another VIP. -uuid=`ovn-nbctl create load_balancer vips:30.0.0.3="172.16.1.2,172.16.1.3,172.16.1.4"` -ovn-nbctl add logical_switch foo load_balancer $uuid +ovn-nbctl lb-add foo lb1 30.0.0.3 172.16.1.2,172.16.1.3,172.16.1.4 # Config OVN load-balancer with another VIP (this time with ports). -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"172.16.1.2:80,172.16.1.3:80,172.16.1.4:80"' +ovn-nbctl lb-add foo lb2 30.0.0.2:8000 172.16.1.2:80,172.16.1.3:80,172.16.1.4:80 # Wait for ovn-controller to catch up. OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | grep ct\(]) @@ -468,11 +466,10 @@ for i in `seq 1 4`; do done # Config OVN load-balancer with a VIP. -uuid=`ovn-nbctl create load_balancer vips:30.0.0.1="192.168.1.3,192.168.1.4,192.168.1.5"` -ovn-nbctl set logical_switch foo load_balancer=$uuid +ovn-nbctl lb-add foo lb0 30.0.0.1 192.168.1.3,192.168.1.4,192.168.1.5 # Config OVN load-balancer with another VIP (this time with ports). -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"192.168.1.3:80,192.168.1.4:80,192.168.1.5:80"' +ovn-nbctl lb-add foo lb1 30.0.0.2:8000 192.168.1.3:80,192.168.1.4:80,192.168.1.5:80 # Wait for ovn-controller to catch up. OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | grep ct\(]) -- 1.8.3.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev