diff --git a/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java b/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java index 87a16626d2b..63e9d8025f3 100644 --- a/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java +++ b/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java @@ -188,9 +188,11 @@ public class CommandSetupHelper { public void createVmDataCommand(final VirtualRouter router, final UserVm vm, final NicVO nic, final String publicKey, final Commands cmds) { final String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText(); final String zoneName = _dcDao.findById(router.getDataCenterId()).getName(); + final IPAddressVO staticNatIp = _ipAddressDao.findByVmIdAndNetworkId(nic.getNetworkId(), vm.getId()); cmds.addCommand( "vmdata", - generateVmDataCommand(router, nic.getIPv4Address(), vm.getUserData(), serviceOffering, zoneName, nic.getIPv4Address(), vm.getHostName(), vm.getInstanceName(), + generateVmDataCommand(router, nic.getIPv4Address(), vm.getUserData(), serviceOffering, zoneName, + staticNatIp == null || staticNatIp.getState() != IpAddress.State.Allocated ? null : staticNatIp.getAddress().addr(), vm.getHostName(), vm.getInstanceName(), vm.getId(), vm.getUuid(), publicKey, nic.getNetworkId())); } @@ -1035,7 +1037,7 @@ public class CommandSetupHelper { } private VmDataCommand generateVmDataCommand(final VirtualRouter router, final String vmPrivateIpAddress, final String userData, final String serviceOffering, - final String zoneName, final String guestIpAddress, final String vmName, final String vmInstanceName, final long vmId, final String vmUuid, final String publicKey, + final String zoneName, final String publicIpAddress, final String vmName, final String vmInstanceName, final long vmId, final String vmUuid, final String publicKey, final long guestNetworkId) { final VmDataCommand cmd = new VmDataCommand(vmPrivateIpAddress, vmName, _networkModel.getExecuteInSeqNtwkElmtCmd()); @@ -1049,18 +1051,21 @@ public class CommandSetupHelper { cmd.addVmData("userdata", "user-data", userData); cmd.addVmData("metadata", "service-offering", StringUtils.unicodeEscape(serviceOffering)); cmd.addVmData("metadata", "availability-zone", StringUtils.unicodeEscape(zoneName)); - cmd.addVmData("metadata", "local-ipv4", guestIpAddress); + cmd.addVmData("metadata", "local-ipv4", vmPrivateIpAddress); cmd.addVmData("metadata", "local-hostname", StringUtils.unicodeEscape(vmName)); - if (dcVo.getNetworkType() == NetworkType.Basic) { - cmd.addVmData("metadata", "public-ipv4", guestIpAddress); + + Network network = _networkDao.findById(guestNetworkId); + if (dcVo.getNetworkType() == NetworkType.Basic || network.getGuestType() == Network.GuestType.Shared) { + cmd.addVmData("metadata", "public-ipv4", vmPrivateIpAddress); cmd.addVmData("metadata", "public-hostname", StringUtils.unicodeEscape(vmName)); } else { - if (router.getPublicIpAddress() == null) { - cmd.addVmData("metadata", "public-ipv4", guestIpAddress); - } else { + if (publicIpAddress != null) { + cmd.addVmData("metadata", "public-ipv4", publicIpAddress); + cmd.addVmData("metadata", "public-hostname", publicIpAddress); + } else if (router.getPublicIpAddress() != null) { cmd.addVmData("metadata", "public-ipv4", router.getPublicIpAddress()); + cmd.addVmData("metadata", "public-hostname", router.getPublicIpAddress()); } - cmd.addVmData("metadata", "public-hostname", router.getPublicIpAddress()); } if (vmUuid == null) { cmd.addVmData("metadata", "instance-id", vmInstanceName); diff --git a/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java b/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java index aea24a49ee5..de567749043 100644 --- a/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java @@ -24,6 +24,12 @@ import java.util.Set; import javax.inject.Inject; +import com.cloud.network.element.UserDataServiceProvider; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.vm.NicProfile; +import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.VirtualMachineProfileImpl; import org.apache.cloudstack.api.command.user.firewall.ListPortForwardingRulesCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; @@ -145,6 +151,8 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules LoadBalancerVMMapDao _loadBalancerVMMapDao; @Inject VpcService _vpcSvc; + @Inject + VMTemplateDao _templateDao; protected void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account caller, Boolean ignoreVmState) { if (ipAddress == null || ipAddress.getAllocatedTime() == null || ipAddress.getAllocatedToAccountId() == null) { @@ -597,6 +605,7 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules // enable static nat on the backend s_logger.trace("Enabling static nat for ip address " + ipAddress + " and vm id=" + vmId + " on the backend"); if (applyStaticNatForIp(ipId, false, caller, false)) { + applyUserData(vmId, network, guestNic); performedIpAssoc = false; // ignor unassignIPFromVpcNetwork in finally block return true; } else { @@ -620,6 +629,24 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules return false; } + protected void applyUserData(long vmId, Network network, Nic guestNic) throws ResourceUnavailableException { + UserVmVO vm = _vmDao.findById(vmId); + VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId()); + NicProfile nicProfile = new NicProfile(guestNic, network, null, null, null, + _networkModel.isSecurityGroupSupportedInNetwork(network), + _networkModel.getNetworkTag(template.getHypervisorType(), network)); + VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vm); + UserDataServiceProvider element = _networkModel.getUserDataUpdateProvider(network); + if (element == null) { + s_logger.error("Can't find network element for " + Service.UserData.getName() + " provider needed for UserData update"); + } else { + boolean result = element.saveUserData(network, nicProfile, vmProfile); + if (!result) { + s_logger.error("Failed to update userdata for vm " + vm + " and nic " + guestNic); + } + } + } + protected void isIpReadyForStaticNat(long vmId, IPAddressVO ipAddress, String vmIp, Account caller, long callerUserId) throws NetworkRuleConflictException, ResourceUnavailableException { if (ipAddress.isSourceNat()) { @@ -1096,6 +1123,10 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules revokeStaticNatRuleInternal(rule.getId(), caller, userId, false); } + IPAddressVO ipAddress = _ipAddressDao.findById(ipId); + Long vmId = ipAddress.getAssociatedWithVmId(); + Long networkId = ipAddress.getAssociatedWithNetworkId(); + boolean success = true; // revoke all port forwarding rules @@ -1105,7 +1136,17 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules success = success && applyStaticNatRulesForIp(ipId, _ipAddrMgr.RulesContinueOnError.value(), caller, true); // revoke static nat for the ip address - success = success && applyStaticNatForIp(ipId, false, caller, true); + if (vmId != null && networkId != null) { + Network guestNetwork = _networkModel.getNetwork(networkId); + Nic guestNic = _networkModel.getNicInNetwork(vmId, guestNetwork.getId()); + if (applyStaticNatForIp(ipId, false, caller, true)) { + if (ipAddress.getState() == IpAddress.State.Releasing) { + applyUserData(vmId, guestNetwork, guestNic); + } + } else { + success = false; + } + } // Now we check again in case more rules have been inserted. rules.addAll(_portForwardingDao.listByIpAndNotRevoked(ipId)); @@ -1243,7 +1284,12 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules } } - return disableStaticNat(ipId, caller, ctx.getCallingUserId(), false); + if (disableStaticNat(ipId, caller, ctx.getCallingUserId(), false)) { + Nic guestNic = _networkModel.getNicInNetworkIncludingRemoved(vmId, guestNetwork.getId()); + applyUserData(vmId, guestNetwork, guestNic); + return true; + } + return false; } @Override