Skip to content

Commit 09fce75

Browse files
OVS/GRE: bug fixes (#5446)
* OVS/GRE: fix failed to fetch cloudbr* info on host * OVS/GRE: move ovstunnel.py to python3 * OVS: add test_privategw_acl_ovs_gre.py for automatic testing (1) VR <-> VM should work (2) Private GW should work * OVS: fix an issue on xenserver ovs bridges are deleted by xenserver/ovs automatically ``` [root@ref-trl-1797-x-M7-wei-zhou-xs2 ~]# grep -r xapi7 /var/log/ |grep del-br /var/log/xensource.log:Sep 15 07:13:44 ref-trl-1797-x-M7-wei-zhou-xs2 xcp-networkd: [ info|localhost|611 |org.xen.xapi.xenops.classic events D:4a3d931cd89f|network_utils] /usr/bin/ovs-vsctl --timeout=20 -- --if-exists del-br xapi7 /var/log/daemon.log:Sep 15 07:13:45 ref-trl-1797-x-M7-wei-zhou-xs2 ovs-vsctl: ovs|00001|vsctl|INFO|Called as /usr/bin/ovs-vsctl --timeout=20 -- --if-exists del-br xapi7 ``` which results that xe network exists but bridge does not exist, and operation stuck for 20 minutes at ``` 2021-09-15 16:06:56 DEBUG [root] #### VMOPS enter create_tunnel #### 2021-09-15 16:06:56 DEBUG [root] Creating tunnel from host 2 to host 1 with GRE key 2116 2021-09-15 16:06:56 DEBUG [root] Executing:['/usr/bin/ovs-vsctl', '--timeout=0', 'wait-until', 'bridge', 'xapi7', '--', 'get', 'bridge', 'xapi7', 'name'] 2021-09-15 16:26:56 DEBUG [root] bridge xapi7 for creating tunnel - VERIFIED 2021-09-15 16:26:56 DEBUG [root] Executing:['/usr/bin/ovs-vsctl', 'add-port', 'xapi7', 't2116-2-1', '--', 'set', 'interface', 't2116-2-1', 'type=gre', 'options:key=2116', 'options:remote_ip=10.0.34.230'] ``` * OVS/GRE: component test test_vpc_distributed_routing_offering.py passes on xenserver * OVS: support Shared network with GRE protocol * update #5446: use lang3.StringUtils * OVS/GRE: VPC with distributed routing on kvm (still not working)
1 parent 4a42e7e commit 09fce75

13 files changed

Lines changed: 808 additions & 61 deletions

File tree

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ env:
8888
smoke/test_portable_publicip
8989
smoke/test_portforwardingrules
9090
smoke/test_privategw_acl
91+
smoke/test_privategw_acl_ovs_gre
9192
smoke/test_projects
9293
smoke/test_public_ip_range"
9394

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1806,7 +1806,7 @@ public synchronized boolean findOrCreateTunnelNetwork(final String nwName) {
18061806
return true;
18071807
}
18081808

1809-
public synchronized boolean configureTunnelNetwork(final long networkId,
1809+
public synchronized boolean configureTunnelNetwork(final Long networkId,
18101810
final long hostId, final String nwName) {
18111811
try {
18121812
final boolean findResult = findOrCreateTunnelNetwork(nwName);

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,8 @@ public InterfaceDef plug(NicTO nic, String guestOsType, String nicAdapter, Map<S
159159
String brName = (trafficLabel != null && !trafficLabel.isEmpty()) ? _pifs.get(trafficLabel) : _pifs.get("private");
160160
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType, nicAdapter), networkRateKBps);
161161
} else if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vswitch) {
162-
String vnetId = Networks.BroadcastDomainType.getValue(nic.getBroadcastUri());
163-
String brName = "OVSTunnel" + vnetId;
164-
s_logger.debug("nic " + nic + " needs to be connected to LogicalSwitch " + brName);
162+
String brName = getOvsTunnelNetworkName(nic.getBroadcastUri().getAuthority());
163+
s_logger.debug("nic " + nic + " needs to be connected to Open vSwitch bridge " + brName);
165164
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType, nicAdapter), networkRateKBps);
166165
} else {
167166
intf.defBridgeNet(_bridges.get("guest"), null, nic.getMac(), getGuestNicModel(guestOsType, nicAdapter), networkRateKBps);
@@ -193,6 +192,19 @@ public InterfaceDef plug(NicTO nic, String guestOsType, String nicAdapter, Map<S
193192
return intf;
194193
}
195194

195+
private String getOvsTunnelNetworkName(final String broadcastUri) {
196+
if (broadcastUri.contains(".")) {
197+
final String[] parts = broadcastUri.split("\\.");
198+
return "OVS-DR-VPC-Bridge" + parts[0];
199+
} else {
200+
try {
201+
return "OVSTunnel" + broadcastUri;
202+
} catch (final Exception e) {
203+
return null;
204+
}
205+
}
206+
}
207+
196208
@Override
197209
public void unplug(InterfaceDef iface, boolean deleteBr) {
198210
// Libvirt apparently takes care of this, see BridgeVifDriver unplug

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtOvsFetchInterfaceCommandWrapper.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package com.cloud.hypervisor.kvm.resource.wrapper;
2121

22+
import org.apache.commons.lang3.StringUtils;
2223
import org.apache.log4j.Logger;
2324

2425
import com.cloud.agent.api.Answer;
@@ -40,9 +41,18 @@ public Answer execute(final OvsFetchInterfaceCommand command, final LibvirtCompu
4041

4142
s_logger.debug("Will look for network with name-label:" + label);
4243
try {
43-
final String ipadd = Script.runSimpleBashScript("ifconfig " + label + " | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'");
44-
final String mask = Script.runSimpleBashScript("ifconfig " + label + " | grep 'inet addr:' | cut -d: -f4");
45-
final String mac = Script.runSimpleBashScript("ifconfig " + label + " | grep HWaddr | awk -F \" \" '{print $5}'");
44+
String ipadd = Script.runSimpleBashScript("ifconfig " + label + " | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'");
45+
if (StringUtils.isEmpty(ipadd)) {
46+
ipadd = Script.runSimpleBashScript("ifconfig " + label + " | grep ' inet ' | awk '{ print $2}'");
47+
}
48+
String mask = Script.runSimpleBashScript("ifconfig " + label + " | grep 'inet addr:' | cut -d: -f4");
49+
if (StringUtils.isEmpty(mask)) {
50+
mask = Script.runSimpleBashScript("ifconfig " + label + " | grep ' inet ' | awk '{ print $4}'");
51+
}
52+
String mac = Script.runSimpleBashScript("ifconfig " + label + " | grep HWaddr | awk -F \" \" '{print $5}'");
53+
if (StringUtils.isEmpty(mac)) {
54+
mac = Script.runSimpleBashScript("ifconfig " + label + " | grep ' ether ' | awk '{ print $2}'");
55+
}
4656
return new OvsFetchInterfaceAnswer(command, true, "Interface " + label
4757
+ " retrieved successfully", ipadd, mask, mac);
4858

plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -884,33 +884,18 @@ public synchronized Network configureTunnelNetwork(final Connection conn, final
884884
// Invoke plugin to setup the bridge which will be used by this
885885
// network
886886
final String bridge = nw.getBridge(conn);
887-
final Map<String, String> nwOtherConfig = nw.getOtherConfig(conn);
888-
final String configuredHosts = nwOtherConfig.get("ovs-host-setup");
889-
boolean configured = false;
890-
if (configuredHosts != null) {
891-
final String hostIdsStr[] = configuredHosts.split(",");
892-
for (final String hostIdStr : hostIdsStr) {
893-
if (hostIdStr.equals(((Long)hostId).toString())) {
894-
configured = true;
895-
break;
896-
}
897-
}
887+
String result;
888+
if (bridgeName.startsWith("OVS-DR-VPC-Bridge")) {
889+
result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge_for_distributed_routing", "bridge", bridge, "key", bridgeName, "xs_nw_uuid", nw.getUuid(conn), "cs_host_id",
890+
((Long)hostId).toString());
891+
} else {
892+
result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge", "bridge", bridge, "key", bridgeName, "xs_nw_uuid", nw.getUuid(conn), "cs_host_id", ((Long)hostId).toString());
898893
}
899894

900-
if (!configured) {
901-
String result;
902-
if (bridgeName.startsWith("OVS-DR-VPC-Bridge")) {
903-
result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge_for_distributed_routing", "bridge", bridge, "key", bridgeName, "xs_nw_uuid", nw.getUuid(conn), "cs_host_id",
904-
((Long)hostId).toString());
905-
} else {
906-
result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge", "bridge", bridge, "key", bridgeName, "xs_nw_uuid", nw.getUuid(conn), "cs_host_id", ((Long)hostId).toString());
907-
}
908-
909-
// Note down the fact that the ovs bridge has been setup
910-
final String[] res = result.split(":");
911-
if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) {
912-
throw new CloudRuntimeException("Unable to pre-configure OVS bridge " + bridge);
913-
}
895+
// Note down the fact that the ovs bridge has been setup
896+
final String[] res = result.split(":");
897+
if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) {
898+
throw new CloudRuntimeException("Unable to pre-configure OVS bridge " + bridge);
914899
}
915900
return nw;
916901
} catch (final Exception e) {

plugins/network-elements/ovs/src/main/java/com/cloud/network/guru/OvsGuestNetworkGuru.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,14 @@ && isMyIsolationMethod(physicalNetwork)
8181
&& _ntwkOfferingSrvcDao.areServicesSupportedByNetworkOffering(
8282
offering.getId(), Service.Connectivity)) {
8383
return true;
84+
} else if (networkType == NetworkType.Advanced
85+
&& offering.getGuestType() == GuestType.Shared
86+
&& _ntwkOfferingSrvcDao.isProviderForNetworkOffering(offering.getId(), Network.Provider.Ovs)
87+
&& physicalNetwork.getIsolationMethods().contains("GRE")) {
88+
return true;
8489
} else {
85-
s_logger.trace("We only take care of Guest networks of type "
86-
+ GuestType.Isolated + " in zone of type "
87-
+ NetworkType.Advanced);
90+
s_logger.trace(String.format("We only take care of Guest networks of type %s with Service %s or type with %s provider %s in %s zone",
91+
GuestType.Isolated, Service.Connectivity, GuestType.Shared, Network.Provider.Ovs, NetworkType.Advanced));
8892
return false;
8993
}
9094
}
@@ -107,6 +111,9 @@ public Network design(NetworkOffering offering, DeploymentPlan plan,
107111
}
108112

109113
config.setBroadcastDomainType(BroadcastDomainType.Vswitch);
114+
if (config.getBroadcastUri() != null) {
115+
config.setBroadcastUri(BroadcastDomainType.Vswitch.toUri(config.getBroadcastUri().toString().replace("vlan://", "")));
116+
}
110117

111118
return config;
112119
}

