CLOUDSTACK-6106 supporting VPC VR on Hyper-V

This commit is contained in:
Rajesh Battala 2014-03-12 07:26:08 +05:30
parent 794b38a789
commit 1b4325d2c8
4 changed files with 158 additions and 33 deletions

View File

@ -21,6 +21,7 @@ public class ModifyVmNicConfigCommand extends Command {
String vmName;
int vlan;
String macAddress;
int index;
protected ModifyVmNicConfigCommand() {
}
@ -30,6 +31,12 @@ public class ModifyVmNicConfigCommand extends Command {
this.macAddress = macAddress;
}
public ModifyVmNicConfigCommand(String vmName, int vlan, int position) {
this.vmName = vmName;
this.vlan = vlan;
this.index = position;
}
public String getVmName() {
return vmName;
}

View File

@ -34,6 +34,7 @@ import com.cloud.storage.dao.GuestOSDao;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.hypervisor.hyperv.manager.HypervManager;
import com.cloud.network.NetworkModel;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
@ -74,16 +75,20 @@ public class HypervGuru extends HypervisorGuruBase implements HypervisorGuru {
if(vm.getVirtualMachine().getType() == VirtualMachine.Type.DomainRouter) {
NicProfile publicNicProfile = null;
NicProfile controlNicProfile = null;
NicProfile profile = null;
for(NicProfile nicProfile : nicProfiles) {
if(nicProfile.getTrafficType() == TrafficType.Public) {
publicNicProfile = nicProfile;
break;
}
else if (nicProfile.getTrafficType() == TrafficType.Control) {
controlNicProfile = nicProfile;
}
}
if(publicNicProfile != null) {
if(publicNicProfile != null || controlNicProfile != null) {
NicTO[] nics = to.getNics();
// reserve extra NICs
NicTO[] expandedNics = new NicTO[MaxNicSupported];
int i = 0;
@ -95,18 +100,27 @@ public class HypervGuru extends HypervisorGuruBase implements HypervisorGuru {
}
deviceId++;
long networkId = publicNicProfile.getNetworkId();
long networkId = 0;
if(publicNicProfile != null ) {
networkId= publicNicProfile.getNetworkId();
profile = publicNicProfile;
}
else {
networkId = controlNicProfile.getNetworkId();
profile = controlNicProfile;
}
NetworkVO network = _networkDao.findById(networkId);
// for Hyperv Hot Nic plug is not supported and it will support upto 8 nics.
// creating the VR with extra nics (actual nics(3) + extra nics) will be 8
for(; i < MaxNicSupported; i++) {
NicTO nicTo = new NicTO();
nicTo.setDeviceId(deviceId++);
nicTo.setBroadcastType(publicNicProfile.getBroadcastType());
nicTo.setType(publicNicProfile.getTrafficType());
nicTo.setBroadcastType(BroadcastDomainType.Vlan);
nicTo.setType(TrafficType.Public);
nicTo.setIp("0.0.0.0");
nicTo.setNetmask("255.255.255.255");
nicTo.setName(publicNicProfile.getName());
nicTo.setName(profile.getName());
try {
String mac = _networkMgr.getNextAvailableMacAddressInNetwork(networkId);
@ -114,16 +128,16 @@ public class HypervGuru extends HypervisorGuruBase implements HypervisorGuru {
} catch (InsufficientAddressCapacityException e) {
throw new CloudRuntimeException("unable to allocate mac address on network: " + networkId);
}
nicTo.setDns1(publicNicProfile.getDns1());
nicTo.setDns2(publicNicProfile.getDns2());
if (publicNicProfile.getGateway() != null) {
nicTo.setDns1(profile.getDns1());
nicTo.setDns2(profile.getDns2());
if (publicNicProfile != null && publicNicProfile.getGateway() != null) {
nicTo.setGateway(publicNicProfile.getGateway());
} else {
nicTo.setGateway(network.getGateway());
}
nicTo.setDefaultNic(false);
nicTo.setBroadcastUri(publicNicProfile.getBroadCastUri());
nicTo.setIsolationuri(publicNicProfile.getIsolationUri());
nicTo.setBroadcastUri(profile.getBroadCastUri());
nicTo.setIsolationuri(profile.getIsolationUri());
Integer networkRate = _networkMgr.getNetworkRate(network.getId(), null);
nicTo.setNetworkRateMbps(networkRate);
@ -137,9 +151,12 @@ public class HypervGuru extends HypervisorGuruBase implements HypervisorGuru {
for(NicTO nicTo : sortNicsByDeviceId(to.getNics())) {
sbMacSequence.append(nicTo.getMac()).append("|");
}
sbMacSequence.deleteCharAt(sbMacSequence.length() - 1);
String bootArgs = to.getBootArgs();
to.setBootArgs(bootArgs + " nic_macs=" + sbMacSequence.toString());
if (!sbMacSequence.toString().isEmpty()) {
sbMacSequence.deleteCharAt(sbMacSequence.length() - 1);
String bootArgs = to.getBootArgs();
to.setBootArgs(bootArgs + " nic_macs=" + sbMacSequence.toString());
}
}

View File

@ -83,10 +83,14 @@ 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.SetupGuestNetworkCommand;
import com.cloud.agent.api.StartCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.UnPlugNicAnswer;
import com.cloud.agent.api.UnPlugNicCommand;
import com.cloud.agent.api.StartupRoutingCommand.VmState;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.UnsupportedAnswer;
@ -172,7 +176,7 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
protected final int _retry = 24;
protected final int _sleep = 10000;
protected static final int DEFAULT_DOMR_SSHPORT = 3922;
private final int maxid = 4094;
private String _clusterGuid;
// Used by initialize to assert object configured before
@ -477,7 +481,12 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
answer = execute((SetStaticRouteCommand) cmd);
} else if (clazz == SetMonitorServiceCommand.class) {
answer = execute((SetMonitorServiceCommand) cmd);
} else {
} else if (clazz == PlugNicCommand.class) {
answer = execute((PlugNicCommand)cmd);
} else if (clazz == UnPlugNicCommand.class) {
answer = execute((UnPlugNicCommand)cmd);
}
else {
if (clazz == StartCommand.class) {
VirtualMachineTO vmSpec = ((StartCommand)cmd).getVirtualMachine();
if (vmSpec.getType() != VirtualMachine.Type.User) {
@ -509,6 +518,59 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
return answer;
}
private PlugNicAnswer execute(PlugNicCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource PlugNicCommand " + s_gson.toJson(cmd));
}
try {
String vmName = cmd.getVmName();
NicTO nic = cmd.getNic();
URI broadcastUri = nic.getBroadcastUri();
if (BroadcastDomainType.getSchemeValue(broadcastUri) != BroadcastDomainType.Vlan) {
throw new InternalErrorException("Unable to assign a public IP to a VIF on network " + nic.getBroadcastUri());
}
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
int publicNicInfo = -1;
publicNicInfo = getVmNics(vmName, maxid);
if (publicNicInfo > 0) {
modifyNicVlan(vmName, vlanId, publicNicInfo);
}
return new PlugNicAnswer(cmd, true, "success");
} catch (Exception e) {
s_logger.error("Unexpected exception: ", e);
return new PlugNicAnswer(cmd, false, "Unable to execute PlugNicCommand due to " + e.toString());
}
}
private UnPlugNicAnswer execute(UnPlugNicCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource UnPlugNicCommand " + s_gson.toJson(cmd));
}
try {
String vmName = cmd.getVmName();
NicTO nic = cmd.getNic();
URI broadcastUri = nic.getBroadcastUri();
if (BroadcastDomainType.getSchemeValue(broadcastUri) != BroadcastDomainType.Vlan) {
throw new InternalErrorException("Unable to unassign a public IP to a VIF on network " + nic.getBroadcastUri());
}
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
int publicNicInfo = -1;
publicNicInfo = getVmNics(vmName, vlanId);
if (publicNicInfo > 0) {
modifyNicVlan(vmName, maxid, publicNicInfo);
}
return new UnPlugNicAnswer(cmd, true, "success");
} catch (Exception e) {
s_logger.error("Unexpected exception: ", e);
return new UnPlugNicAnswer(cmd, false, "Unable to execute unPlugNicCommand due to " + e.toString());
}
}
@Override
public ExecutionResult executeInVR(String routerIP, String script, String args) {
Pair<Boolean, String> result;
@ -621,14 +683,18 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
protected ExecutionResult prepareNetworkElementCommand(SetupGuestNetworkCommand cmd) {
NicTO nic = cmd.getNic();
String routerIp = getRouterSshControlIp(cmd);
String domrName =
cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
try {
int ethDeviceNum = findRouterEthDeviceIndex(domrName, routerIp,
nic.getMac());
nic.setDeviceId(ethDeviceNum);
URI broadcastUri = nic.getBroadcastUri();
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
int ethDeviceNum = getVmNics(domrName, vlanId);
if (ethDeviceNum > 0) {
nic.setDeviceId(ethDeviceNum);
} else {
return new ExecutionResult(false, "Prepare SetupGuestNetwork failed due to unable to find the nic");
}
} catch (Exception e) {
String msg = "Prepare SetupGuestNetwork failed due to " + e.toString();
s_logger.warn(msg, e);
@ -640,23 +706,27 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
private ExecutionResult prepareNetworkElementCommand(IpAssocVpcCommand cmd) {
String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
String routerIp = getRouterSshControlIp(cmd);
try {
IpAddressTO[] ips = cmd.getIpAddresses();
for (IpAddressTO ip : ips) {
int ethDeviceNum = findRouterEthDeviceIndex(routerName, routerIp, ip.getVifMacAddress());
if (ethDeviceNum < 0) {
URI broadcastUri = BroadcastDomainType.fromString(ip.getBroadcastUri());
if (BroadcastDomainType.getSchemeValue(broadcastUri) != BroadcastDomainType.Vlan) {
throw new InternalErrorException("Invalid Broadcast URI " + ip.getBroadcastUri());
}
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
int publicNicInfo = -1;
publicNicInfo = getVmNics(routerName, vlanId);
if (publicNicInfo < 0) {
if (ip.isAdd()) {
throw new InternalErrorException("Failed to find DomR VIF to associate/disassociate IP with.");
} else {
} else {
s_logger.debug("VIF to deassociate IP with does not exist, return success");
continue;
}
}
ip.setNicDevId(ethDeviceNum);
ip.setNicDevId(publicNicInfo);
}
} catch (Exception e) {
s_logger.error("Prepare Ip Assoc failure on applying one ip due to exception: ", e);
@ -668,12 +738,17 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
protected ExecutionResult prepareNetworkElementCommand(SetSourceNatCommand cmd) {
String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
String routerIp = getRouterSshControlIp(cmd);
IpAddressTO pubIp = cmd.getIpAddress();
try {
int ethDeviceNum = findRouterEthDeviceIndex(routerName, routerIp, pubIp.getVifMacAddress());
pubIp.setNicDevId(ethDeviceNum);
String broadcastUri = pubIp.getBroadcastUri();
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
int ethDeviceNum = getVmNics(routerName, vlanId);
if (ethDeviceNum > 0) {
pubIp.setNicDevId(ethDeviceNum);
} else {
return new ExecutionResult(false, "Prepare Ip SNAT failed due to unable to find the nic");
}
} catch (Exception e) {
String msg = "Prepare Ip SNAT failure due to " + e.toString();
s_logger.error(msg, e);
@ -686,12 +761,16 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
NicTO nic = cmd.getNic();
String routerName =
cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
String routerIp = getRouterSshControlIp(cmd);
try {
int ethDeviceNum = findRouterEthDeviceIndex(routerName, routerIp,
nic.getMac());
nic.setDeviceId(ethDeviceNum);
URI broadcastUri = nic.getBroadcastUri();
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
int ethDeviceNum = getVmNics(routerName, vlanId);
if (ethDeviceNum > 0) {
nic.setDeviceId(ethDeviceNum);
} else {
return new ExecutionResult(false, "Prepare SetNetworkACL failed due to unable to find the nic");
}
} catch (Exception e) {
String msg = "Prepare SetNetworkACL failed due to " + e.toString();
s_logger.error(msg, e);
@ -1730,6 +1809,27 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
}
}
protected void modifyNicVlan(String vmName, int vlanId, int pos) {
ModifyVmNicConfigCommand modifynic = new ModifyVmNicConfigCommand(vmName, vlanId, pos);
URI agentUri = null;
try {
String cmdName = ModifyVmNicConfigCommand.class.getName();
agentUri =
new URI("https", null, _agentIp, _port,
"/api/HypervResource/" + cmdName, null, null);
} catch (URISyntaxException e) {
String errMsg = "Could not generate URI for Hyper-V agent";
s_logger.error(errMsg, e);
}
String ansStr = postHttpRequest(s_gson.toJson(modifynic), agentUri);
Answer[] result = s_gson.fromJson(ansStr, Answer[].class);
s_logger.debug("executeRequest received response "
+ s_gson.toJson(result));
if (result.length > 0) {
ModifyVmNicConfigAnswer ans = ((ModifyVmNicConfigAnswer)result[0]);
}
}
protected void assignPublicIpAddress(final String vmName, final String privateIpAddress, final String publicIpAddress, final boolean add, final boolean firstIP,
final boolean sourceNat, final String broadcastId, final String vlanGateway, final String vlanNetmask, final String vifMacAddress) throws Exception {

View File

@ -2289,6 +2289,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
hTypes.add(HypervisorType.KVM);
hTypes.add(HypervisorType.Simulator);
hTypes.add(HypervisorType.LXC);
hTypes.add(HypervisorType.Hyperv);
return hTypes;
}