From patchwork Tue Aug 30 03:12:48 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: nickcooper-zhangtonghao X-Patchwork-Id: 663981 X-Patchwork-Delegate: guru@ovn.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (archives.nicira.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 3sNYW56m0Sz9s5l for ; Tue, 30 Aug 2016 13:13:21 +1000 (AEST) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id E77DC105F8; Mon, 29 Aug 2016 20:13:20 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v3.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 2BDDA105EB for ; Mon, 29 Aug 2016 20:13:20 -0700 (PDT) Received: from bar6.cudamail.com (localhost [127.0.0.1]) by mx3v3.cudamail.com (Postfix) with ESMTPS id B2CFD16190A for ; Mon, 29 Aug 2016 21:13:19 -0600 (MDT) X-ASG-Debug-ID: 1472526795-0b32375d5d0dbb0001-byXFYA Received: from mx3-pf2.cudamail.com ([192.168.14.1]) by bar6.cudamail.com with ESMTP id ZcnNP9wMUbGPIsVY (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 29 Aug 2016 21:13:15 -0600 (MDT) X-Barracuda-Envelope-From: nickcooper-zhangtonghao@opencloud.tech X-Barracuda-RBL-Trusted-Forwarder: 192.168.14.1 Received: from unknown (HELO smtpbgau1.qq.com) (54.206.16.166) by mx3-pf2.cudamail.com with ESMTPS (DHE-RSA-AES256-SHA encrypted); 30 Aug 2016 03:13:14 -0000 Received-SPF: none (mx3-pf2.cudamail.com: domain at opencloud.tech does not designate permitted sender hosts) X-Barracuda-Apparent-Source-IP: 54.206.16.166 X-Barracuda-RBL-IP: 54.206.16.166 X-QQ-mid: bizesmtp14t1472526787tq2bew87 Received: from local.opencloud.tech.localdomai (unknown [106.120.127.11]) by esmtp4.qq.com (ESMTP) with id ; Tue, 30 Aug 2016 11:12:57 +0800 (CST) X-QQ-SSF: 01100000002000F0FFF0B00A0000000 X-QQ-FEAT: oGLsAtV5lZK17waJTSSNbvhdSFcMks8f+OgSg1V3AhN9p7lL029aQCgTyGoe+ 60n/5J7i/A99X6y4xPePaz9WIh5HQb8VOjj2H5V0aqmI4jL61s3w9td3OcwmAEsa76IkD0K BFSsh8JSUCpCToXmac9x3x8iuhrSWkc9qqlAdnZngi2kQveiDQ7CtDYdl0dMn8PiWfnZQEo MuDzG0YzU5szimPta2HbHSpEOiKRyDn8JXOuTyTiRhNdHxJ8oCbsHs28eImctP6OuX+xFqm B/J65JtjPEc/2x X-QQ-GoodBg: 0 X-CudaMail-Envelope-Sender: nickcooper-zhangtonghao@opencloud.tech From: nickcooper-zhangtonghao To: dev@openvswitch.org X-CudaMail-MID: CM-V2-828058541 X-CudaMail-DTE: 082916 X-CudaMail-Originating-IP: 54.206.16.166 Date: Mon, 29 Aug 2016 20:12:48 -0700 X-ASG-Orig-Subj: [##CM-V2-828058541##][PATCH v2] ovn-nbctl: Add LB commands. Message-Id: <1472526768-58481-1-git-send-email-nickcooper-zhangtonghao@opencloud.tech> X-Mailer: git-send-email 1.8.3.1 X-QQ-SENDSIZE: 520 X-QQ-Bgrelay: 1 X-GBUdb-Analysis: 0, 54.206.16.166, Ugly c=0.339637 p=-0.111111 Source Normal X-MessageSniffer-Rules: 0-0-0-28373-c X-Barracuda-Connect: UNKNOWN[192.168.14.1] X-Barracuda-Start-Time: 1472526795 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.10 X-Barracuda-Spam-Status: No, SCORE=1.10 using global scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=4.0 tests=BSF_SC0_MV0713, BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.32446 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC0_MV0713 Custom rule MV0713 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Cc: guru@ovn.org, nickcooper-zhangtonghao Subject: [ovs-dev] [PATCH v2] ovn-nbctl: Add LB commands. X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" 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 --- 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.

+ + 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. + +

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 @@ +

Logical Switch LB Commands

+
+
[--may-exist] lb-add switch lb vip ips [protocol]
+
+ Adds the specified LB to switch. We should assign lb + 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 protocol + must be either tcp or udp. This argument is useful + when a port number is provided as part of the vip. If the protocol + is unspecified and a port number is provided as part of vip, + OVN assumes the protocol to be tcp. It is an error if a load-balancer + named lb already exists, unless --may-exist is specified. + The following example adds a load-balancer with protocol udp: +

+ 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 +

+
+ +
[--if-exists] lb-del switch [lb]
+
+ Deletes LBs from switch. If only + switch is supplied, all the LBs from the logical + switch are deleted. If lb is also specified, + then the lb will be deleted only from the logical switch. + It is an error if lb does not exist, unless --if-exists + is specified. +
+ +
lb-list switch
+
+ Lists the LBs on switch. +
+
+

Logical Switch Port Commands

[--may-exist] lsp-add switch port
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\(])