diff options
author | Justin Pettit <jpettit@nicira.com> | 2009-07-28 22:16:50 -0700 |
---|---|---|
committer | Justin Pettit <jpettit@nicira.com> | 2009-07-28 22:16:50 -0700 |
commit | a5e54d9b6f8002f34cc792df69e6eda68cf95223 (patch) | |
tree | 5667dbde61b4f79f86dd04a5bc1be2c8ea9731bf | |
parent | 4cff83cbad9c0ccd8575a001c7345066a2e6fa00 (diff) | |
parent | 3cdc31a4c3ab312cf41b00845d1316aff181ab1b (diff) |
Merge commit 'origin/citrix'
Conflicts:
configure.ac
-rw-r--r-- | debian/openvswitch-switch-config.templates | 8 | ||||
-rwxr-xr-x | debian/openvswitch-switch.init | 2 | ||||
-rw-r--r-- | debian/openvswitch-switch.template | 4 | ||||
-rw-r--r-- | debian/po/templates.pot | 8 | ||||
-rw-r--r-- | lib/cfg.c | 19 | ||||
-rw-r--r-- | lib/cfg.h | 2 | ||||
-rw-r--r-- | lib/socket-util.c | 21 | ||||
-rw-r--r-- | lib/vconn.c | 8 | ||||
-rw-r--r-- | utilities/ovs-controller.8.in | 19 | ||||
-rw-r--r-- | utilities/ovs-ofctl.8.in | 19 | ||||
-rw-r--r-- | utilities/ovs-openflowd.8.in | 24 | ||||
-rw-r--r-- | vswitchd/bridge.c | 7 | ||||
-rw-r--r-- | vswitchd/ovs-brcompatd.c | 88 | ||||
-rw-r--r-- | vswitchd/ovs-vswitchd.conf.5.in | 33 | ||||
-rwxr-xr-x | xenserver/opt_xensource_libexec_interface-reconfigure | 22 | ||||
-rw-r--r-- | xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py | 23 |
16 files changed, 212 insertions, 95 deletions
diff --git a/debian/openvswitch-switch-config.templates b/debian/openvswitch-switch-config.templates index 16646824..8ea2d5b4 100644 --- a/debian/openvswitch-switch-config.templates +++ b/debian/openvswitch-switch-config.templates @@ -113,16 +113,16 @@ Template: openvswitch-switch/controller-vconn Type: string _Description: Controller location: Specify how the OpenFlow switch should connect to the OpenFlow controller. - The value should be in form "ssl:HOST[:PORT]" to connect to the controller - over SSL (recommended for security) or "tcp:HOST[:PORT]" to connect over + The value should be in form "ssl:IP[:PORT]" to connect to the controller + over SSL (recommended for security) or "tcp:IP[:PORT]" to connect over cleartext TCP. Template: openvswitch-switch/controller-vconn-error Type: error _Description: The controller location is invalid. - The controller location must be specifed as "ssl:HOST[:PORT]" to + The controller location must be specifed as "ssl:IP[:PORT]" to connect to the controller over SSL (recommended for security) or - "tcp:HOST[:PORT]" to connect over cleartext TCP. + "tcp:IP[:PORT]" to connect over cleartext TCP. Template: openvswitch-switch/pki-uri Type: string diff --git a/debian/openvswitch-switch.init b/debian/openvswitch-switch.init index ece07a83..da4ec692 100755 --- a/debian/openvswitch-switch.init +++ b/debian/openvswitch-switch.init @@ -220,7 +220,7 @@ case "$1" in configure_ssl ;; *) - echo "$default: CONTROLLER must be in the form 'ssl:HOST[:PORT]' or 'tcp:HOST[:PORT]' when not in discovery mode" >&2 + echo "$default: CONTROLLER must be in the form 'ssl:IP[:PORT]' or 'tcp:IP[:PORT]' when not in discovery mode" >&2 echo "Run ovs-switch-setup (in the openvswitch-switch-config package) or edit /etc/default/openvswitch-switch to configure" >&2 exit 1 esac diff --git a/debian/openvswitch-switch.template b/debian/openvswitch-switch.template index 0a72198f..f06d4a03 100644 --- a/debian/openvswitch-switch.template +++ b/debian/openvswitch-switch.template @@ -69,8 +69,8 @@ SWITCH_IP=dhcp # CONTROLLER: Location of controller. # One of the following formats: -# tcp:HOST[:PORT] via TCP to PORT (default: 6633) on HOST -# ssl:HOST[:PORT] via SSL to PORT (default: 6633) on HOST +# tcp:IP[:PORT] via TCP to PORT (default: 6633) at IP +# ssl:IP[:PORT] via SSL to PORT (default: 6633) at IP # The default below assumes that the controller is running locally. # This setting has no effect when MODE is set to 'discovery'. #CONTROLLER="tcp:127.0.0.1" diff --git a/debian/po/templates.pot b/debian/po/templates.pot index d425b8a4..abccbc42 100644 --- a/debian/po/templates.pot +++ b/debian/po/templates.pot @@ -278,8 +278,8 @@ msgstr "" #: ../openvswitch-switch-config.templates:10001 msgid "" "Specify how the OpenFlow switch should connect to the OpenFlow controller. " -"The value should be in form \"ssl:HOST[:PORT]\" to connect to the controller " -"over SSL (recommended for security) or \"tcp:HOST[:PORT]\" to connect over " +"The value should be in form \"ssl:IP[:PORT]\" to connect to the controller " +"over SSL (recommended for security) or \"tcp:IP[:PORT]\" to connect over " "cleartext TCP." msgstr "" @@ -293,8 +293,8 @@ msgstr "" #. Description #: ../openvswitch-switch-config.templates:11001 msgid "" -"The controller location must be specifed as \"ssl:HOST[:PORT]\" to connect " -"to the controller over SSL (recommended for security) or \"tcp:HOST[:PORT]\" " +"The controller location must be specifed as \"ssl:IP[:PORT]\" to connect " +"to the controller over SSL (recommended for security) or \"tcp:IP[:PORT]\" " "to connect over cleartext TCP." msgstr "" @@ -676,6 +676,25 @@ cfg_del_match(const char *pattern_, ...) free(pattern); } +/* Fills 'svec' with all of the key-value pairs that match shell glob pattern + * 'pattern'. The caller must first initialize 'svec'. */ +void +cfg_get_matches(struct svec *svec, const char *pattern_, ...) +{ + char *pattern; + char **p; + + FORMAT_KEY(pattern_, pattern); + + for (p = cfg.names; *p; p++) { + if (!fnmatch(pattern, *p, 0)) { + svec_add(svec, *p); + } + } + + free(pattern); +} + /* Fills 'svec' with all of the key-value pairs that have sections that * begin with 'section'. The caller must first initialize 'svec'. */ void @@ -63,6 +63,8 @@ void cfg_add_entry(const char *key, ...) PRINTF_FORMAT(1, 2); void cfg_del_entry(const char *key, ...) PRINTF_FORMAT(1, 2); void cfg_del_section(const char *key, ...) PRINTF_FORMAT(1, 2); void cfg_del_match(const char *pattern, ...) PRINTF_FORMAT(1, 2); +void cfg_get_matches(struct svec *svec, const char *pattern, ...) + PRINTF_FORMAT(2, 3); void cfg_get_section(struct svec *svec, const char *key, ...) PRINTF_FORMAT(2, 3); diff --git a/lib/socket-util.c b/lib/socket-util.c index d5374348..3fcd5a1e 100644 --- a/lib/socket-util.c +++ b/lib/socket-util.c @@ -73,25 +73,16 @@ get_max_fds(void) return max_fds; } -/* Translates 'host_name', which may be a DNS name or an IP address, into a - * numeric IP address in '*addr'. Returns 0 if successful, otherwise a - * positive errno value. */ +/* Translates 'host_name', which must be a string representation of an IP + * address, into a numeric IP address in '*addr'. Returns 0 if successful, + * otherwise a positive errno value. */ int lookup_ip(const char *host_name, struct in_addr *addr) { if (!inet_aton(host_name, addr)) { - struct hostent *he = gethostbyname(host_name); - if (he == NULL) { - struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); - VLOG_ERR_RL(&rl, "gethostbyname(%s): %s", host_name, - (h_errno == HOST_NOT_FOUND ? "host not found" - : h_errno == TRY_AGAIN ? "try again" - : h_errno == NO_RECOVERY ? "non-recoverable error" - : h_errno == NO_ADDRESS ? "no address" - : "unknown error")); - return ENOENT; - } - addr->s_addr = *(uint32_t *) he->h_addr; + struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_ERR_RL(&rl, "\"%s\" is not a valid IP address", host_name); + return ENOENT; } return 0; } diff --git a/lib/vconn.c b/lib/vconn.c index ee2fb0db..32109231 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -128,11 +128,11 @@ vconn_usage(bool active, bool passive, bool bootstrap UNUSED) printf("\n"); if (active) { printf("Active OpenFlow connection methods:\n"); - printf(" tcp:HOST[:PORT] " - "PORT (default: %d) on remote TCP HOST\n", OFP_TCP_PORT); + printf(" tcp:IP[:PORT] " + "PORT (default: %d) at remote IP\n", OFP_TCP_PORT); #ifdef HAVE_OPENSSL - printf(" ssl:HOST[:PORT] " - "SSL PORT (default: %d) on remote HOST\n", OFP_SSL_PORT); + printf(" ssl:IP[:PORT] " + "SSL PORT (default: %d) at remote IP\n", OFP_SSL_PORT); #endif printf(" unix:FILE Unix domain socket named FILE\n"); } diff --git a/utilities/ovs-controller.8.in b/utilities/ovs-controller.8.in index b6b05d07..658cf131 100644 --- a/utilities/ovs-controller.8.in +++ b/utilities/ovs-controller.8.in @@ -38,16 +38,15 @@ to the given \fIip\fR. Listens for connections from OpenFlow switches on the Unix domain server socket named \fIfile\fR. -.TP -\fBssl:\fIhost\fR[\fB:\fIport\fR] -The specified SSL \fIport\fR (default: 6633) on the given remote -\fIhost\fR. The \fB--private-key\fR, \fB--certificate\fR, and -\fB--ca-cert\fR options are mandatory when this form is used. - -.TP -\fBtcp:\fIhost\fR[\fB:\fIport\fR] -The specified TCP \fIport\fR (default: 6633) on the given remote -\fIhost\fR. +.IP "\fBssl:\fIip\fR[\fB:\fIport\fR]" +The specified SSL \fIport\fR (default: 6633) on the host at the given +\fIip\fR, which must be expressed as an IP address (not a DNS name). +The \fB--private-key\fR, \fB--certificate\fR, and \fB--ca-cert\fR +options are mandatory when this form is used. + +.IP "\fBtcp:\fIip\fR[\fB:\fIport\fR]" +The specified TCP \fIport\fR (default: 6633) on the host at the given +\fIip\fR, which must be expressed as an IP address (not a DNS name). .TP \fBunix:\fIfile\fR diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index 0b4856ec..2e2b38b3 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -26,16 +26,15 @@ connecting to an OpenFlow switch. The following connection methods are supported: .RS -.TP -\fBssl:\fIhost\fR[\fB:\fIport\fR] -The specified SSL \fIport\fR (default: 6633) on the given remote -\fIhost\fR. The \fB--private-key\fR, \fB--certificate\fR, and -\fB--ca-cert\fR options are mandatory when this form is used. - -.TP -\fBtcp:\fIhost\fR[\fB:\fIport\fR] -The specified TCP \fIport\fR (default: 6633) on the given remote -\fIhost\fR. +.IP "\fBssl:\fIip\fR[\fB:\fIport\fR]" +The specified SSL \fIport\fR (default: 6633) on the host at the given +\fIip\fR, which must be expressed as an IP address (not a DNS name). +The \fB--private-key\fR, \fB--certificate\fR, and \fB--ca-cert\fR +options are mandatory when this form is used. + +.IP "\fBtcp:\fIip\fR[\fB:\fIport\fR]" +The specified TCP \fIport\fR (default: 6633) on the host at the given +\fIip\fR, which must be expressed as an IP address (not a DNS name). .TP \fBunix:\fIfile\fR diff --git a/utilities/ovs-openflowd.8.in b/utilities/ovs-openflowd.8.in index 3684fab4..4d1a8582 100644 --- a/utilities/ovs-openflowd.8.in +++ b/utilities/ovs-openflowd.8.in @@ -23,16 +23,15 @@ The optional \fIcontroller\fR argument specifies how to connect to the OpenFlow controller. It takes one of the following forms: .RS -.TP -\fBssl:\fIhost\fR[\fB:\fIport\fR] -The specified SSL \fIport\fR (default: 6633) on the given remote -\fIhost\fR. The \fB--private-key\fR, \fB--certificate\fR, and -\fB--ca-cert\fR options are mandatory when this form is used. +.IP "\fBssl:\fIip\fR[\fB:\fIport\fR]" +The specified SSL \fIport\fR (default: 6633) on the host at the given +\fIip\fR, which must be expressed as an IP address (not a DNS name). +The \fB--private-key\fR, \fB--certificate\fR, and \fB--ca-cert\fR +options are mandatory when this form is used. -.TP -\fBtcp:\fIhost\fR[\fB:\fIport\fR] -The specified TCP \fIport\fR (default: 6633) on the given remote -\fIhost\fR. +.IP "\fBtcp:\fIip\fR[\fB:\fIport\fR]" +The specified TCP \fIport\fR (default: 6633) on the host at the given +\fIip\fR, which must be expressed as an IP address (not a DNS name). .TP \fBunix:\fIfile\fR @@ -348,9 +347,10 @@ mode (see \fBContacting the Controller\fR above). When neither option is given, the default is in-band control. .TP -\fB--netflow=\fIhost\fB:\fIport\fR -Configures the given UDP \fIport\fR on the specified IP \fIhost\fR as -a recipient of NetFlow messages for expired flows. +\fB--netflow=\fIip\fB:\fIport\fR +Configures the given UDP \fIport\fR on the specified IP \fIip\fR as +a recipient of NetFlow messages for expired flows. The \fIip\fR must +be specified numerically, not as a DNS name. This option may be specified multiple times to configure additional NetFlow collectors. diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index f977c2b8..cd4fde36 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -793,9 +793,12 @@ bridge_unixctl_fdb_show(struct unixctl_conn *conn, const char *args) if (br->ml) { const struct mac_entry *e; LIST_FOR_EACH (e, struct mac_entry, lru_node, &br->ml->lrus) { + if (e->port < 0 || e->port >= br->n_ports) { + continue; + } ds_put_format(&ds, "%5d %4d "ETH_ADDR_FMT" %3d\n", - e->port, e->vlan, ETH_ADDR_ARGS(e->mac), - mac_entry_age(e)); + br->ports[e->port]->ifaces[0]->dp_ifidx, + e->vlan, ETH_ADDR_ARGS(e->mac), mac_entry_age(e)); } } unixctl_command_reply(conn, 200, ds_cstr(&ds)); diff --git a/vswitchd/ovs-brcompatd.c b/vswitchd/ovs-brcompatd.c index 16fc7866..2384f5ca 100644 --- a/vswitchd/ovs-brcompatd.c +++ b/vswitchd/ovs-brcompatd.c @@ -241,9 +241,14 @@ rewrite_and_reload_config(void) } /* Get all the interfaces for 'bridge' as 'ifaces', breaking bonded interfaces - * down into their constituent parts. */ + * down into their constituent parts. + * + * If 'vlan' < 0, all interfaces on 'bridge' are reported. If 'vlan' == 0, + * then only interfaces for trunk ports or ports with implicit VLAN 0 are + * reported. If 'vlan' > 0, only interfaces with implict VLAN 'vlan' are + * reported. */ static void -get_bridge_ifaces(const char *bridge, struct svec *ifaces) +get_bridge_ifaces(const char *bridge, struct svec *ifaces, int vlan) { struct svec ports; int i; @@ -253,6 +258,15 @@ get_bridge_ifaces(const char *bridge, struct svec *ifaces) cfg_get_all_keys(&ports, "bridge.%s.port", bridge); for (i = 0; i < ports.n; i++) { const char *port_name = ports.names[i]; + if (vlan >= 0) { + int port_vlan = cfg_get_vlan(0, "vlan.%s.tag", port_name); + if (port_vlan < 0) { + port_vlan = 0; + } + if (vlan != port_vlan) { + continue; + } + } if (cfg_has_section("bonding.%s", port_name)) { struct svec slaves; svec_init(&slaves); @@ -288,7 +302,7 @@ prune_ports(void) struct svec ifaces; /* Check that each bridge interface exists. */ - get_bridge_ifaces(br_name, &ifaces); + get_bridge_ifaces(br_name, &ifaces, -1); for (j = 0; j < ifaces.n; j++) { const char *iface_name = ifaces.names[j]; enum netdev_flags flags; @@ -518,6 +532,27 @@ handle_port_cmd(struct ofpbuf *buffer, bool add) return error; } +/* Returns the name of the bridge that contains a port named 'port_name', as a + * malloc'd string that the caller must free, or a null pointer if no bridge + * contains a port named 'port_name'. */ +static char * +get_bridge_containing_port(const char *port_name) +{ + struct svec matches; + const char *start, *end; + + svec_init(&matches); + cfg_get_matches(&matches, "bridge.*.port=%s", port_name); + if (!matches.n) { + return 0; + } + + start = matches.names[0] + strlen("bridge."); + end = strstr(start, ".port="); + assert(end); + return xmemdup0(start, end - start); +} + static int handle_fdb_query_cmd(struct ofpbuf *buffer) { @@ -542,35 +577,65 @@ handle_fdb_query_cmd(struct ofpbuf *buffer) int n_local_macs; int i; + /* Impedance matching between the vswitchd and Linux kernel notions of what + * a bridge is. The kernel only handles a single VLAN per bridge, but + * vswitchd can deal with all the VLANs on a single bridge. We have to + * pretend that the former is the case even though the latter is the + * implementation. */ + const char *linux_bridge; /* Name used by brctl. */ + char *ovs_bridge; /* Name used by ovs-vswitchd. */ + int br_vlan; /* VLAN tag. */ + struct svec ifaces; + struct ofpbuf query_data; char *unixctl_command; uint64_t count, skip; - const char *br_name; - struct svec ifaces; char *output; char *save_ptr; uint32_t seq; int error; /* Parse the command received from brcompat_mod. */ - error = parse_command(buffer, &seq, &br_name, NULL, &count, &skip); + error = parse_command(buffer, &seq, &linux_bridge, NULL, &count, &skip); if (error) { return error; } + /* Figure out vswitchd bridge and VLAN. */ + cfg_read(); + if (bridge_exists(linux_bridge)) { + /* Bridge name is the same. We are interested in VLAN 0. */ + ovs_bridge = xstrdup(linux_bridge); + br_vlan = 0; + } else { + /* No such Open vSwitch bridge 'linux_bridge', but there might be an + * internal port named 'linux_bridge' on some other bridge + * 'ovs_bridge'. If so then we are interested in the VLAN assigned to + * port 'linux_bridge' on the bridge named 'ovs_bridge'. */ + const char *port_name = linux_bridge; + + ovs_bridge = get_bridge_containing_port(port_name); + br_vlan = cfg_get_vlan(0, "vlan.%s.tag", port_name); + if (!ovs_bridge || br_vlan < 0) { + free(ovs_bridge); + send_reply(seq, ENODEV, NULL); + return error; + } + } + /* Fetch the forwarding database using ovs-appctl. */ - unixctl_command = xasprintf("fdb/show %s", br_name); + unixctl_command = xasprintf("fdb/show %s", ovs_bridge); error = execute_appctl_command(unixctl_command, &output); free(unixctl_command); if (error) { + free(ovs_bridge); send_reply(seq, error, NULL); return error; } /* Fetch the MAC address for each interface on the bridge, so that we can * fill in the is_local field in the response. */ - cfg_read(); - get_bridge_ifaces(br_name, &ifaces); + get_bridge_ifaces(ovs_bridge, &ifaces, br_vlan); local_macs = xmalloc(ifaces.n * sizeof *local_macs); n_local_macs = 0; for (i = 0; i < ifaces.n; i++) { @@ -607,6 +672,10 @@ handle_fdb_query_cmd(struct ofpbuf *buffer) continue; } + if (vlan != br_vlan) { + continue; + } + if (skip > 0) { skip--; continue; @@ -635,6 +704,7 @@ handle_fdb_query_cmd(struct ofpbuf *buffer) send_reply(seq, 0, &query_data); ofpbuf_uninit(&query_data); + free(ovs_bridge); return 0; } diff --git a/vswitchd/ovs-vswitchd.conf.5.in b/vswitchd/ovs-vswitchd.conf.5.in index 7599355b..665d3d04 100644 --- a/vswitchd/ovs-vswitchd.conf.5.in +++ b/vswitchd/ovs-vswitchd.conf.5.in @@ -317,8 +317,9 @@ NetFlow is a protocol that exports a number of details about terminating IP flows, such as the principals involved and duration. A bridge may be configured to send NetFlow v5 records to NetFlow collectors when flows end. To enable, define the key \fBnetflow.\fIbridge\fB.host\fR for each -collector in the form \fIhost\fB:\fIport\fR. Records from \fIbridge\fR -will be sent to each \fIhost\fR on UDP \fIport\fR. +collector in the form \fIip\fB:\fIport\fR. Records from \fIbridge\fR +will be sent to each \fIip\fR on UDP \fIport\fR. The \fIip\fR must +be specified numerically, not as a DNS name. The NetFlow messages will use the datapath index for the engine type and id. This can be overridden with the \fBnetflow.\fIbridge\fB.engine-type\fR and @@ -350,16 +351,15 @@ supports the OpenFlow Management Protocol, such as NOX. This functionality is enabled by setting the key \fBmgmt.controller\fR to one of the following values: . -.TP -\fBssl:\fIhost\fR[\fB:\fIport\fR] -The specified SSL \fIport\fR (default: 6633) on the given remote -\fIhost\fR. SSL must be configured when this form is used (see \fBSSL +.IP "\fBssl:\fIip\fR[\fB:\fIport\fR]" +The specified SSL \fIport\fR (default: 6633) on the host at the given +\fIip\fR, which must be expressed as an IP address (not a DNS name). +SSL must be configured when this form is used (see \fBSSL Configuration\fR, below). . -.TP -\fBtcp:\fIhost\fR[\fB:\fIport\fR] -The specified TCP \fIport\fR (default: 6633) on the given remote -\fIhost\fR. +.IP "\fBtcp:\fIip\fR[\fB:\fIport\fR]" +The specified TCP \fIport\fR (default: 6633) on the host at the given +\fIip\fR, which must be expressed as an IP address (not a DNS name). .PP The maximum time between attempts to connect to the controller may be specified in integral seconds with the \fBmgmt.max-backoff\fR key. The @@ -430,15 +430,16 @@ that it receives specifies one or more DNS servers. .RE . .TP -\fBssl:\fIhost\fR[\fB:\fIport\fR] -The specified SSL \fIport\fR (default: 6633) on the given remote -\fIhost\fR. SSL must be configured when this form is used (see \fBSSL +\fBssl:\fIip\fR[\fB:\fIport\fR] +The specified SSL \fIport\fR (default: 6633) on the host at the given +\fIip\fR, which must be expressed as an IP address (not a DNS name). +SSL must be configured when this form is used (see \fBSSL Configuration\fR, below). . .TP -\fBtcp:\fIhost\fR[\fB:\fIport\fR] -The specified TCP \fIport\fR (default: 6633) on the given remote -\fIhost\fR. +\fBtcp:\fIip\fR[\fB:\fIport\fR] +The specified TCP \fIport\fR (default: 6633) on the host at the given +\fIip\fR, which must be expressed as an IP address (not a DNS name). . .TP \fBunix:\fIfile\fR diff --git a/xenserver/opt_xensource_libexec_interface-reconfigure b/xenserver/opt_xensource_libexec_interface-reconfigure index 74f06f8c..2a32fad2 100755 --- a/xenserver/opt_xensource_libexec_interface-reconfigure +++ b/xenserver/opt_xensource_libexec_interface-reconfigure @@ -835,6 +835,15 @@ def action_up(pif): for physdev in physdevs: down_netdev(physdev) + # If we are bringing up a bond, remove IP addresses from the + # slaves (because we are implicitly being asked to take them down). + # + # Conversely, if we are bringing up an interface that has bond + # masters, remove IP addresses from the bond master (because we + # are implicitly being asked to take it down). + for bond_pif in bond_slaves + bond_masters: + run_command(["/sbin/ifconfig", ipdev_name(bond_pif), '0.0.0.0']) + # Remove all keys related to pif and any bond masters linked to PIF. del_ports = [ipdev] + physdevs + bond_masters if vlan_slave and bond_master: @@ -929,6 +938,19 @@ def action_up(pif): # Update /etc/issue (which contains the IP address of the management interface) os.system("/sbin/update-issue") + + if bond_slaves: + # There seems to be a race somewhere: without this sleep, using + # XenCenter to create a bond that becomes the management interface + # fails with "The underlying connection was closed: A connection that + # was expected to be kept alive was closed by the server." on every + # second or third try, even though /var/log/messages doesn't show + # anything unusual. + # + # The race is probably present even without vswitch, but bringing up a + # bond without vswitch involves a built-in pause of 10 seconds or more + # to wait for the bond to transition from learning to forwarding state. + time.sleep(5) def action_down(pif): rec = db.get_pif_record(pif) diff --git a/xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py b/xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py index 45231395..dbd00a45 100644 --- a/xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py +++ b/xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py @@ -32,6 +32,17 @@ class VSwitchService: if self.processname == None: self.processname = name + def version(self): + try: + output = ShellPipe(["service", self.name, "version"]).Stdout() + except StandardError, e: + log.error("version retrieval error: " + str(e)) + return "<unknown>" + for line in output: + if self.processname in line: + return line.split()[-1] + return "<unknown>" + def status(self): try: output = ShellPipe(["service", self.name, "status"]).Stdout() @@ -40,12 +51,12 @@ class VSwitchService: return "<unknown>" if len(output) == 0: return "<unknown>" - for l in output: - if self.processname not in l: + for line in output: + if self.processname not in line: continue - elif "running" in l: + elif "running" in line: return "Running" - elif "stop" in l: + elif "stop" in line: return "Stopped" else: return "<unknown>" @@ -262,8 +273,8 @@ class XSFeatureVSwitch: inPane.NewLine() - versionStr = data.host.other_config({}).get("vSwitchVersion", "<Unknown>") - inPane.AddStatusField(Lang("Version", 20), versionStr) + inPane.AddStatusField(Lang("Version", 20), + VSwitchService.Inst("vswitch", "ovs-vswitchd").version()) inPane.NewLine() |