scripts/vm/hypervisor/xenserver/ovstunnel

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,16 @@ def setup_ovs_bridge(session, args):
106106
"uuid=%s" % xs_nw_uuid,
107107
"param-name=other-config",
108108
"param-key=ovs-host-setup"])
109-
conf_hosts = cs_host_id + (conf_hosts and ',%s' % conf_hosts or '')
110-
lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid,
111-
"other-config:ovs-host-setup=%s" % conf_hosts])
109+
host_found = False
110+
if conf_hosts:
111+
setup_hosts = conf_hosts.split(",")
112+
for host in setup_hosts:
113+
if host == cs_host_id:
114+
host_found = True
115+
if not host_found:
116+
conf_hosts = cs_host_id + (conf_hosts and ',%s' % conf_hosts or '')
117+
lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid,
118+
"other-config:ovs-host-setup=%s" % conf_hosts])
112119

113120
# BLOCK IPv6 - Flow spec changes with ovs version
114121
# Temporarily no need BLOCK IPv6
@@ -161,9 +168,16 @@ def setup_ovs_bridge_for_distributed_routing(session, args):
161168
"uuid=%s" % xs_nw_uuid,
162169
"param-name=other-config",
163170
"param-key=ovs-host-setup"])
164-
conf_hosts = cs_host_id + (conf_hosts and ',%s' % conf_hosts or '')
165-
lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid,
166-
"other-config:ovs-host-setup=%s" % conf_hosts])
171+
host_found = False
172+
if conf_hosts:
173+
setup_hosts = conf_hosts.split(",")
174+
for host in setup_hosts:
175+
if host == cs_host_id:
176+
host_found = True
177+
if not host_found:
178+
conf_hosts = cs_host_id + (conf_hosts and ',%s' % conf_hosts or '')
179+
lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid,
180+
"other-config:ovs-host-setup=%s" % conf_hosts])
167181

