Skip to content

Commit 3df8b91

Browse files
committed
add kvm support & LB service
1 parent 9c702ff commit 3df8b91

14 files changed

Lines changed: 1618 additions & 126 deletions

File tree

api/src/com/cloud/event/EventTypes.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,9 @@ public class EventTypes {
400400
public static final String EVENT_EXTERNAL_NVP_CONTROLLER_CONFIGURE = "PHYSICAL.NVPCONTROLLER.CONFIGURE";
401401
public static final String EVENT_EXTERNAL_OVS_CONTROLLER_ADD = "PHYSICAL.OVSCONTROLLER.ADD";
402402
public static final String EVENT_EXTERNAL_OVS_CONTROLLER_DELETE = "PHYSICAL.OVSCONTROLLER.DELETE";
403+
public static final String EVENT_EXTERNAL_ODL_CONTROLLER_ADD = "PHYSICAL.ODLCONTROLLER.ADD";
404+
public static final String EVENT_EXTERNAL_ODL_CONTROLLER_DELETE = "PHYSICAL.ODLCONTROLLER.DELETE";
405+
public static final String EVENT_EXTERNAL_ODL_CONTROLLER_CONFIGURE = "PHYSICAL.ODLCONTROLLER.CONFIGURE";
403406

404407
// AutoScale
405408
public static final String EVENT_COUNTER_CREATE = "COUNTER.CREATE";

api/src/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,11 @@ public class ApiConstants {
412412
// Ovs controller
413413
public static final String OVS_DEVICE_ID = "ovsdeviceid";
414414
public static final String OVS_DEVICE_NAME = "ovsdevicename";
415+
// OpenDaylight controller
416+
public static final String ODL_DEVICE_ID = "odldeviceid";
417+
public static final String ODL_DEVICE_NAME = "odldevicename";
418+
public static final String ODL_TRANSPORT_ZONE_UUID = "transportzoneuuid";
419+
public static final String ODL_GATEWAYSERVICE_UUID = "l3gatewayserviceuuid";
415420

416421
public static final String EXTERNAL_SWITCH_MGMT_DEVICE_ID = "vsmdeviceid";
417422
public static final String EXTERNAL_SWITCH_MGMT_DEVICE_NAME = "vsmdevicename";

client/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@
8585
<artifactId>cloud-plugin-network-nvp</artifactId>
8686
<version>${project.version}</version>
8787
</dependency>
88+
<!--
89+
<dependency>
90+
<groupId>org.apache.cloudstack</groupId>
91+
<artifactId>cloud-plugin-network-odl</artifactId>
92+
<version>${project.version}</version>
93+
</dependency>
94+
-->
8895
<dependency>
8996
<groupId>org.apache.cloudstack</groupId>
9097
<artifactId>cloud-plugin-network-contrail</artifactId>

plugins/hypervisors/kvm/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@
4343
<artifactId>libvirt</artifactId>
4444
<version>${cs.libvirt-java.version}</version>
4545
</dependency>
46+
<dependency>
47+
<groupId>org.apache.cloudstack</groupId>
48+
<artifactId>cloud-plugin-network-ovs</artifactId>
49+
<version>${project.version}</version>
50+
</dependency>
4651
<dependency>
4752
<groupId>com.ceph</groupId>
4853
<artifactId>rados</artifactId>

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

Lines changed: 215 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,13 @@
132132
import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand;
133133
import com.cloud.agent.api.NetworkUsageAnswer;
134134
import com.cloud.agent.api.NetworkUsageCommand;
135+
import com.cloud.agent.api.OvsCreateTunnelAnswer;
136+
import com.cloud.agent.api.OvsCreateTunnelCommand;
137+
import com.cloud.agent.api.OvsDestroyBridgeCommand;
138+
import com.cloud.agent.api.OvsDestroyTunnelCommand;
139+
import com.cloud.agent.api.OvsFetchInterfaceAnswer;
140+
import com.cloud.agent.api.OvsFetchInterfaceCommand;
141+
import com.cloud.agent.api.OvsSetupBridgeCommand;
135142
import com.cloud.agent.api.PingCommand;
136143
import com.cloud.agent.api.PingRoutingCommand;
137144
import com.cloud.agent.api.PingRoutingWithNwGroupsCommand;
@@ -294,6 +301,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
294301
private String _ovsPvlanDhcpHostPath;
295302
private String _ovsPvlanVmPath;
296303
private String _routerProxyPath;
304+
private String _ovsTunnelPath;
297305
private String _host;
298306
private String _dcId;
299307
private String _pod;
@@ -599,6 +607,11 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
599607
throw new ConfigurationException("Unable to find the security_group.py");
600608
}
601609

610+
_ovsTunnelPath = Script.findScript(networkScriptsDir, "ovstunnel.py");
611+
if (_ovsTunnelPath == null) {
612+
throw new ConfigurationException("Unable to find the ovstunnel.py");
613+
}
614+
602615
_routerProxyPath = Script.findScript("scripts/network/domr/", "router_proxy.sh");
603616
if (_routerProxyPath == null) {
604617
throw new ConfigurationException("Unable to find the router_proxy.sh");
@@ -1271,7 +1284,17 @@ public Answer executeRequest(Command cmd) {
12711284
return execute((SetMonitorServiceCommand)cmd);
12721285
} else if (cmd instanceof CheckOnHostCommand) {
12731286
return execute((CheckOnHostCommand)cmd);
1274-
} else {
1287+
} else if (cmd instanceof OvsFetchInterfaceCommand) {
1288+
return execute((OvsFetchInterfaceCommand) cmd);
1289+
} else if (cmd instanceof OvsSetupBridgeCommand) {
1290+
return execute((OvsSetupBridgeCommand) cmd);
1291+
} else if (cmd instanceof OvsDestroyBridgeCommand) {
1292+
return execute((OvsDestroyBridgeCommand) cmd);
1293+
} else if (cmd instanceof OvsCreateTunnelCommand) {
1294+
return execute((OvsCreateTunnelCommand) cmd);
1295+
} else if (cmd instanceof OvsDestroyTunnelCommand) {
1296+
return execute((OvsDestroyTunnelCommand) cmd);
1297+
} else {
12751298
s_logger.warn("Unsupported command ");
12761299
return Answer.createUnsupportedCommandAnswer(cmd);
12771300
}
@@ -1280,6 +1303,188 @@ public Answer executeRequest(Command cmd) {
12801303
}
12811304
}
12821305

1306+
// Tuna added
1307+
private OvsFetchInterfaceAnswer execute(OvsFetchInterfaceCommand cmd) {
1308+
String label = cmd.getLabel();
1309+
s_logger.debug("Will look for network with name-label:" + label);
1310+
try {
1311+
String ipadd = Script.runSimpleBashScript("ifconfig " + label + " | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'");
1312+
String mask = Script.runSimpleBashScript("ifconfig " + label + " | grep 'inet addr:' | cut -d: -f4");
1313+
String mac = Script.runSimpleBashScript("ifconfig " + label + " | grep HWaddr | awk -F \" \" '{print $5}'");
1314+
return new OvsFetchInterfaceAnswer(cmd, true, "Interface " + label
1315+
+ " retrieved successfully", ipadd, mask, mac);
1316+
1317+
} catch (Exception e) {
1318+
s_logger.warn("Caught execption when fetching interface", e);
1319+
return new OvsFetchInterfaceAnswer(cmd, false, "EXCEPTION:"
1320+
+ e.getMessage());
1321+
}
1322+
1323+
}
1324+
1325+
private Answer execute(OvsSetupBridgeCommand cmd) {
1326+
findOrCreateTunnelNetwork(cmd.getKey());
1327+
configureTunnelNetwork(cmd.getNetworkId(), cmd.getHostId(),
1328+
cmd.getKey());
1329+
s_logger.debug("OVS Bridge configured");
1330+
return new Answer(cmd, true, null);
1331+
}
1332+
1333+
private Answer execute(OvsDestroyBridgeCommand cmd) {
1334+
destroyTunnelNetwork(cmd.getKey());
1335+
s_logger.debug("OVS Bridge destroyed");
1336+
return new Answer(cmd, true, null);
1337+
}
1338+
1339+
private synchronized void destroyTunnelNetwork(int key) {
1340+
try {
1341+
findOrCreateTunnelNetwork(key);
1342+
String bridge = "OVSTunnel" + key;
1343+
Script cmd = new Script(_ovsTunnelPath, _timeout, s_logger);
1344+
cmd.add("destroy_ovs_bridge");
1345+
cmd.add("--bridge", bridge);
1346+
String result = cmd.execute();
1347+
String[] res = result.split(":");
1348+
if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) {
1349+
// TODO: Should make this error not fatal?
1350+
// Can Concurrent VM shutdown/migration/reboot events can cause
1351+
// this method
1352+
// to be executed on a bridge which has already been removed?
1353+
throw new CloudRuntimeException("Unable to remove OVS bridge "
1354+
+ bridge + ":" + res);
1355+
}
1356+
return;
1357+
} catch (Exception e) {
1358+
s_logger.warn("destroyTunnelNetwork failed:", e);
1359+
return;
1360+
}
1361+
}
1362+
1363+
private boolean networkExist(String nwName) {
1364+
Script.runSimpleBashScript("ifconfig " + nwName);
1365+
String result = Script.runSimpleBashScript("echo $?");
1366+
return result.equals("0");
1367+
}
1368+
1369+
private synchronized boolean findOrCreateTunnelNetwork(long key) {
1370+
try {
1371+
String nwName = "OVSTunnel" + key;
1372+
if (networkExist(nwName)) {
1373+
return true;
1374+
}
1375+
// if not found, create a new one
1376+
Map<String, String> otherConfig = new HashMap<String, String>();
1377+
otherConfig.put("ovs-host-setup", "");
1378+
Script.runSimpleBashScript("ovs-vsctl -- --may-exist add-br "
1379+
+ nwName + " -- set bridge " + nwName
1380+
+ " other_config:ovs_host_setup=\" \"");
1381+
s_logger.debug("### KVM network for tunnels created:" + nwName);
1382+
} catch (Exception e) {
1383+
s_logger.warn("createTunnelNetwork failed", e);
1384+
}
1385+
return true;
1386+
}
1387+
1388+
private synchronized boolean configureTunnelNetwork(long networkId,
1389+
long hostId, int key) {
1390+
try {
1391+
findOrCreateTunnelNetwork(key);
1392+
String nwName = "OVSTunnel" + key;
1393+
String configuredHosts = Script
1394+
.runSimpleBashScript("ovs-vsctl get bridge " + nwName
1395+
+ " other_config:ovs_host_setup");
1396+
boolean configured = false;
1397+
if (configuredHosts != null) {
1398+
String hostIdsStr[] = configuredHosts.split(",");
1399+
for (String hostIdStr : hostIdsStr) {
1400+
if (hostIdStr.equals(((Long) hostId).toString())) {
1401+
configured = true;
1402+
break;
1403+
}
1404+
}
1405+
}
1406+
if (!configured) {
1407+
Script cmd = new Script(_ovsTunnelPath, _timeout, s_logger);
1408+
cmd.add("setup_ovs_bridge");
1409+
cmd.add("--key", String.valueOf(key));
1410+
cmd.add("--cs_host_id", ((Long) hostId).toString());
1411+
cmd.add("--bridge", nwName);
1412+
String result = cmd.execute();
1413+
String[] res = result.split(":");
1414+
if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) {
1415+
throw new CloudRuntimeException(
1416+
"Unable to pre-configure OVS bridge " + nwName
1417+
+ " for network ID:" + networkId + " - "
1418+
+ res);
1419+
}
1420+
}
1421+
} catch (Exception e) {
1422+
s_logger.warn("createandConfigureTunnelNetwork failed", e);
1423+
return false;
1424+
}
1425+
return true;
1426+
}
1427+
1428+
private OvsCreateTunnelAnswer execute(OvsCreateTunnelCommand cmd) {
1429+
String bridge = "OVSTunnel" + cmd.getKey();
1430+
try {
1431+
if (!findOrCreateTunnelNetwork(cmd.getKey())) {
1432+
s_logger.debug("Error during bridge setup");
1433+
return new OvsCreateTunnelAnswer(cmd, false,
1434+
"Cannot create network", bridge);
1435+
}
1436+
1437+
configureTunnelNetwork(cmd.getNetworkId(), cmd.getFrom(),
1438+
cmd.getKey());
1439+
Script command = new Script(_ovsTunnelPath, _timeout, s_logger);
1440+
command.add("create_tunnel");
1441+
command.add("--bridge", bridge);
1442+
command.add("--remote_ip", cmd.getRemoteIp());
1443+
command.add("--key", cmd.getKey().toString());
1444+
command.add("--src_host", cmd.getFrom().toString());
1445+
command.add("--dst_host", cmd.getTo().toString());
1446+
1447+
String result = command.execute();
1448+
String[] res = result.split(":");
1449+
if (res.length == 2 && res[0].equalsIgnoreCase("SUCCESS")) {
1450+
return new OvsCreateTunnelAnswer(cmd, true, result, res[1],
1451+
bridge);
1452+
} else {
1453+
return new OvsCreateTunnelAnswer(cmd, false, result, bridge);
1454+
}
1455+
} catch (Exception e) {
1456+
s_logger.debug("Error during tunnel setup");
1457+
s_logger.warn("Caught execption when creating ovs tunnel", e);
1458+
return new OvsCreateTunnelAnswer(cmd, false, e.getMessage(), bridge);
1459+
}
1460+
}
1461+
1462+
private Answer execute(OvsDestroyTunnelCommand cmd) {
1463+
try {
1464+
if (!findOrCreateTunnelNetwork(cmd.getKey())) {
1465+
s_logger.warn("Unable to find tunnel network for GRE key:"
1466+
+ cmd.getKey());
1467+
return new Answer(cmd, false, "No network found");
1468+
}
1469+
1470+
String bridge = "OVSTunnel" + cmd.getKey();
1471+
Script command = new Script(_ovsTunnelPath, _timeout, s_logger);
1472+
command.add("destroy_tunnel");
1473+
command.add("--bridge", bridge);
1474+
command.add("--iface_name", cmd.getInPortName());
1475+
String result = command.execute();
1476+
if (result.equalsIgnoreCase("SUCCESS")) {
1477+
return new Answer(cmd, true, result);
1478+
} else {
1479+
return new Answer(cmd, false, result);
1480+
}
1481+
} catch (Exception e) {
1482+
s_logger.warn("caught execption when destroy ovs tunnel", e);
1483+
return new Answer(cmd, false, e.getMessage());
1484+
}
1485+
}
1486+
// end Tuna added
1487+
12831488
private CheckNetworkAnswer execute(CheckNetworkCommand cmd) {
12841489
List<PhysicalNetworkSetupInfo> phyNics = cmd.getPhysicalNetworkInfoList();
12851490
String errMsg = null;
@@ -3025,7 +3230,8 @@ private Answer execute(NetworkUsageCommand cmd) {
30253230
}
30263231
}
30273232

