This is an automated email from the ASF dual-hosted git repository.

andrijapanic pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/master by this push:
     new 9c6b02f  Userdata to display static NAT as public ip instead of VR ip 
(#3862)
9c6b02f is described below

commit 9c6b02fd8b2282ceb80a1b9205871a4e93a00682
Author: Andrija Panic <[email protected]>
AuthorDate: Thu Mar 5 12:49:17 2020 +0100

    Userdata to display static NAT as public ip instead of VR ip (#3862)
    
    * Userdata to display static NAT as public ip instead of VR ip
    
    If static nat is enabled on VM then metadata service should return
    the static nat instead of gateway IP.
    If static not is not enabled then it should return the gateway IP
    as the public IP
    
    Test results:
    
    Step to reproduce:
    
    1. Create a vm
    2. Ssh to vm.
    3. Run the below command inside the vm
    wget http://<VR public ip>/latest/meta-data/public-ipv4
    
    Note down the output of the above command
    4. Now acquire a new public and enable static NAT on that IP to this vm
    5. Now run the same command mentioned above in the VM
    This should display the static NAT ip instead of VR public IP
    
    Output:
    
    Before enabling static nat
    
    wget http://10.10.10.40/latest/meta-data/public-ipv4
    $ cat public-ipv4
    10.10.10.29
    
    After enabling static nat
    
    wget http://10.10.10.40/latest/meta-data/public-ipv4
    $ cat public-ipv4
    10.11.10.30
    
    * server: apply vm user data when release a public ip
    
    Co-authored-by: Wei Zhou <[email protected]>
---
 .../cloud/network/router/CommandSetupHelper.java   | 23 ++++++----
 .../com/cloud/network/rules/RulesManagerImpl.java  | 50 +++++++++++++++++++++-
 2 files changed, 62 insertions(+), 11 deletions(-)

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 87a1662..63e9d80 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 aea24a4..de56774 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

Reply via email to