168182
# first clear the default rule (rule for 'NORMAL' processing which makes a bridge simple L2 learn & flood switch)
169183
lib.del_flows(bridge, table=0)

scripts/vm/network/vnet/cloudstack_pluginlib.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def do_cmd(cmd):
104104
"%s (stderr output:%s)" % (ret_code, err))
105105
raise PluginError(err)
106106
output = proc.stdout.read()
107-
if output.endswith('\n'):
107+
if output.endswith(b'\n'):
108108
output = output[:-1]
109109
return output
110110

scripts/vm/network/vnet/ovstunnel.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/python
1+
#!/usr/bin/python3
22
# Licensed to the Apache Software Foundation (ASF) under one
33
# or more contributor license agreements. See the NOTICE file
44
# distributed with this work for additional information
@@ -37,7 +37,7 @@ def setup_ovs_bridge(bridge, key, cs_host_id):
3737
res = lib.check_switch()
3838
if res != "SUCCESS":
3939
#return "FAILURE:%s" % res
40-
return 'false'
40+
return 'false'
4141

4242
logging.debug("About to manually create the bridge:%s" % bridge)
4343
#set gre_key to bridge
@@ -50,23 +50,23 @@ def setup_ovs_bridge(bridge, key, cs_host_id):
5050
logging.debug("Bridge has been manually created:%s" % res)
5151
if res:
5252
# result = "FAILURE:%s" % res
53-
result = 'false'
53+
result = 'false'
5454
else:
5555
# Verify the bridge actually exists, with the gre_key properly set
5656
res = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge",
5757
bridge, "other_config:gre_key"])
58-
if key in res:
58+
if key in str(res):
5959
# result = "SUCCESS:%s" % bridge
6060
result = 'true'
6161
else:
6262
# result = "FAILURE:%s" % res
6363
result = 'false'
6464