3028-
private Answer execute(RebootCommand cmd) {
3233+
3234+
private Answer execute(RebootCommand cmd) {
30293235

30303236
synchronized (_vms) {
30313237
_vms.put(cmd.getVmName(), State.Starting);
@@ -3106,7 +3312,8 @@ protected GetVmStatsAnswer execute(GetVmStatsCommand cmd) {
31063312
}
31073313
}
31083314

3109-
protected Answer execute(StopCommand cmd) {
3315+
3316+
protected Answer execute(StopCommand cmd) {
31103317
final String vmName = cmd.getVmName();
31113318

31123319
State state = null;
@@ -3422,6 +3629,11 @@ protected StartAnswer execute(StartCommand cmd) {
34223629
}
34233630

34243631
// pass cmdline info to system vms
3632+
// if (vmSpec.getType() != VirtualMachine.Type.User) {
3633+
// passCmdLine(vmName, vmSpec.getBootArgs() );
3634+
// }
3635+
// merge with master branch
3636+
// pass cmdline info to system vms
34253637
if (vmSpec.getType() != VirtualMachine.Type.User) {
34263638
if ((conn.getVersion() < 1001000)) { // CLOUDSTACK-2823: try passCmdLine some times if kernel < 2.6.34 and qemu < 1.1.0 on hypervisor (for instance, CentOS 6.4)
34273639
//wait for 5 minutes at most

0 commit comments

Comments
 (0)