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

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


The following commit(s) were added to refs/heads/4.19 by this push:
     new a0e592e945e prevent nic removal on out of bounds router stop (#8371)
a0e592e945e is described below

commit a0e592e945e44e67a379a77982e5011b36db3e3c
Author: dahn <d...@onecht.net>
AuthorDate: Fri Feb 16 14:33:22 2024 +0100

    prevent nic removal on out of bounds router stop (#8371)
    
    Co-authored-by: Vishesh <vishes...@gmail.com>
    Co-authored-by: Wei Zhou <weiz...@apache.org>
---
 api/src/main/java/com/cloud/vm/NicProfile.java     |  2 +-
 .../main/java/com/cloud/serializer/GsonHelper.java |  2 +
 .../engine/orchestration/NetworkOrchestrator.java  | 11 ++-
 .../schema/src/main/java/com/cloud/vm/NicVO.java   | 13 +--
 .../com/cloud/network/guru/ControlNetworkGuru.java | 13 ++-
 .../cloud/network/guru/PodBasedNetworkGuru.java    |  2 +-
 .../router/VirtualNetworkApplianceManager.java     | 99 ++++++++++------------
 .../router/VirtualNetworkApplianceManagerImpl.java | 82 ++++++++----------
 8 files changed, 102 insertions(+), 122 deletions(-)

diff --git a/api/src/main/java/com/cloud/vm/NicProfile.java 
b/api/src/main/java/com/cloud/vm/NicProfile.java
index 3f37331b1e4..d3c1daa1f5d 100644
--- a/api/src/main/java/com/cloud/vm/NicProfile.java
+++ b/api/src/main/java/com/cloud/vm/NicProfile.java
@@ -442,6 +442,6 @@ public class NicProfile implements InternalIdentity, 
Serializable {
 
     @Override
     public String toString() {
-        return String.format("NicProfile %s", 
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "vmId", 
"reservationId", "iPv4Address", "broadcastUri"));
+        return String.format("NicProfile %s", 
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "vmId", 
"deviceId", "broadcastUri", "reservationId", "iPv4Address"));
     }
 }
diff --git a/core/src/main/java/com/cloud/serializer/GsonHelper.java 
b/core/src/main/java/com/cloud/serializer/GsonHelper.java
index 7ac85d39317..7c33ef0e5d5 100644
--- a/core/src/main/java/com/cloud/serializer/GsonHelper.java
+++ b/core/src/main/java/com/cloud/serializer/GsonHelper.java
@@ -51,6 +51,8 @@ public class GsonHelper {
         GsonBuilder loggerBuilder = new GsonBuilder();
         loggerBuilder.disableHtmlEscaping();
         loggerBuilder.setExclusionStrategies(new 
LoggingExclusionStrategy(s_logger));
+        loggerBuilder.serializeSpecialFloatingPointValues();
+        // maybe add loggerBuilder.serializeNulls(); as well?
         s_gogger = setDefaultGsonConfig(loggerBuilder);
         s_logger.info("Default Builder inited.");
     }
diff --git 
a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
 