65-
lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:is-ovs-tun-network=True"])
65+
lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:is-ovs-tun-network=True"])
6666
#get list of hosts using this bridge
6767
conf_hosts = lib.do_cmd([lib.VSCTL_PATH, "get","bridge", bridge,"other_config:ovs-host-setup"])
6868
#add cs_host_id to list of hosts using this bridge
69-
conf_hosts = cs_host_id + (conf_hosts and ',%s' % conf_hosts or '')
69+
conf_hosts = cs_host_id + (conf_hosts and ',%s' % eval(conf_hosts) or '')
7070
lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge,
7171
"other_config:ovs-host-setup=%s" % conf_hosts])
7272

@@ -92,7 +92,7 @@ def setup_ovs_bridge_for_distributed_routing(bridge, cs_host_id):
9292

9393
res = lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:is-ovs_vpc_distributed_vr_network=True"])
9494
conf_hosts = lib.do_cmd([lib.VSCTL_PATH, "get","bridge", bridge,"other:ovs-host-setup"])
95-
conf_hosts = cs_host_id + (conf_hosts and ',%s' % conf_hosts or '')
95+
conf_hosts = cs_host_id + (conf_hosts and ',%s' % eval(conf_hosts) or '')
9696
lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge,
9797
"other_config:ovs-host-setup=%s" % conf_hosts])
9898

