Inter-VLAN support in VMware

This commit is contained in:
Kelven Yang 2012-06-28 16:20:40 -07:00
parent 318d2aedbd
commit 738a326dfa
1 changed files with 292 additions and 3 deletions

View File

@ -29,6 +29,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
@ -87,6 +88,8 @@ import com.cloud.agent.api.NetworkUsageCommand;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PingTestCommand;
import com.cloud.agent.api.PlugNicAnswer;
import com.cloud.agent.api.PlugNicCommand;
import com.cloud.agent.api.PoolEjectCommand;
import com.cloud.agent.api.PrepareForMigrationAnswer;
import com.cloud.agent.api.PrepareForMigrationCommand;
@ -95,8 +98,11 @@ import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.RebootAnswer;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.RebootRouterCommand;
import com.cloud.agent.api.SetSourceNatAnswer;
import com.cloud.agent.api.SetupAnswer;
import com.cloud.agent.api.SetupCommand;
import com.cloud.agent.api.SetupGuestNetworkAnswer;
import com.cloud.agent.api.SetupGuestNetworkCommand;
import com.cloud.agent.api.StartAnswer;
import com.cloud.agent.api.StartCommand;
import com.cloud.agent.api.StartupCommand;
@ -105,6 +111,8 @@ import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.StopCommand;
import com.cloud.agent.api.StoragePoolInfo;
import com.cloud.agent.api.UnPlugNicAnswer;
import com.cloud.agent.api.UnPlugNicCommand;
import com.cloud.agent.api.UpgradeSnapshotCommand;
import com.cloud.agent.api.ValidateSnapshotAnswer;
import com.cloud.agent.api.ValidateSnapshotCommand;
@ -114,14 +122,19 @@ import com.cloud.agent.api.check.CheckSshCommand;
import com.cloud.agent.api.routing.DhcpEntryCommand;
import com.cloud.agent.api.routing.IpAssocAnswer;
import com.cloud.agent.api.routing.IpAssocCommand;
import com.cloud.agent.api.routing.IpAssocVpcCommand;
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
import com.cloud.agent.api.routing.SavePasswordCommand;
import com.cloud.agent.api.routing.SetFirewallRulesAnswer;
import com.cloud.agent.api.routing.SetFirewallRulesCommand;
import com.cloud.agent.api.routing.SetNetworkACLAnswer;
import com.cloud.agent.api.routing.SetNetworkACLCommand;
import com.cloud.agent.api.routing.SetPortForwardingRulesAnswer;
import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
import com.cloud.agent.api.routing.SetPortForwardingRulesVpcCommand;
import com.cloud.agent.api.routing.SetSourceNatCommand;
import com.cloud.agent.api.routing.SetStaticNatRulesAnswer;
import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
import com.cloud.agent.api.routing.VmDataCommand;
@ -230,6 +243,9 @@ import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
import com.vmware.vim25.VirtualMachinePowerState;
import com.vmware.vim25.VirtualMachineRuntimeInfo;
import com.vmware.vim25.VirtualSCSISharing;
import com.xensource.xenapi.Connection;
import com.xensource.xenapi.VIF;
import com.xensource.xenapi.VM;
public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService {
private static final Logger s_logger = Logger.getLogger(VmwareResource.class);
@ -409,6 +425,20 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
answer = execute((GetDomRVersionCmd)cmd);
} else if (cmd instanceof CheckNetworkCommand) {
answer = execute((CheckNetworkCommand) cmd);
} else if (cmd instanceof SetupGuestNetworkCommand) {
return execute((SetupGuestNetworkCommand) cmd);
} else if (cmd instanceof PlugNicCommand) {
return execute((PlugNicCommand) cmd);
} else if (cmd instanceof UnPlugNicCommand) {
return execute((UnPlugNicCommand) cmd);
} else if (cmd instanceof IpAssocVpcCommand) {
return execute((IpAssocVpcCommand) cmd);
} else if (cmd instanceof SetSourceNatCommand) {
return execute((SetSourceNatCommand) cmd);
} else if (cmd instanceof SetNetworkACLCommand) {
return execute((SetNetworkACLCommand) cmd);
} else if (cmd instanceof SetPortForwardingRulesVpcCommand) {
return execute((SetPortForwardingRulesVpcCommand) cmd);
} else {
answer = Answer.createUnsupportedCommandAnswer(cmd);
}
@ -704,10 +734,269 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
s_logger.error("Unexpected exception: " + e.toString(), e);
return new Answer(cmd, false, "LoadBalancerConfigCommand failed due to " + VmwareHelper.getExceptionMessage(e));
}
}
}
private int allocRouterEthDeviceIndex(String domrName, String routerIp, NicTO nic) {
// TODO need to figure out which device number to use for the NIC
return 1;
}
private int findRouterEthDeviceIndex(String domrName, String routerIp, NicTO nic) {
// TODO
return 1;
}
private int findRouterEthDeviceIndex(String domrName, String routerIp, IpAddressTO ip) {
// TODO need to find the dev index inside router based on IP address
return 1;
}
private SetupGuestNetworkAnswer execute(SetupGuestNetworkCommand cmd) {
VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
NicTO nic = cmd.getNic();
String routerIp = getRouterSshControlIp(cmd);
String domrGIP = cmd.getAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP);
String domrName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
String gw = cmd.getAccessDetail(NetworkElementCommand.GUEST_NETWORK_GATEWAY);
String cidr = Long.toString(NetUtils.getCidrSize(nic.getNetmask()));;
String domainName = cmd.getNetworkDomain();
String dns = cmd.getDefaultDns1();
if (dns == null || dns.isEmpty()) {
dns = cmd.getDefaultDns2();
} else {
String dns2= cmd.getDefaultDns2();
if ( dns2 != null && !dns2.isEmpty()) {
dns += "," + dns2;
}
}
try {
int ethDeviceNum = allocRouterEthDeviceIndex(domrName, routerIp, nic);
String args = "-C ";
String dev = "eth" + ethDeviceNum;
args += " -d " + dev;
args += " -i " + domrGIP;
args += " -g " + gw;
args += " -m " + cidr;
args += " -n " + NetUtils.getSubNet(domrGIP, nic.getNetmask());
if ( dns != null && !dns.isEmpty() ) {
args += " -s " + dns;
}
if ( domainName != null && !domainName.isEmpty() ) {
args += " -e " + domainName;
}
Pair<Boolean, String> result = SshHelper.sshExecute(routerIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null,
"/opt/cloud/bin/vpc_guestnw.sh " + args);
if (!result.first()) {
String msg = "SetupGuestNetworkCommand on domain router " + routerIp + " failed. message: " + result.second();
s_logger.error(msg);
return new SetupGuestNetworkAnswer(cmd, false, msg);
}
if (s_logger.isInfoEnabled()) {
s_logger.info("SetupGuestNetworkCommand on domain router " + routerIp + " completed");
}
return new SetupGuestNetworkAnswer(cmd, true, "success");
} catch (Exception e) {
String msg = " UnPlug Nic failed due to " + e.toString();
s_logger.warn(msg, e);
return new SetupGuestNetworkAnswer(cmd, false, msg);
}
}
protected IpAssocAnswer execute(IpAssocVpcCommand cmd) {
String[] results = new String[cmd.getIpAddresses().length];
int i = 0;
String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
String routerIp = getRouterSshControlIp(cmd);
try {
IpAddressTO[] ips = cmd.getIpAddresses();
for (IpAddressTO ip : ips) {
assignVPCPublicIpAddress(routerName, routerIp, ip);
results[i++] = ip.getPublicIp() + " - success";
}
} catch (Exception e) {
s_logger.error("Ip Assoc failure on applying one ip due to exception: ", e);
results[i++] = IpAssocAnswer.errorResult;
}
return new IpAssocAnswer(cmd, results);
}
protected SetSourceNatAnswer execute(SetSourceNatCommand cmd) {
VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
String routerIp = getRouterSshControlIp(cmd);
IpAddressTO pubIp = cmd.getIpAddress();
try {
int ethDeviceNum = findRouterEthDeviceIndex(routerName, routerIp, pubIp);
String args = "";
args += " -A ";
args += " -l ";
args += pubIp.getPublicIp();
args += " -c ";
args += "eth" + ethDeviceNum;
Pair<Boolean, String> result = SshHelper.sshExecute(routerIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null,
"/opt/cloud/bin/vpc_snat.sh " + args);
if (!result.first()) {
String msg = "SetupGuestNetworkCommand on domain router " + routerIp + " failed. message: " + result.second();
s_logger.error(msg);
return new SetSourceNatAnswer(cmd, false, msg);
}
return new SetSourceNatAnswer(cmd, true, "success");
} catch (Exception e) {
String msg = "Ip SNAT failure due to " + e.toString();
s_logger.error(msg, e);
return new SetSourceNatAnswer(cmd, false, msg);
}
}
private SetNetworkACLAnswer execute(SetNetworkACLCommand cmd) {
VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
String routerIp = getRouterSshControlIp(cmd);
String[] results = new String[cmd.getRules().length];
try {
String [][] rules = cmd.generateFwRules();
StringBuilder sb = new StringBuilder();
String[] aclRules = rules[0];
if (aclRules.length == 0) {
return new SetNetworkACLAnswer(cmd, true, results);
}
for (int i = 0; i < aclRules.length; i++) {
sb.append(aclRules[i]).append(',');
}
NicTO nic = cmd.getNic();
int ethDeviceNum = findRouterEthDeviceIndex(routerName, routerIp, nic);
String args = "";
args += " -d " + "eth" + ethDeviceNum;
args += " -i " + nic.getIp();
args += " -m " + Long.toString(NetUtils.getCidrSize(nic.getNetmask()));
args += " -a " + sb.toString();
Pair<Boolean, String> result = SshHelper.sshExecute(routerIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null,
"/opt/cloud/bin/vpc_acl.sh " + args);
if (!result.first()) {
String msg = "SetNetworkACLAnswer on domain router " + routerIp + " failed. message: " + result.second();
s_logger.error(msg);
return new SetNetworkACLAnswer(cmd, false, results);
}
return new SetNetworkACLAnswer(cmd, true, results);
} catch (Exception e) {
String msg = "SetNetworkACL failed due to " + e.toString();
s_logger.error(msg, e);
return new SetNetworkACLAnswer(cmd, false, results);
}
}
protected SetPortForwardingRulesAnswer execute(SetPortForwardingRulesVpcCommand cmd) {
VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
String routerIp = getRouterSshControlIp(cmd);
String[] results = new String[cmd.getRules().length];
int i = 0;
boolean endResult = true;
for (PortForwardingRuleTO rule : cmd.getRules()) {
String args ="";
args += rule.revoked() ? " -D" : " -A";
args += " -P " + rule.getProtocol().toLowerCase();
args += " -l " + rule.getSrcIp();
args += " -p " + rule.getStringSrcPortRange().replace(":", "-");
args += " -r " + rule.getDstIp();
args += " -d " + rule.getStringDstPortRange().replace(":", "-");
try {
Pair<Boolean, String> sshResult = SshHelper.sshExecute(routerIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null,
"/opt/cloud/bin/vpc_portforwarding " + args);
if (!sshResult.first()) {
results[i++] = "Failed";
endResult = false;
} else {
results[i++] = null;
}
} catch(Exception e) {
results[i++] = "Failed";
endResult = false;
}
}
return new SetPortForwardingRulesAnswer(cmd, results, endResult);
}
private UnPlugNicAnswer execute(UnPlugNicCommand cmd) {
// TODO
return new UnPlugNicAnswer(cmd, false, "Unsupported yet");
}
private PlugNicAnswer execute(PlugNicCommand cmd) {
// TODO
return new PlugNicAnswer(cmd, false, "Unsupported yet");
}
protected void assignVPCPublicIpAddress(String domrName, String routerIp, IpAddressTO ip) throws Exception {
VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
int ethDeviceNum = this.findRouterEthDeviceIndex(domrName, routerIp, ip);
if (ethDeviceNum < 0) {
throw new InternalErrorException("Failed to find DomR VIF to associate/disassociate IP with.");
}
String args = "";
if (ip.isAdd()) {
args += " -A ";
} else {
args += " -D ";
}
args += " -l ";
args += ip.getPublicIp();
args += " -c ";
args += "eth" + ethDeviceNum;
args += " -g ";
args += ip.getVlanGateway();
args += " -m ";
args += Long.toString(NetUtils.getCidrSize(ip.getVlanNetmask()));
args += " -n ";
args += NetUtils.getSubNet(ip.getPublicIp(), ip.getVlanNetmask());
Pair<Boolean, String> result = SshHelper.sshExecute(routerIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null,
"/opt/cloud/bin/vpc_ipassoc.sh " + args);
if (!result.first()) {
throw new InternalErrorException("Unable to assign public IP address");
}
}
protected void assignPublicIpAddress(VirtualMachineMO vmMo, final String vmName, final String privateIpAddress, final String publicIpAddress, final boolean add, final boolean firstIP,
final boolean sourceNat, final String vlanId, final String vlanGateway, final String vlanNetmask, final String vifMacAddress, String guestIp) throws Exception {
final boolean sourceNat, final String vlanId, final String vlanGateway, final String vlanNetmask, final String vifMacAddress, String guestIp) throws Exception {
String publicNeworkName = HypervisorHostHelper.getPublicNetworkNamePrefix(vlanId);
Pair<Integer, VirtualDevice> publicNicInfo = vmMo.getNicDeviceIndex(publicNeworkName);