b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
index 6c10a02abba..57f6f99bf2a 100644
--- 
a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
+++ 
b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
@@ -2310,12 +2310,12 @@ public class NetworkOrchestrator extends ManagerBase 
implements NetworkOrchestra
 
     @DB
     protected void releaseNic(final VirtualMachineProfile vmProfile, final 
long nicId) throws ConcurrentOperationException, ResourceUnavailableException {
-        final Pair<Network, NicProfile> networkToRelease = 
Transaction.execute(new TransactionCallback<Pair<Network, NicProfile>>() {
+        final Pair<Network, NicProfile> networkToRelease = 
Transaction.execute(new TransactionCallback<>() {
             @Override
             public Pair<Network, NicProfile> doInTransaction(final 
TransactionStatus status) {
                 final NicVO nic = _nicDao.lockRow(nicId, true);
                 if (nic == null) {
-                    throw new ConcurrentOperationException("Unable to acquire 
lock on nic " + nic);
+                    throw new 
ConcurrentOperationException(String.format("Unable to acquire lock on nic 
id=%d", nicId));
                 }
 
                 final Nic.State originalState = nic.getState();
@@ -2329,6 +2329,9 @@ public class NetworkOrchestrator extends ManagerBase 
implements NetworkOrchestra
                         final NicProfile profile = new NicProfile(nic, 
network, nic.getBroadcastUri(), nic.getIsolationUri(), null, _networkModel
                                 .isSecurityGroupSupportedInNetwork(network), 
_networkModel.getNetworkTag(vmProfile.getHypervisorType(), network));
                         if (guru.release(profile, vmProfile, 
nic.getReservationId())) {
+                            if (s_logger.isDebugEnabled()) {
+                                s_logger.debug(String.format("The nic %s on %s 
was released according to %s by guru %s, now updating record.", nic, profile, 
vmProfile, guru));
+                            }
                             applyProfileToNicForRelease(nic, profile);
                             nic.setState(Nic.State.Allocated);
                             if (originalState == Nic.State.Reserved) {
@@ -2338,7 +2341,7 @@ public class NetworkOrchestrator extends ManagerBase 
implements NetworkOrchestra
                             }
                         }
                         // Perform release on network elements
-                        return new Pair<Network, NicProfile>(network, profile);
+                        return new Pair<>(network, profile);
                     } else {
                         nic.setState(Nic.State.Allocated);
                         updateNic(nic, network.getId(), -1);
@@ -2435,7 +2438,7 @@ public class NetworkOrchestrator extends ManagerBase 
implements NetworkOrchestra
             for (final NetworkElement element : networkElements) {
                 if (providersToImplement.contains(element.getProvider())) {
                     if (s_logger.isDebugEnabled()) {
-                        s_logger.debug("Asking " + element.getName() + " to 
release " + nic);
+                        s_logger.debug(String.format("Asking %s to release %s, 
according to the reservation strategy %s", element.getName(), nic, 
nic.getReservationStrategy()));
                     }
                     try {
                         element.release(network, profile, vm, null);
diff --git a/engine/schema/src/main/java/com/cloud/vm/NicVO.java 
b/engine/schema/src/main/java/com/cloud/vm/NicVO.java
index a32a943ea58..936efd112b7 100644
--- a/engine/schema/src/main/java/com/cloud/vm/NicVO.java
+++ b/engine/schema/src/main/java/com/cloud/vm/NicVO.java
@@ -30,6 +30,7 @@ import javax.persistence.Id;
 import javax.persistence.Table;
 import javax.persistence.Transient;
 
+import 
org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 
@@ -329,17 +330,7 @@ public class NicVO implements Nic {
 
     @Override
     public String toString() {
-        return new StringBuilder("Nic[").append(id)
-            .append("-")
-            .append(instanceId)
-            .append("-")
-            .append(deviceId)
-            .append("-")
-            .append(reservationId)
-            .append("-")
-            .append(iPv4Address)
-            .append("]")
-            .toString();
+        return String.format("Nic %s", 
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", 
"instanceId", "deviceId", "broadcastUri", "reservationId", "iPv4Address"));
     }
 
     @Override
diff --git 
a/server/src/main/java/com/cloud/network/guru/ControlNetworkGuru.java 
b/server/src/main/java/com/cloud/network/guru/ControlNetworkGuru.java
index ce62c7b4e3f..ce59b50f3c3 100644
--- a/server/src/main/java/com/cloud/network/guru/ControlNetworkGuru.java
+++ b/server/src/main/java/com/cloud/network/guru/ControlNetworkGuru.java
@@ -21,6 +21,7 @@ import java.util.Map;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import com.cloud.network.router.VirtualNetworkApplianceManager;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 import org.apache.log4j.Logger;
 
@@ -166,18 +167,24 @@ public class ControlNetworkGuru extends 
PodBasedNetworkGuru implements NetworkGu
         assert nic.getTrafficType() == TrafficType.Control;
         HypervisorType hType = vm.getHypervisorType();
         if ( ( (hType == HypervisorType.VMware) || (hType == 
HypervisorType.Hyperv) )&& isRouterVm(vm)) {
+            if 
(!VirtualNetworkApplianceManager.RemoveControlIpOnStop.valueIn(vm.getVirtualMachine().getDataCenterId()))
 {
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug(String.format("not releasing %s from %s 
with reservationId %s, as systemvm.release.control.ip.on.stop is set to false 
for the data center.", nic, vm, reservationId));
+                }
+                return true;
+            }
             long dcId = vm.getVirtualMachine().getDataCenterId();
             DataCenterVO dcVo = _dcDao.findById(dcId);
             if (dcVo.getNetworkType() != NetworkType.Basic) {
                 super.release(nic, vm, reservationId);
                 if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("Released nic: " + nic);
+                    s_logger.debug(String.format("Released nic: %s for vm %s", 
nic, vm));
                 }
                 return true;
             } else {
                 nic.deallocate();
                 if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("Released nic: " + nic);
+                    s_logger.debug(String.format("Released nic: %s for vm %s", 
nic, vm));
                 }
                 return true;
             }
@@ -187,7 +194,7 @@ public class ControlNetworkGuru extends PodBasedNetworkGuru 
implements NetworkGu
 
         nic.deallocate();
         if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Released nic: " + nic);
+            s_logger.debug(String.format("Released nic: %s for vm %s", nic, 
vm));
         }
 
         return true;
diff --git 
a/server/src/main/java/com/cloud/network/guru/PodBasedNetworkGuru.java 
b/server/src/main/java/com/cloud/network/guru/PodBasedNetworkGuru.java
index 9f9771e7cfb..44d349a861e 100644
--- a/server/src/main/java/com/cloud/network/guru/PodBasedNetworkGuru.java
+++ b/server/src/main/java/com/cloud/network/guru/PodBasedNetworkGuru.java
@@ -159,7 +159,7 @@ public class PodBasedNetworkGuru extends AdapterBase 
implements NetworkGuru {
         nic.deallocate();
 
         if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Released nic: " + nic);
+            s_logger.debug(String.format("Released nic: %s for vm %s", nic, 
vm));
         }
 
         return true;
diff --git 
a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManager.java
 
b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManager.java
index 8b2fd81bb48..387e50519e9 100644
--- 
a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManager.java
+++ 
b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManager.java
@@ -36,82 +36,83 @@ import com.cloud.vm.DomainRouterVO;
  */
 public interface VirtualNetworkApplianceManager extends Manager, 
VirtualNetworkApplianceService {
 
-    static final String RouterTemplateXenCK = "router.template.xenserver";
-    static final String RouterTemplateKvmCK = "router.template.kvm";
-    static final String RouterTemplateVmwareCK = "router.template.vmware";
-    static final String RouterTemplateHyperVCK = "router.template.hyperv";
-    static final String RouterTemplateLxcCK = "router.template.lxc";
-    static final String RouterTemplateOvm3CK = "router.template.ovm3";
-    static final String SetServiceMonitorCK = 
"network.router.EnableServiceMonitoring";
-    static final String RouterAlertsCheckIntervalCK = 
"router.alerts.check.interval";
-    static final String VirtualRouterServiceOfferingCK = 
"router.service.offering";
-
-    static final String RouterHealthChecksConfigRefreshIntervalCK = 
"router.health.checks.config.refresh.interval";
-    static final String RouterHealthChecksResultFetchIntervalCK = 
"router.health.checks.results.fetch.interval";
-    static final String RouterHealthChecksFailuresToRecreateVrCK = 
"router.health.checks.failures.to.recreate.vr";
-
-    static final ConfigKey<String> RouterTemplateXen = new 
ConfigKey<String>(String.class, RouterTemplateXenCK, "Advanced", "SystemVM 
Template (XenServer)",
+    String RouterTemplateXenCK = "router.template.xenserver";
+    String RouterTemplateKvmCK = "router.template.kvm";
+    String RouterTemplateVmwareCK = "router.template.vmware";
+    String RouterTemplateHyperVCK = "router.template.hyperv";
+    String RouterTemplateLxcCK = "router.template.lxc";
+    String RouterTemplateOvm3CK = "router.template.ovm3";
+    String SetServiceMonitorCK = "network.router.EnableServiceMonitoring";
+    String RouterAlertsCheckIntervalCK = "router.alerts.check.interval";
+    String VirtualRouterServiceOfferingCK = "router.service.offering";
+
+    String RouterHealthChecksConfigRefreshIntervalCK = 
"router.health.checks.config.refresh.interval";
+    String RouterHealthChecksResultFetchIntervalCK = 
"router.health.checks.results.fetch.interval";
+    String RouterHealthChecksFailuresToRecreateVrCK = 
"router.health.checks.failures.to.recreate.vr";
+    String RemoveControlIpOnStopCK = "systemvm.release.control.ip.on.stop";
+
+    ConfigKey<String> RouterTemplateXen = new ConfigKey<>(String.class, 
RouterTemplateXenCK, "Advanced", "SystemVM Template (XenServer)",
             "Name of the default router template on Xenserver.", true, 
ConfigKey.Scope.Zone, null);
-    static final ConfigKey<String> RouterTemplateKvm = new 
ConfigKey<String>(String.class, RouterTemplateKvmCK, "Advanced", "SystemVM 
Template (KVM)",
+    ConfigKey<String> RouterTemplateKvm = new ConfigKey<>(String.class, 
RouterTemplateKvmCK, "Advanced", "SystemVM Template (KVM)",
             "Name of the default router template on KVM.", true, 
ConfigKey.Scope.Zone, null);
-    static final ConfigKey<String> RouterTemplateVmware = new 
ConfigKey<String>(String.class, RouterTemplateVmwareCK, "Advanced", "SystemVM 
Template (vSphere)",
+    ConfigKey<String> RouterTemplateVmware = new ConfigKey<>(String.class, 
RouterTemplateVmwareCK, "Advanced", "SystemVM Template (vSphere)",
             "Name of the default router template on Vmware.", true, 
ConfigKey.Scope.Zone, null);
-    static final ConfigKey<String> RouterTemplateHyperV = new 
ConfigKey<String>(String.class, RouterTemplateHyperVCK, "Advanced", "SystemVM 
Template (HyperV)",
+    ConfigKey<String> RouterTemplateHyperV = new ConfigKey<>(String.class, 
RouterTemplateHyperVCK, "Advanced", "SystemVM Template (HyperV)",
             "Name of the default router template on Hyperv.", true, 
ConfigKey.Scope.Zone, null);
-    static final ConfigKey<String> RouterTemplateLxc = new 
ConfigKey<String>(String.class, RouterTemplateLxcCK, "Advanced", "SystemVM 
Template (LXC)",
+    ConfigKey<String> RouterTemplateLxc = new ConfigKey<>(String.class, 
RouterTemplateLxcCK, "Advanced", "SystemVM Template (LXC)",
             "Name of the default router template on LXC.", true, 
ConfigKey.Scope.Zone, null);
-    static final ConfigKey<String> RouterTemplateOvm3 = new 
ConfigKey<String>(String.class, RouterTemplateOvm3CK, "Advanced", "SystemVM 
Template (Ovm3)",
+    ConfigKey<String> RouterTemplateOvm3 = new ConfigKey<>(String.class, 
RouterTemplateOvm3CK, "Advanced", "SystemVM Template (Ovm3)",
             "Name of the default router template on Ovm3.", true, 
ConfigKey.Scope.Zone, null);
 
-    static final ConfigKey<Boolean> SetServiceMonitor = new 
ConfigKey<Boolean>(Boolean.class, SetServiceMonitorCK, "Advanced", "true",
+    ConfigKey<Boolean> SetServiceMonitor = new ConfigKey<>(Boolean.class, 
SetServiceMonitorCK, "Advanced", "true",
             "service monitoring in router enable/disable option, default 
true", true, ConfigKey.Scope.Zone, null);
 
-    static final ConfigKey<Integer> RouterAlertsCheckInterval = new 
ConfigKey<Integer>(Integer.class, RouterAlertsCheckIntervalCK, "Advanced", 
"1800",
+    ConfigKey<Integer> RouterAlertsCheckInterval = new 
ConfigKey<>(Integer.class, RouterAlertsCheckIntervalCK, "Advanced", "1800",
             "Interval (in seconds) to check for alerts in Virtual Router.", 
false, ConfigKey.Scope.Global, null);
-    static final ConfigKey<Boolean> RouterVersionCheckEnabled = new 
ConfigKey<Boolean>("Advanced", Boolean.class, "router.version.check", "true",
+    ConfigKey<Boolean> RouterVersionCheckEnabled = new ConfigKey<>("Advanced", 
Boolean.class, "router.version.check", "true",
             "If true, router minimum required version is checked before 
sending command", false);
-    static final ConfigKey<Boolean> UseExternalDnsServers = new 
ConfigKey<Boolean>(Boolean.class, "use.external.dns", "Advanced", "false",
+    ConfigKey<Boolean> UseExternalDnsServers = new ConfigKey<>(Boolean.class, 
"use.external.dns", "Advanced", "false",
             "Bypass internal dns, use external dns1 and dns2", true, 
ConfigKey.Scope.Zone, null);
-    static final ConfigKey<Boolean> ExposeDnsAndBootpServer = new 
ConfigKey<Boolean>(Boolean.class, "expose.dns.externally", "Advanced", "true",
+    ConfigKey<Boolean> ExposeDnsAndBootpServer = new 
ConfigKey<>(Boolean.class, "expose.dns.externally", "Advanced", "true",
             "open dns, dhcp and bootp on the public interface", true, 
ConfigKey.Scope.Zone, null);
 
-    static final ConfigKey<String> VirtualRouterServiceOffering = new 
ConfigKey<String>(String.class, VirtualRouterServiceOfferingCK, "Advanced", "",
+    ConfigKey<String> VirtualRouterServiceOffering = new 
ConfigKey<>(String.class, VirtualRouterServiceOfferingCK, "Advanced", "",
             "Uuid of the service offering used by virtual routers; if NULL - 
system offering will be used", true, ConfigKey.Scope.Account, null);
 
     // Health checks
-    static final ConfigKey<Boolean> RouterHealthChecksEnabled = new 
ConfigKey<Boolean>(Boolean.class, "router.health.checks.enabled", "Advanced", 
"true",
+    ConfigKey<Boolean> RouterHealthChecksEnabled = new 
ConfigKey<>(Boolean.class, "router.health.checks.enabled", "Advanced", "true",
             "If true, router health checks are allowed to be executed and 
read. If false, all scheduled checks and API calls for on demand checks are 
disabled.",
             true, ConfigKey.Scope.Global, null);
-    static final ConfigKey<Integer> RouterHealthChecksBasicInterval = new 
ConfigKey<Integer>(Integer.class, "router.health.checks.basic.interval", 
"Advanced", "3",
+    ConfigKey<Integer> RouterHealthChecksBasicInterval = new 
ConfigKey<>(Integer.class, "router.health.checks.basic.interval", "Advanced", 
"3",
             "Interval in minutes at which basic router health checks are 
performed. If set to 0, no tests are scheduled.",
             true, ConfigKey.Scope.Global, null, 
RouterHealthChecksEnabled.key());
-    static final ConfigKey<Integer> RouterHealthChecksAdvancedInterval = new 
ConfigKey<Integer>(Integer.class, "router.health.checks.advanced.interval", 
"Advanced", "10",
+    ConfigKey<Integer> RouterHealthChecksAdvancedInterval = new 
ConfigKey<>(Integer.class, "router.health.checks.advanced.interval", 
"Advanced", "10",
             "Interval in minutes at which advanced router health checks are 
performed. If set to 0, no tests are scheduled.",
             true, ConfigKey.Scope.Global, null, 
RouterHealthChecksEnabled.key());
-    static final ConfigKey<Integer> RouterHealthChecksConfigRefreshInterval = 
new ConfigKey<Integer>(Integer.class, 
RouterHealthChecksConfigRefreshIntervalCK, "Advanced", "10",
+    ConfigKey<Integer> RouterHealthChecksConfigRefreshInterval = new 
ConfigKey<>(Integer.class, RouterHealthChecksConfigRefreshIntervalCK, 
"Advanced", "10",
             "Interval in minutes at which router health checks config - such 
as scheduling intervals, excluded checks, etc is updated on virtual routers by 
the management server. This value should" +
                     " be sufficiently high (like 2x) from the 
router.health.checks.basic.interval and router.health.checks.advanced.interval 
so that there is time between new results generation and results generation for 
passed data.",
             false, ConfigKey.Scope.Global, null, 
RouterHealthChecksEnabled.key());
-    static final ConfigKey<Integer> RouterHealthChecksResultFetchInterval = 
new ConfigKey<Integer>(Integer.class, RouterHealthChecksResultFetchIntervalCK, 
"Advanced", "10",
+    ConfigKey<Integer> RouterHealthChecksResultFetchInterval = new 
ConfigKey<>(Integer.class, RouterHealthChecksResultFetchIntervalCK, "Advanced", 
"10",
             "Interval in minutes at which router health checks results are 
fetched by management server. On each result fetch, management server evaluates 
need to recreate VR as per configuration of " + 
RouterHealthChecksFailuresToRecreateVrCK +
                     "This value should be sufficiently high (like 2x) from the 
router.health.checks.basic.interval and router.health.checks.advanced.interval 
so that there is time between new results generation and fetch.",
             false, ConfigKey.Scope.Global, null, 
RouterHealthChecksEnabled.key());
-    static final ConfigKey<String> RouterHealthChecksFailuresToRecreateVr = 
new ConfigKey<String>(String.class, RouterHealthChecksFailuresToRecreateVrCK, 
"Advanced", "",
+    ConfigKey<String> RouterHealthChecksFailuresToRecreateVr = new 
ConfigKey<>(String.class, RouterHealthChecksFailuresToRecreateVrCK, "Advanced", 
"",
             "Health checks failures defined by this config are the checks that 
should cause router recreation. If empty the recreate is not attempted for any 
health check failure. Possible values are comma separated script names " +
                     "from systemvm’s /root/health_scripts/ (namely - 
cpu_usage_check.py, dhcp_check.py, disk_space_check.py, dns_check.py, 
gateways_check.py, haproxy_check.py, iptables_check.py, memory_usage_check.py, 
router_version_check.py), connectivity.test, filesystem.writable.test " +
                     " or services (namely - loadbalancing.service, 
webserver.service, dhcp.service) ",
             true, ConfigKey.Scope.Zone, null, null, 
RouterHealthChecksEnabled.key(), null, null, ConfigKey.Kind.CSV, null);
-    static final ConfigKey<String> RouterHealthChecksToExclude = new 
ConfigKey<String>(String.class, "router.health.checks.to.exclude", "Advanced", 
"",
+    ConfigKey<String> RouterHealthChecksToExclude = new 
ConfigKey<>(String.class, "router.health.checks.to.exclude", "Advanced", "",
             "Health checks that should be excluded when executing scheduled 
checks on the router. This can be a comma separated list of script names placed 
in the '/root/health_checks/' folder. Currently the following scripts are " +
                     "placed in default systemvm template -  
cpu_usage_check.py, disk_space_check.py, gateways_check.py, iptables_check.py, 
router_version_check.py, dhcp_check.py, dns_check.py, haproxy_check.py, 
memory_usage_check.py.",
             true, ConfigKey.Scope.Zone, null, null, 
RouterHealthChecksEnabled.key(), null, null, ConfigKey.Kind.CSV, null);
-    static final ConfigKey<Double> RouterHealthChecksFreeDiskSpaceThreshold = 
new ConfigKey<Double>(Double.class, 
"router.health.checks.free.disk.space.threshold",
+    ConfigKey<Double> RouterHealthChecksFreeDiskSpaceThreshold = new 
ConfigKey<>(Double.class, "router.health.checks.free.disk.space.threshold",
             "Advanced", "100", "Free disk space threshold (in MB) on VR below 
which the check is considered a failure.",
             true, ConfigKey.Scope.Zone, null, RouterHealthChecksEnabled.key());
-    static final ConfigKey<Double> RouterHealthChecksMaxCpuUsageThreshold = 
new ConfigKey<Double>(Double.class, 
"router.health.checks.max.cpu.usage.threshold",
+    ConfigKey<Double> RouterHealthChecksMaxCpuUsageThreshold = new 
ConfigKey<>(Double.class, "router.health.checks.max.cpu.usage.threshold",
             "Advanced", "100", " Max CPU Usage threshold as % above which 
check is considered a failure.",
             true, ConfigKey.Scope.Zone, null, RouterHealthChecksEnabled.key());
-    static final ConfigKey<Double> RouterHealthChecksMaxMemoryUsageThreshold = 
new ConfigKey<Double>(Double.class, 
"router.health.checks.max.memory.usage.threshold",
+    ConfigKey<Double> RouterHealthChecksMaxMemoryUsageThreshold = new 
ConfigKey<>(Double.class, "router.health.checks.max.memory.usage.threshold",
             "Advanced", "100", "Max Memory Usage threshold as % above which 
check is considered a failure.",
             true, ConfigKey.Scope.Zone, null, RouterHealthChecksEnabled.key());
     ConfigKey<String> RouterLogrotateFrequency = new ConfigKey<>(String.class, 
"router.logrotate.frequency", "Advanced", "*:00:00",
@@ -121,23 +122,15 @@ public interface VirtualNetworkApplianceManager extends 
Manager, VirtualNetworkA
                     "reach the minimum size.",
             true, ConfigKey.Scope.Zone, null);
 
-    public static final int DEFAULT_ROUTER_VM_RAMSIZE = 256;            // 256M
-    public static final int DEFAULT_ROUTER_CPU_MHZ = 500;                // 
500 MHz
-    public static final boolean USE_POD_VLAN = false;
-    public static final int DEFAULT_PRIORITY = 100;
-    public static final int DEFAULT_DELTA = 2;
-
-    /**
-    /*
-     * Send ssh public/private key pair to specified host
-     * @param hostId
-     * @param pubKey
-     * @param prvKey
-     *
-     * NOT USED IN THE VIRTUAL NET APPLIANCE
-     *
-     */
-    //boolean sendSshKeysToHost(Long hostId, String pubKey, String prvKey):
+    ConfigKey<Boolean> RemoveControlIpOnStop = new ConfigKey<>(Boolean.class, 
RemoveControlIpOnStopCK, "Advanced", "true",
+            "on stopping routers and system VMs the IP will be released to 
preserve IPv4 space.", true, ConfigKey.Scope.Zone, null);
+
+    int DEFAULT_ROUTER_VM_RAMSIZE = 256;            // 256M
+    int DEFAULT_ROUTER_CPU_MHZ = 500;                // 500 MHz
+    boolean USE_POD_VLAN = false;
+    int DEFAULT_PRIORITY = 100;
+    int DEFAULT_DELTA = 2;
+
 
     boolean startRemoteAccessVpn(Network network, RemoteAccessVpn vpn, List<? 
extends VirtualRouter> routers) throws ResourceUnavailableException;
 
diff --git 
a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
 
b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index d49322bde60..ebce0492ce3 100644
--- 
a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ 
b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -57,7 +57,6 @@ import 
org.apache.cloudstack.api.command.admin.router.UpgradeRouterTemplateCmd;
 import org.apache.cloudstack.config.ApiServiceConfiguration;
 import org.apache.cloudstack.context.CallContext;
 import 
org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
-import org.apache.cloudstack.framework.config.ConfigDepot;
 import org.apache.cloudstack.framework.config.ConfigKey;
 import org.apache.cloudstack.framework.config.Configurable;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
@@ -66,7 +65,6 @@ import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
 import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO;
 import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
 import org.apache.cloudstack.managed.context.ManagedContextRunnable;
-import 
org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinitionBuilder;
 import org.apache.cloudstack.network.topology.NetworkTopology;
 import org.apache.cloudstack.network.topology.NetworkTopologyContext;
 import org.apache.cloudstack.utils.CloudStackVersion;
@@ -116,13 +114,11 @@ import com.cloud.api.query.vo.UserVmJoinVO;
 import com.cloud.cluster.ManagementServerHostVO;
 import com.cloud.cluster.dao.ManagementServerHostDao;
 import com.cloud.configuration.Config;
-import com.cloud.configuration.ConfigurationManager;
 import com.cloud.configuration.ZoneConfig;
 import com.cloud.dc.DataCenter;
 import com.cloud.dc.DataCenter.NetworkType;
 import com.cloud.dc.DataCenterVO;
 import com.cloud.dc.HostPodVO;
-import com.cloud.dc.dao.ClusterDao;
 import com.cloud.dc.dao.DataCenterDao;
 import com.cloud.dc.dao.HostPodDao;
 import com.cloud.dc.dao.VlanDao;
@@ -144,7 +140,6 @@ import com.cloud.host.Status;
 import com.cloud.host.dao.HostDao;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.network.IpAddress;
-import com.cloud.network.IpAddressManager;
 import com.cloud.network.MonitoringService;
 import com.cloud.network.Network;
 import com.cloud.network.Network.GuestType;
@@ -178,17 +173,13 @@ import com.cloud.network.dao.NetworkServiceMapDao;
 import com.cloud.network.dao.NetworkVO;
 import com.cloud.network.dao.OpRouterMonitorServiceDao;
 import com.cloud.network.dao.OpRouterMonitorServiceVO;
-import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
 import com.cloud.network.dao.RemoteAccessVpnDao;
 import com.cloud.network.dao.RouterHealthCheckResultDao;
 import com.cloud.network.dao.RouterHealthCheckResultVO;
 import com.cloud.network.dao.Site2SiteCustomerGatewayDao;
 import com.cloud.network.dao.Site2SiteVpnConnectionDao;
 import com.cloud.network.dao.Site2SiteVpnConnectionVO;
-import com.cloud.network.dao.Site2SiteVpnGatewayDao;
-import com.cloud.network.dao.UserIpv6AddressDao;
 import com.cloud.network.dao.VirtualRouterProviderDao;
-import com.cloud.network.dao.VpnUserDao;
 import com.cloud.network.lb.LoadBalancingRule;
 import com.cloud.network.lb.LoadBalancingRule.LbDestination;
 import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy;
@@ -217,16 +208,11 @@ import com.cloud.offering.NetworkOffering;
 import com.cloud.offering.ServiceOffering;
 import com.cloud.offerings.NetworkOfferingVO;
 import com.cloud.offerings.dao.NetworkOfferingDao;
-import com.cloud.resource.ResourceManager;
 import com.cloud.serializer.GsonHelper;
-import com.cloud.server.ConfigurationServer;
 import com.cloud.server.ManagementServer;
 import com.cloud.service.ServiceOfferingVO;
 import com.cloud.service.dao.ServiceOfferingDao;
 import com.cloud.storage.Storage.ProvisioningType;
-import com.cloud.storage.dao.GuestOSDao;
-import com.cloud.storage.dao.VMTemplateDao;
-import com.cloud.storage.dao.VolumeDao;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
 import com.cloud.user.User;
@@ -273,9 +259,7 @@ import com.cloud.vm.dao.DomainRouterDao;
 import com.cloud.vm.dao.NicDao;
 import com.cloud.vm.dao.NicIpAliasDao;
 import com.cloud.vm.dao.NicIpAliasVO;
-import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.UserVmDetailsDao;
-import com.cloud.vm.dao.VMInstanceDao;
 import com.google.gson.JsonSyntaxException;
 import com.google.gson.reflect.TypeToken;
 
@@ -302,7 +286,6 @@ Configurable, StateListener<VirtualMachine.State, 
VirtualMachine.Event, VirtualM
     @Inject private LoadBalancerDao _loadBalancerDao;
     @Inject private LoadBalancerVMMapDao _loadBalancerVMMapDao;
     @Inject protected IPAddressDao _ipAddressDao;
-    @Inject private VMTemplateDao _templateDao;
     @Inject protected DomainRouterDao _routerDao;
     @Inject private UserDao _userDao;
     @Inject protected UserStatisticsDao _userStatsDao;
@@ -313,17 +296,11 @@ Configurable, StateListener<VirtualMachine.State, 
VirtualMachine.Event, VirtualM
     @Inject protected AgentManager _agentMgr;
     @Inject private AlertManager _alertMgr;
     @Inject private AccountManager _accountMgr;
-    @Inject private ConfigurationManager _configMgr;
-    @Inject private ConfigurationServer _configServer;
     @Inject protected ServiceOfferingDao _serviceOfferingDao;
-    @Inject private UserVmDao _userVmDao;
-    @Inject private VMInstanceDao _vmDao;
     @Inject private NetworkOfferingDao _networkOfferingDao;
-    @Inject private GuestOSDao _guestOSDao;
     @Inject protected NetworkOrchestrationService _networkMgr;
     @Inject protected NetworkModel _networkModel;
     @Inject protected VirtualMachineManager _itMgr;
-    @Inject private VpnUserDao _vpnUsersDao;
     @Inject private RulesManager _rulesMgr;
     @Inject protected NetworkDao _networkDao;
     @Inject private LoadBalancingRulesManager _lbMgr;
@@ -331,21 +308,13 @@ Configurable, StateListener<VirtualMachine.State, 
VirtualMachine.Event, VirtualM
     @Inject protected RemoteAccessVpnDao _vpnDao;
     @Inject protected NicDao _nicDao;
     @Inject private NicIpAliasDao _nicIpAliasDao;
-    @Inject private VolumeDao _volumeDao;
     @Inject private UserVmDetailsDao _vmDetailsDao;
-    @Inject private ClusterDao _clusterDao;
-    @Inject private ResourceManager _resourceMgr;
-    @Inject private PhysicalNetworkServiceProviderDao _physicalProviderDao;
     @Inject protected VirtualRouterProviderDao _vrProviderDao;
     @Inject private ManagementServerHostDao _msHostDao;
     @Inject private Site2SiteCustomerGatewayDao _s2sCustomerGatewayDao;
-    @Inject private Site2SiteVpnGatewayDao _s2sVpnGatewayDao;
     @Inject private Site2SiteVpnConnectionDao _s2sVpnConnectionDao;
     @Inject private Site2SiteVpnManager _s2sVpnMgr;
-    @Inject private UserIpv6AddressDao _ipv6Dao;
     @Inject private NetworkService _networkSvc;
-    @Inject private IpAddressManager _ipAddrMgr;
-    @Inject private ConfigDepot _configDepot;
     @Inject protected MonitoringServiceDao _monitorServiceDao;
     @Inject private AsyncJobManager _asyncMgr;
     @Inject protected VpcDao _vpcDao;
@@ -372,7 +341,6 @@ Configurable, StateListener<VirtualMachine.State, 
VirtualMachine.Event, VirtualM
     @Inject protected RouterControlHelper _routerControlHelper;
 
     @Inject protected CommandSetupHelper _commandSetupHelper;
-    @Inject protected RouterDeploymentDefinitionBuilder 
_routerDeploymentManagerBuilder;
     @Inject private ManagementServer mgr;
 
     private int _routerRamSize;
@@ -2798,28 +2766,43 @@ Configurable, StateListener<VirtualMachine.State, 
VirtualMachine.Event, VirtualM
             final VirtualMachine vm = profile.getVirtualMachine();
             final DomainRouterVO domR = _routerDao.findById(vm.getId());
             processStopOrRebootAnswer(domR, answer);
-            final List<? extends Nic> routerNics = 
_nicDao.listByVmId(profile.getId());
-            for (final Nic nic : routerNics) {
-                final Network network = 
_networkModel.getNetwork(nic.getNetworkId());
-                final DataCenterVO dcVO = 
_dcDao.findById(network.getDataCenterId());
-
-                if (network.getTrafficType() == TrafficType.Guest && 
nic.getBroadcastUri() != null && 
nic.getBroadcastUri().getScheme().equals("pvlan")) {
-                    final NicProfile nicProfile = new NicProfile(nic, network, 
nic.getBroadcastUri(), nic.getIsolationUri(), 0, false, "pvlan-nic");
-
-                    final NetworkTopology networkTopology = 
_networkTopologyContext.retrieveNetworkTopology(dcVO);
-                    try {
-                        networkTopology.setupDhcpForPvlan(false, domR, 
domR.getHostId(), nicProfile);
-                    } catch (final ResourceUnavailableException e) {
-                        s_logger.debug("ERROR in finalizeStop: ", e);
-                    }
-                }
+            if 
(Boolean.TRUE.equals(RemoveControlIpOnStop.valueIn(profile.getVirtualMachine().getDataCenterId())))
 {
+                removeNics(vm, domR);
             }
-
         }
     }
 
     @Override
     public void finalizeExpunge(final VirtualMachine vm) {
+        if 
(Boolean.FALSE.equals(RemoveControlIpOnStop.valueIn(vm.getDataCenterId()))) {
+            final DomainRouterVO domR = _routerDao.findById(vm.getId());
+            s_logger.info(String.format("removing nics for VR [%s]", vm));
+            removeNics(vm, domR);
+        }
+    }
+
+    private void removeNics(VirtualMachine vm, DomainRouterVO domR) {
+        final List<? extends Nic> routerNics = _nicDao.listByVmId(vm.getId());
+        final DataCenterVO dcVO = _dcDao.findById(vm.getDataCenterId());
+
+        for (final Nic nic : routerNics) {
+            final Network network = 
_networkModel.getNetwork(nic.getNetworkId());
+
+            removeDhcpRulesForPvLan(domR, nic, network, dcVO);
+        }
+    }
+
+    private void removeDhcpRulesForPvLan(DomainRouterVO domR, Nic nic, Network 
network, DataCenterVO dcVO) {
+        if (network.getTrafficType() == TrafficType.Guest && 
nic.getBroadcastUri() != null && 
nic.getBroadcastUri().getScheme().equals("pvlan")) {
+            final NicProfile nicProfile = new NicProfile(nic, network, 
nic.getBroadcastUri(), nic.getIsolationUri(), 0, false, "pvlan-nic");
+
+            final NetworkTopology networkTopology = 
_networkTopologyContext.retrieveNetworkTopology(dcVO);
+            try {
+                networkTopology.setupDhcpForPvlan(false, domR, 
domR.getHostId(), nicProfile);
+            } catch (final ResourceUnavailableException e) {
+                s_logger.debug("ERROR in finalizeStop: ", e);
+            }
+        }
     }
 
     @Override
@@ -3341,7 +3324,8 @@ Configurable, StateListener<VirtualMachine.State, 
VirtualMachine.Event, VirtualM
                 RouterHealthChecksMaxCpuUsageThreshold,
                 RouterHealthChecksMaxMemoryUsageThreshold,
                 ExposeDnsAndBootpServer,
-                RouterLogrotateFrequency
+                RouterLogrotateFrequency,
+                RemoveControlIpOnStop
         };
     }
 


Reply via email to