@@ -162,7 +162,7 @@ def create_tunnel(bridge, remote_ip, key, src_host, dst_host):
162162
wait = [lib.VSCTL_PATH, "--timeout=30", "wait-until", "bridge",
163163
bridge, "--", "get", "bridge", bridge, "name"]
164164
res = lib.do_cmd(wait)
165-
if bridge not in res:
165+
if bridge not in str(res):
166166
logging.debug("WARNING:Can't find bridge %s for creating " +
167167
"tunnel!" % bridge)
168168
# return "FAILURE:NO_BRIDGE"
@@ -185,7 +185,7 @@ def create_tunnel(bridge, remote_ip, key, src_host, dst_host):
185185
# Expecting python-style list as output
186186
iface_list = []
187187
if len(res) > 2:
188-
iface_list = res.strip()[1:-1].split(',')
188+
iface_list = res.strip()[1:-1].split(b',')
189189
if len(iface_list) != 1:
190190
logging.debug("WARNING: Unexpected output while verifying " +
191191
"port %s on bridge %s" % (name, bridge))
@@ -202,7 +202,7 @@ def create_tunnel(bridge, remote_ip, key, src_host, dst_host):
202202
key_validation = lib.do_cmd(verify_interface_key)
203203
ip_validation = lib.do_cmd(verify_interface_ip)
204204

205-
if not key in key_validation or not remote_ip in ip_validation:
205+
if not key in str(key_validation) or not remote_ip in str(ip_validation):
206206
logging.debug("WARNING: Unexpected output while verifying " +
207207
"interface %s on bridge %s" % (name, bridge))
208208
# return "FAILURE:VERIFY_INTERFACE_FAILED"
@@ -213,12 +213,18 @@ def create_tunnel(bridge, remote_ip, key, src_host, dst_host):
213213
iface_uuid, "ofport"]
214214
tun_ofport = lib.do_cmd(cmd_tun_ofport)
215215
# Ensure no trailing LF
216-
if tun_ofport.endswith('\n'):
216+
if tun_ofport.endswith(b'\n'):
217217
tun_ofport = tun_ofport[:-1]
218218

219-
ovs_tunnel_network = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge, "other_config:is-ovs-tun-network"])
220-
ovs_vpc_distributed_vr_network = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge,
221-
"other_config:is-ovs_vpc_distributed_vr_network"])
219+
try:
220+
ovs_tunnel_network = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge, "other_config:is-ovs-tun-network"])
221+
except:
222+
ovs_tunnel_network = 'False'
223+
try:
224+
ovs_vpc_distributed_vr_network = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge,
225+
"other_config:is-ovs_vpc_distributed_vr_network"])
226+
except:
227+
ovs_vpc_distributed_vr_network = 'False'
222228

223229
if ovs_tunnel_network == 'True':
224230
# add flow entryies for dropping broadcast coming in from gre tunnel

server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,13 @@ && isMyIsolationMethod(physnet)
148148
&& offering.getGuestType() == GuestType.Shared
149149
&& !_ntwkOfferingSrvcDao.isProviderForNetworkOffering(offering.getId(), Network.Provider.NiciraNvp)) {
150150
return true;
151+
} else if (dc.getNetworkType() == NetworkType.Advanced
152+
&& offering.getGuestType() == GuestType.Shared
153+
&& ! _ntwkOfferingSrvcDao.isProviderForNetworkOffering(offering.getId(), Network.Provider.Ovs)
154+
&& physnet.getIsolationMethods().contains("GRE")) {
155+
return true;
151156
} else {
152-
s_logger.trace("We only take care of Guest networks of type " + GuestType.Shared);
157+
s_logger.trace("We only take care of Shared Guest networks without Ovs or NiciraNvp provider");
153158
return false;
154159
}
155160
}

0 commit comments

Comments
 (0)