You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by "weizhouapache (via GitHub)" <gi...@apache.org> on 2025/08/19 08:23:28 UTC

[PR] Improvement: SSL offloading with Virtual Router [cloudstack]

weizhouapache opened a new pull request, #11468:
URL: https://github.com/apache/cloudstack/pull/11468

   ### Description
   
   This PR improves the SSL termination feature to support CloudStack VR
   
   Design doc: https://cwiki.apache.org/confluence/display/CLOUDSTACK/SSL+Offloading+with+Virtual+Router
   
   
   <!--- Describe your changes in DETAIL - And how has behaviour functionally changed. -->
   
   <!-- For new features, provide link to FS, dev ML discussion etc. -->
   <!-- In case of bug fix, the expected and actual behaviours, steps to reproduce. -->
   
   <!-- When "Fixes: #<id>" is specified, the issue/PR will automatically be closed when this PR gets merged -->
   <!-- For addressing multiple issues/PRs, use multiple "Fixes: #<id>" -->
   <!-- Fixes: # -->
   
   <!--- ******************************************************************************* -->
   <!--- NOTE: AUTOMATION USES THE DESCRIPTIONS TO SET LABELS AND PRODUCE DOCUMENTATION. -->
   <!--- PLEASE PUT AN 'X' in only **ONE** box -->
   <!--- ******************************************************************************* -->
   
   ### Types of changes
   
   - [ ] Breaking change (fix or feature that would cause existing functionality to change)
   - [ ] New feature (non-breaking change which adds functionality)
   - [ ] Bug fix (non-breaking change which fixes an issue)
   - [x] Enhancement (improves an existing feature and functionality)
   - [ ] Cleanup (Code refactoring and cleanup, that may add test cases)
   - [ ] build/CI
   - [ ] test (unit or integration test code)
   
   ### Feature/Enhancement Scale or Bug Severity
   
   #### Feature/Enhancement Scale
   
   - [ ] Major
   - [ ] Minor
   
   #### Bug Severity
   
   - [ ] BLOCKER
   - [ ] Critical
   - [ ] Major
   - [ ] Minor
   - [ ] Trivial
   
   ### Screenshots (if appropriate):
   
   ### How Has This Been Tested?
   
   <!-- Please describe in detail how you tested your changes. -->
   <!-- Include details of your testing environment, and the tests you ran to -->
   
   #### How did you try to break this feature and the system with this change?
   
   <!-- see how your change affects other areas of the code, etc. -->
   
   <!-- Please read the [CONTRIBUTING](https://github.com/apache/cloudstack/blob/main/CONTRIBUTING.md) document -->
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291171554


##########
server/src/main/java/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java:
##########
@@ -1294,8 +1294,13 @@ public boolean assignCertToLoadBalancer(long lbRuleId, Long certId) {
 
         //check if the lb is already bound
         LoadBalancerCertMapVO certMapRule = _lbCertMapDao.findByLbRuleId(loadBalancer.getId());
-        if (certMapRule != null)
-            throw new InvalidParameterValueException("Another certificate is already bound to the LB");
+        if (certMapRule != null) {
+            if (!forced) {
+                throw new InvalidParameterValueException("Another certificate is already bound to the LB");
+            }
+            logger.debug("Another certificate is already bound to the LB, removing it");
+            removeCertFromLoadBalancer(lbRuleId);
+        }

Review Comment:
   added method `validateCertMapRule`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3213686630

   <b>[SF] Trillian test result (tid-14094)</b>
   Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
   Total time taken: 54839 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14094-kvm-ol8.zip
   Smoke tests completed. 147 look OK, 0 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "DaanHoogland (via GitHub)" <gi...@apache.org>.
DaanHoogland commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2293408883


##########
core/src/main/java/com/cloud/network/HAProxyConfigurator.java:
##########
@@ -520,61 +544,69 @@ private List<String> getRulesForPool(final LoadBalancerTO lbTO, final boolean ke
             destsAvailable = true;
         }
 
-        Boolean httpbasedStickiness = false;
+        boolean httpbasedStickiness = false;
         /* attach stickiness sub rule only if the destinations are available */
-        if (stickinessSubRule != null && destsAvailable == true) {
+        if (stickinessSubRule != null && destsAvailable) {
             for (final StickinessPolicyTO stickinessPolicy : lbTO.getStickinessPolicies()) {
                 if (stickinessPolicy == null) {
                     continue;
                 }
                 if (StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName()) ||
                         StickinessMethodType.AppCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) {
                     httpbasedStickiness = true;
+                    break;
                 }
             }
             if (httpbasedStickiness) {
-                result.addAll(dstWithCookieSubRule);
+                backendConfigs.addAll(dstWithCookieSubRule);
             } else {
-                result.addAll(dstSubRule);
+                backendConfigs.addAll(dstSubRule);
             }
-            result.add(stickinessSubRule);
+            backendConfigs.add(stickinessSubRule);
         } else {
-            result.addAll(dstSubRule);
+            backendConfigs.addAll(dstSubRule);
         }
         if (stickinessSubRule != null && !destsAvailable) {
             logger.warn("Haproxy stickiness policy for lb rule: " + lbTO.getSrcIp() + ":" + lbTO.getSrcPort() + ": Not Applied, cause:  backends are unavailable");
         }
-        if (publicPort == NetUtils.HTTP_PORT && !keepAliveEnabled || httpbasedStickiness) {
-            sb = new StringBuilder();
-            sb.append("\t").append("mode http");
-            result.add(sb.toString());
-            sb = new StringBuilder();
-            sb.append("\t").append("option httpclose");
-            result.add(sb.toString());
+        boolean keepAliveEnabled = lbCmd.keepAliveEnabled;
+        boolean http = (publicPort == NetUtils.HTTP_PORT && !keepAliveEnabled);
+        if (http || httpbasedStickiness || sslOffloading) {
+            frontendConfigs.add("\tmode http");
+            String keepAliveLine = keepAliveEnabled ? "\tno option forceclose" : "\toption httpclose";
+            frontendConfigs.add(keepAliveLine);
         }
 
+        // add line like this: "listen  65_37_141_30-80\n\tbind 65.37.141.30:80"
+        result.add(String.format("listen %s", poolName));
+        result.addAll(frontendConfigs);
+
         String cidrList = lbTO.getCidrList();
 
         if (StringUtils.isNotBlank(cidrList)) {
             result.add(String.format("\tacl network_allowed src %s \n\ttcp-request connection reject if !network_allowed", cidrList));
         }
 
+        result.addAll(backendConfigs);
         result.add(blankLine);
         return result;
     }
 
     private String generateStatsRule(final LoadBalancerConfigCommand lbCmd, final String ruleName, final String statsIp) {
         final StringBuilder rule = new StringBuilder("\nlisten ").append(ruleName).append("\n\tbind ").append(statsIp).append(":").append(lbCmd.lbStatsPort);
         // TODO DH: write test for this in both cases
-        if (!lbCmd.keepAliveEnabled) {
-            logger.info("Haproxy mode http enabled");
-            rule.append("\n\tmode http\n\toption httpclose");
+        rule.append("\n\tmode http");
+        if (lbCmd.keepAliveEnabled) {
+            logger.info("Haproxy option http-keep-alive enabled");
+        } else {
+            logger.info("Haproxy option httpclose enabled");
+            rule.append("\n\toption httpclose");
         }
         rule.append("\n\tstats enable\n\tstats uri     ")
-        .append(lbCmd.lbStatsUri)
-        .append("\n\tstats realm   Haproxy\\ Statistics\n\tstats auth    ")
-        .append(lbCmd.lbStatsAuth);
-        rule.append("\n");
+                .append(lbCmd.lbStatsUri)
+                .append("\n\tstats realm   Haproxy\\ Statistics\n\tstats auth    ")
+                .append(lbCmd.lbStatsAuth)
+                .append("\n");

Review Comment:
   so you have your settings at 8 spaces per tab? (no big care anyway, so don’t bother too much)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3236391128

   @borisstoyanov a [SL] Trillian-Jenkins matrix job (EL8 mgmt + EL8 KVM, Ubuntu22 mgmt + Ubuntu22 KVM, EL8 mgmt + VMware 7.0u3, EL9 mgmt + XCP-ng 8.2 ) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3258441052

   <b>[SF] Trillian test result (tid-14216)</b>
   Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
   Total time taken: 54071 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14216-kvm-ol8.zip
   Smoke tests completed. 147 look OK, 0 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3211040703

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291107577


##########
core/src/main/java/com/cloud/network/HAProxyConfigurator.java:
##########
@@ -520,61 +544,69 @@ private List<String> getRulesForPool(final LoadBalancerTO lbTO, final boolean ke
             destsAvailable = true;
         }
 
-        Boolean httpbasedStickiness = false;
+        boolean httpbasedStickiness = false;
         /* attach stickiness sub rule only if the destinations are available */
-        if (stickinessSubRule != null && destsAvailable == true) {
+        if (stickinessSubRule != null && destsAvailable) {
             for (final StickinessPolicyTO stickinessPolicy : lbTO.getStickinessPolicies()) {
                 if (stickinessPolicy == null) {
                     continue;
                 }
                 if (StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName()) ||
                         StickinessMethodType.AppCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) {
                     httpbasedStickiness = true;
+                    break;
                 }
             }
             if (httpbasedStickiness) {
-                result.addAll(dstWithCookieSubRule);
+                backendConfigs.addAll(dstWithCookieSubRule);
             } else {
-                result.addAll(dstSubRule);
+                backendConfigs.addAll(dstSubRule);
             }
-            result.add(stickinessSubRule);
+            backendConfigs.add(stickinessSubRule);
         } else {
-            result.addAll(dstSubRule);
+            backendConfigs.addAll(dstSubRule);
         }
         if (stickinessSubRule != null && !destsAvailable) {
             logger.warn("Haproxy stickiness policy for lb rule: " + lbTO.getSrcIp() + ":" + lbTO.getSrcPort() + ": Not Applied, cause:  backends are unavailable");
         }
-        if (publicPort == NetUtils.HTTP_PORT && !keepAliveEnabled || httpbasedStickiness) {
-            sb = new StringBuilder();
-            sb.append("\t").append("mode http");
-            result.add(sb.toString());
-            sb = new StringBuilder();
-            sb.append("\t").append("option httpclose");
-            result.add(sb.toString());
+        boolean keepAliveEnabled = lbCmd.keepAliveEnabled;
+        boolean http = (publicPort == NetUtils.HTTP_PORT && !keepAliveEnabled);
+        if (http || httpbasedStickiness || sslOffloading) {
+            frontendConfigs.add("\tmode http");
+            String keepAliveLine = keepAliveEnabled ? "\tno option forceclose" : "\toption httpclose";
+            frontendConfigs.add(keepAliveLine);
         }
 
+        // add line like this: "listen  65_37_141_30-80\n\tbind 65.37.141.30:80"
+        result.add(String.format("listen %s", poolName));
+        result.addAll(frontendConfigs);
+
         String cidrList = lbTO.getCidrList();
 
         if (StringUtils.isNotBlank(cidrList)) {
             result.add(String.format("\tacl network_allowed src %s \n\ttcp-request connection reject if !network_allowed", cidrList));
         }
 
+        result.addAll(backendConfigs);
         result.add(blankLine);
         return result;
     }
 
     private String generateStatsRule(final LoadBalancerConfigCommand lbCmd, final String ruleName, final String statsIp) {
         final StringBuilder rule = new StringBuilder("\nlisten ").append(ruleName).append("\n\tbind ").append(statsIp).append(":").append(lbCmd.lbStatsPort);
         // TODO DH: write test for this in both cases
-        if (!lbCmd.keepAliveEnabled) {
-            logger.info("Haproxy mode http enabled");
-            rule.append("\n\tmode http\n\toption httpclose");
+        rule.append("\n\tmode http");
+        if (lbCmd.keepAliveEnabled) {
+            logger.info("Haproxy option http-keep-alive enabled");
+        } else {
+            logger.info("Haproxy option httpclose enabled");
+            rule.append("\n\toption httpclose");
         }
         rule.append("\n\tstats enable\n\tstats uri     ")
-        .append(lbCmd.lbStatsUri)
-        .append("\n\tstats realm   Haproxy\\ Statistics\n\tstats auth    ")
-        .append(lbCmd.lbStatsAuth);
-        rule.append("\n");
+                .append(lbCmd.lbStatsUri)
+                .append("\n\tstats realm   Haproxy\\ Statistics\n\tstats auth    ")
+                .append(lbCmd.lbStatsAuth)
+                .append("\n");

Review Comment:
   this is auto-formatted by intelliJ IDEA. I guess it is ok ?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3209828322

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3258613085

   <b>[SF] Trillian test result (tid-14217)</b>
   Environment: kvm-ubuntu22 (x2), zone: Advanced Networking with Mgmt server u22
   Total time taken: 57677 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14217-kvm-ubuntu22.zip
   Smoke tests completed. 147 look OK, 0 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3257643776

   
   @blueorangutan package
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3254181833

   Packaging result [SF]: ✔️ el8 ✖️ el9  ✔️ debian ✖️ suse15. SL-JID 14850


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3239931121

   @blueorangutan test


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3240569575

   <b>[SF] Trillian test result (tid-14156)</b>
   Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
   Total time taken: 54131 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14156-kvm-ol8.zip
   Smoke tests completed. 146 look OK, 1 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   test_04_rvpc_network_garbage_collector_nics | `Failure` | 1452.31 | test_vpc_redundant.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3235893467

   @borisstoyanov a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3236142279

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3199962762

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2293490356


##########
core/src/main/java/com/cloud/network/HAProxyConfigurator.java:
##########
@@ -520,61 +544,69 @@ private List<String> getRulesForPool(final LoadBalancerTO lbTO, final boolean ke
             destsAvailable = true;
         }
 
-        Boolean httpbasedStickiness = false;
+        boolean httpbasedStickiness = false;
         /* attach stickiness sub rule only if the destinations are available */
-        if (stickinessSubRule != null && destsAvailable == true) {
+        if (stickinessSubRule != null && destsAvailable) {
             for (final StickinessPolicyTO stickinessPolicy : lbTO.getStickinessPolicies()) {
                 if (stickinessPolicy == null) {
                     continue;
                 }
                 if (StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName()) ||
                         StickinessMethodType.AppCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) {
                     httpbasedStickiness = true;
+                    break;
                 }
             }
             if (httpbasedStickiness) {
-                result.addAll(dstWithCookieSubRule);
+                backendConfigs.addAll(dstWithCookieSubRule);
             } else {
-                result.addAll(dstSubRule);
+                backendConfigs.addAll(dstSubRule);
             }
-            result.add(stickinessSubRule);
+            backendConfigs.add(stickinessSubRule);
         } else {
-            result.addAll(dstSubRule);
+            backendConfigs.addAll(dstSubRule);
         }
         if (stickinessSubRule != null && !destsAvailable) {
             logger.warn("Haproxy stickiness policy for lb rule: " + lbTO.getSrcIp() + ":" + lbTO.getSrcPort() + ": Not Applied, cause:  backends are unavailable");
         }
-        if (publicPort == NetUtils.HTTP_PORT && !keepAliveEnabled || httpbasedStickiness) {
-            sb = new StringBuilder();
-            sb.append("\t").append("mode http");
-            result.add(sb.toString());
-            sb = new StringBuilder();
-            sb.append("\t").append("option httpclose");
-            result.add(sb.toString());
+        boolean keepAliveEnabled = lbCmd.keepAliveEnabled;
+        boolean http = (publicPort == NetUtils.HTTP_PORT && !keepAliveEnabled);
+        if (http || httpbasedStickiness || sslOffloading) {
+            frontendConfigs.add("\tmode http");
+            String keepAliveLine = keepAliveEnabled ? "\tno option forceclose" : "\toption httpclose";
+            frontendConfigs.add(keepAliveLine);
         }
 
+        // add line like this: "listen  65_37_141_30-80\n\tbind 65.37.141.30:80"
+        result.add(String.format("listen %s", poolName));
+        result.addAll(frontendConfigs);
+
         String cidrList = lbTO.getCidrList();
 
         if (StringUtils.isNotBlank(cidrList)) {
             result.add(String.format("\tacl network_allowed src %s \n\ttcp-request connection reject if !network_allowed", cidrList));
         }
 
+        result.addAll(backendConfigs);
         result.add(blankLine);
         return result;
     }
 
     private String generateStatsRule(final LoadBalancerConfigCommand lbCmd, final String ruleName, final String statsIp) {
         final StringBuilder rule = new StringBuilder("\nlisten ").append(ruleName).append("\n\tbind ").append(statsIp).append(":").append(lbCmd.lbStatsPort);
         // TODO DH: write test for this in both cases
-        if (!lbCmd.keepAliveEnabled) {
-            logger.info("Haproxy mode http enabled");
-            rule.append("\n\tmode http\n\toption httpclose");
+        rule.append("\n\tmode http");
+        if (lbCmd.keepAliveEnabled) {
+            logger.info("Haproxy option http-keep-alive enabled");
+        } else {
+            logger.info("Haproxy option httpclose enabled");
+            rule.append("\n\toption httpclose");
         }
         rule.append("\n\tstats enable\n\tstats uri     ")
-        .append(lbCmd.lbStatsUri)
-        .append("\n\tstats realm   Haproxy\\ Statistics\n\tstats auth    ")
-        .append(lbCmd.lbStatsAuth);
-        rule.append("\n");
+                .append(lbCmd.lbStatsUri)
+                .append("\n\tstats realm   Haproxy\\ Statistics\n\tstats auth    ")
+                .append(lbCmd.lbStatsAuth)
+                .append("\n");

Review Comment:
   normally I replace tab with 4 spaces.
   
   maybe caused by the indentation rules in java ?
   
   <img width="1098" height="432" alt="image" src="https://github.com/user-attachments/assets/acb798c9-eec0-4c5d-ba7f-f3343408aee1" />
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3213502544

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "borisstoyanov (via GitHub)" <gi...@apache.org>.
borisstoyanov commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3235892085

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3236372669

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ debian ✔️ suse15. SL-JID 14765


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3274072233

   > > [SF] Trillian test result (tid-14236) Environment: vmware-80u3 (x2), zone: Advanced Networking with Mgmt server ol8 Total time taken: 80726 seconds Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14236-vmware-80u3.zip Smoke tests completed. 145 look OK, 2 have errors, 0 did not run Only failed and skipped tests results shown below:
   > > Test	Result	Time (s)	Test File
   > > ContextSuite context=TestSharedFSLifecycle>:setup	`Error`	0.00	test_sharedfs_lifecycle.py
   > > test_01_ssl_offloading_isolated_network	`Failure`	1882.23	test_ssl_offloading.py
   > > test_01_ssl_offloading_isolated_network	`Error`	1882.26	test_ssl_offloading.py
   > > test_02_ssl_offloading_project_vpc	`Error`	712.65	test_ssl_offloading.py
   > > test_02_ssl_offloading_project_vpc	`Error`	712.66	test_ssl_offloading.py
   > > ContextSuite context=TestSslOffloading>:teardown	`Error`	843.72	test_ssl_offloading.py
   > 
   > @weizhouapache this might be a potential issue, in Marvin logs I see bunch of: `"Exception: Warning: Exception during cleanup : HTTPConnectionPool(host='10.0.34.57', port=8080): Max retries exceeded with url: /client/api?jobid=f30b4774-a137-4419-8b08-92ab4fbf418c&command=queryAsyncJobResult&response=json&apiKey=LIN6rqXuaJwMPfGYFh13qDwYz5VNNz1J2J6qIOWcd3oLQOq0WtD4CwRundBL6rzXToa3lQOC_vKjI3nkHtiD8Q&signature=RzxkJU6oHq5zTGOYHIfarU%2BnNTo%3D (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f0bfa438550>: Failed to establish a new connection: [Errno 110] Connection timed out'))\n"]`
   
   thanks @borisstoyanov looking into it
   it looks like the mgmt server is not reachable, probably out-of-memory, let me re-kick the test
   
   the failures with `test_ssl_offloading.py` is caused the cloud-init template for vmware (ubuntu 22.04 cloud image does not work)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "borisstoyanov (via GitHub)" <gi...@apache.org>.
borisstoyanov commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3232819964

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "borisstoyanov (via GitHub)" <gi...@apache.org>.
borisstoyanov commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3253642169

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3254994482

   Packaging result [SF]: ✖️ el8 ✖️ el9  ✖️ debian ✖️ suse15. SL-JID 14851


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3239412912

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3248843948

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3257645042

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291146178


##########
server/src/main/java/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java:
##########
@@ -1294,8 +1294,13 @@ public boolean assignCertToLoadBalancer(long lbRuleId, Long certId) {
 
         //check if the lb is already bound
         LoadBalancerCertMapVO certMapRule = _lbCertMapDao.findByLbRuleId(loadBalancer.getId());
-        if (certMapRule != null)
-            throw new InvalidParameterValueException("Another certificate is already bound to the LB");
+        if (certMapRule != null) {
+            if (!forced) {
+                throw new InvalidParameterValueException("Another certificate is already bound to the LB");
+            }
+            logger.debug("Another certificate is already bound to the LB, removing it");
+            removeCertFromLoadBalancer(lbRuleId);
+        }

Review Comment:
   will do



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291185777


##########
server/src/main/java/org/apache/cloudstack/network/ssl/CertServiceImpl.java:
##########
@@ -423,19 +432,47 @@ private void validateChain(final List<Certificate> chain, final Certificate cert
 
     }
 
-    public PrivateKey parsePrivateKey(final String key) throws IOException {
+    public PrivateKey parsePrivateKey(final String key, String password) throws IOException, OperatorCreationException, PKCSException, NoSuchAlgorithmException, InvalidKeySpecException {
         Preconditions.checkArgument(StringUtils.isNotEmpty(key));
-        try (final PemReader pemReader = new PemReader(new StringReader(key));) {
-            final PemObject pemObject = pemReader.readPemObject();
-            final byte[] content = pemObject.getContent();
-            final PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
-            final KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
-            return factory.generatePrivate(privKeySpec);
-        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
-            throw new IOException("No encryption provider available.", e);
-        } catch (final InvalidKeySpecException e) {
-            throw new IOException("Invalid Key format.", e);
+        PEMParser pemParser = new PEMParser(new StringReader(key));
+        Object privateKeyObj = pemParser.readObject();
+        if (privateKeyObj == null) {
+            throw new CloudRuntimeException("Cannot parse private key");
+        }
+        PrivateKey privateKey;
+        if (privateKeyObj instanceof PKCS8EncryptedPrivateKeyInfo) {
+            if (password == null) {
+                throw new CloudRuntimeException("Key is encrypted by PKCS#8 but password is null");
+            }
+            PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo)privateKeyObj;
+            JceOpenSSLPKCS8DecryptorProviderBuilder builder = new JceOpenSSLPKCS8DecryptorProviderBuilder();
+            InputDecryptorProvider decryptor = builder.build(password.toCharArray());
+
+            PrivateKeyInfo privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(decryptor);
+            String algorithm = privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm().getId();
+            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded());
+            return keyFactory.generatePrivate(keySpec);

Review Comment:
   added method `parsePKCS8EncryptedPrivateKeyInfo`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291168940


##########
server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java:
##########
@@ -929,6 +929,11 @@ public boolean validateHAProxyLBRule(final LoadBalancingRule rule) {
             return false;
         }
 
+        List<String> lbProtocols = Arrays.asList("tcp", "udp", "tcp-proxy", "ssl");
+        if (rule.getLbProtocol() != null && !lbProtocols.contains(rule.getLbProtocol())) {
+            throw new InvalidParameterValueException("protocol " + rule.getLbProtocol() + " is not in valid protocols " + lbProtocols);
+        }

Review Comment:
   add new method `validateHAproxyLbProtocol`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3211036911

   
   @blueorangutan package
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3211300308

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ debian ✔️ suse15. SL-JID 14699


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3232819446

   <b>[SF] Trillian Build Failed (tid-14124)<b/>


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3257263106

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3245991438

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 14820


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3239824459

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3257920414

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 14872


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3238788699

   <b>[SF] Trillian test result (tid-14135)</b>
   Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
   Total time taken: 52730 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14135-kvm-ol8.zip
   Smoke tests completed. 146 look OK, 1 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   test_10_reboot_cpvm_forced | `Error` | 9.38 | test_ssvm.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3239929780

   @blueorangutan test ol8 vmware-80u3


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3238910968

   <b>[SF] Trillian test result (tid-14141)</b>
   Environment: kvm-ubuntu22 (x2), zone: Advanced Networking with Mgmt server u22
   Total time taken: 54590 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14141-kvm-ubuntu22.zip
   Smoke tests completed. 147 look OK, 0 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291195205


##########
server/src/main/java/org/apache/cloudstack/network/ssl/CertServiceImpl.java:
##########
@@ -423,19 +432,47 @@ private void validateChain(final List<Certificate> chain, final Certificate cert
 
     }
 
-    public PrivateKey parsePrivateKey(final String key) throws IOException {
+    public PrivateKey parsePrivateKey(final String key, String password) throws IOException, OperatorCreationException, PKCSException, NoSuchAlgorithmException, InvalidKeySpecException {
         Preconditions.checkArgument(StringUtils.isNotEmpty(key));
-        try (final PemReader pemReader = new PemReader(new StringReader(key));) {
-            final PemObject pemObject = pemReader.readPemObject();
-            final byte[] content = pemObject.getContent();
-            final PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
-            final KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
-            return factory.generatePrivate(privKeySpec);
-        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
-            throw new IOException("No encryption provider available.", e);
-        } catch (final InvalidKeySpecException e) {
-            throw new IOException("Invalid Key format.", e);
+        PEMParser pemParser = new PEMParser(new StringReader(key));
+        Object privateKeyObj = pemParser.readObject();
+        if (privateKeyObj == null) {
+            throw new CloudRuntimeException("Cannot parse private key");
+        }
+        PrivateKey privateKey;
+        if (privateKeyObj instanceof PKCS8EncryptedPrivateKeyInfo) {
+            if (password == null) {
+                throw new CloudRuntimeException("Key is encrypted by PKCS#8 but password is null");
+            }
+            PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo)privateKeyObj;
+            JceOpenSSLPKCS8DecryptorProviderBuilder builder = new JceOpenSSLPKCS8DecryptorProviderBuilder();
+            InputDecryptorProvider decryptor = builder.build(password.toCharArray());
+
+            PrivateKeyInfo privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(decryptor);
+            String algorithm = privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm().getId();
+            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded());
+            return keyFactory.generatePrivate(keySpec);
+        } else if (privateKeyObj instanceof PEMEncryptedKeyPair) {
+            if (password == null) {
+                throw new CloudRuntimeException("Key is encrypted but password is null");
+            }
+            PEMEncryptedKeyPair encryptedKeyPair = (PEMEncryptedKeyPair)privateKeyObj;
+            privateKey = new JcaPEMKeyConverter().getKeyPair(
+                    encryptedKeyPair.decryptKeyPair(new JcePEMDecryptorProviderBuilder().build(password.toCharArray()))).getPrivate();
+        } else if (privateKeyObj instanceof PEMKeyPair) {
+            // Key pair
+            PEMKeyPair pemKeyPair = (PEMKeyPair) privateKeyObj;
+            privateKey = new JcaPEMKeyConverter().getKeyPair(pemKeyPair).getPrivate();
+        } else if (privateKeyObj instanceof PrivateKeyInfo) {
+            // Private key only
+            PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo) privateKeyObj;
+            privateKey = new JcaPEMKeyConverter().getPrivateKey(privateKeyInfo);
+        } else {
+            throw new IllegalArgumentException("Unsupported PEM object: " + privateKeyObj.getClass());
         }

Review Comment:
   chatgpt says 
   ```
   To get the runtime type: obj.getClass() → works in Java 17 and 21.
   ```
   
   I guess it is ok ?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3255925283

   @blueorangutan test matrix


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3254331231

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3249057410

   @borisstoyanov a [SL] Trillian-Jenkins matrix job (EL8 mgmt + EL8 KVM, Ubuntu22 mgmt + Ubuntu22 KVM, EL8 mgmt + VMware 7.0u3, EL9 mgmt + XCP-ng 8.2 ) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3248841823

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "borisstoyanov (via GitHub)" <gi...@apache.org>.
borisstoyanov commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3248770520

   Close/reopen to re-kick the static code analysis tools 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3259646685

   <b>[SF] Trillian test result (tid-14219)</b>
   Environment: xcpng82 (x2), zone: Advanced Networking with Mgmt server ol9
   Total time taken: 77763 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14219-xcpng82.zip
   Smoke tests completed. 140 look OK, 7 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   test_01_events_resource | `Error` | 213.62 | test_events_resource.py
   test_01_non_strict_host_anti_affinity | `Error` | 211.39 | test_nonstrict_affinity_group.py
   test_02_non_strict_host_affinity | `Error` | 52.20 | test_nonstrict_affinity_group.py
   test_01_primary_storage_iscsi | `Error` | 0.77 | test_primary_storage.py
   test_05_disk_offering_strictness_true | `Failure` | 631.83 | test_service_offerings.py
   test_01_volume_usage | `Error` | 100.31 | test_usage.py
   test_01_vpn_usage | `Error` | 1.11 | test_usage.py
   test_11_destroy_vm_and_volumes | `Error` | 26.19 | test_vm_life_cycle.py
   test_01_migrate_vm_strict_tags_success | `Error` | 63.38 | test_vm_strict_host_tags.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3209821388

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3211469867

   @blueorangutan test


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3213849387

   @blueorangutan test


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "borisstoyanov (via GitHub)" <gi...@apache.org>.
borisstoyanov commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3233056394

   @blueorangutan test matrix


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3255715402

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 14857


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3257606086

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 14870


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3257994868

   @blueorangutan test ol8 vmware-80u3


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3244774963

   <b>[SF] Trillian Build Failed (tid-14184)<b/>


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3245719927

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3252357724

   <b>[SF] Trillian test result (tid-14198)</b>
   Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
   Total time taken: 66238 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14198-kvm-ol8.zip
   Smoke tests completed. 147 look OK, 0 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "borisstoyanov (via GitHub)" <gi...@apache.org>.
borisstoyanov closed pull request #11468: Improvement: SSL offloading with Virtual Router
URL: https://github.com/apache/cloudstack/pull/11468


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3249025281

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✖️ debian ✔️ suse15. SL-JID 14828


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3253270926

   <b>[SF] Trillian test result (tid-14201)</b>
   Environment: xcpng82 (x2), zone: Advanced Networking with Mgmt server ol9
   Total time taken: 80808 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14201-xcpng82.zip
   Smoke tests completed. 141 look OK, 6 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   test_01_events_resource | `Error` | 216.30 | test_events_resource.py
   test_01_non_strict_host_anti_affinity | `Error` | 249.21 | test_nonstrict_affinity_group.py
   test_02_non_strict_host_affinity | `Error` | 58.70 | test_nonstrict_affinity_group.py
   test_01_primary_storage_iscsi | `Error` | 0.90 | test_primary_storage.py
   test_01_vpn_usage | `Error` | 1.12 | test_usage.py
   test_11_destroy_vm_and_volumes | `Error` | 23.27 | test_vm_life_cycle.py
   test_01_migrate_vm_strict_tags_success | `Error` | 55.45 | test_vm_strict_host_tags.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3272915393

   <b>[SF] Trillian test result (tid-14253)</b>
   Environment: vmware-80u3 (x2), zone: Advanced Networking with Mgmt server ol8
   Total time taken: 57207 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14253-vmware-80u3.zip
   Smoke tests completed. 127 look OK, 1 have errors, 19 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   test_01_volume_usage | `Error` | 94.40 | test_usage.py
   test_01_vpn_usage | `Error` | 1.12 | test_usage.py
   all_test_vm_autoscaling | `Skipped` | --- | test_vm_autoscaling.py
   all_test_vm_deployment_planner | `Skipped` | --- | test_vm_deployment_planner.py
   all_test_vm_life_cycle | `Skipped` | --- | test_vm_life_cycle.py
   all_test_vm_lifecycle_unmanage_import | `Skipped` | --- | test_vm_lifecycle_unmanage_import.py
   all_test_vm_lifecycle_with_snapshot_or_volume | `Skipped` | --- | test_vm_lifecycle_with_snapshot_or_volume.py
   all_test_vm_schedule | `Skipped` | --- | test_vm_schedule.py
   all_test_vm_snapshot_kvm | `Skipped` | --- | test_vm_snapshot_kvm.py
   all_test_vm_snapshots | `Skipped` | --- | test_vm_snapshots.py
   all_test_vm_strict_host_tags | `Skipped` | --- | test_vm_strict_host_tags.py
   all_test_vnf_templates | `Skipped` | --- | test_vnf_templates.py
   all_test_volumes | `Skipped` | --- | test_volumes.py
   all_test_vpc_ipv6 | `Skipped` | --- | test_vpc_ipv6.py
   all_test_vpc_redundant | `Skipped` | --- | test_vpc_redundant.py
   all_test_vpc_router_nics | `Skipped` | --- | test_vpc_router_nics.py
   all_test_vpc_vpn | `Skipped` | --- | test_vpc_vpn.py
   all_test_webhook_delivery | `Skipped` | --- | test_webhook_delivery.py
   all_test_webhook_lifecycle | `Skipped` | --- | test_webhook_lifecycle.py
   all_test_host_maintenance | `Skipped` | --- | test_host_maintenance.py
   all_test_hostha_kvm | `Skipped` | --- | test_hostha_kvm.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "DaanHoogland (via GitHub)" <gi...@apache.org>.
DaanHoogland commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2290534093


##########
core/src/main/java/com/cloud/network/HAProxyConfigurator.java:
##########
@@ -469,46 +477,62 @@ private String getLbSubRuleForStickiness(final LoadBalancerTO lbTO) {
         return sb.toString();
     }
 
-    private List<String> getRulesForPool(final LoadBalancerTO lbTO, final boolean keepAliveEnabled) {
+    private List<String> getRulesForPool(final LoadBalancerTO lbTO, final LoadBalancerConfigCommand lbCmd) {
         StringBuilder sb = new StringBuilder();
         final String poolName = sb.append(lbTO.getSrcIp().replace(".", "_")).append('-').append(lbTO.getSrcPort()).toString();
         final String publicIP = lbTO.getSrcIp();
         final int publicPort = lbTO.getSrcPort();
         final String algorithm = lbTO.getAlgorithm();
 
-        final List<String> result = new ArrayList<String>();
-        // add line like this: "listen  65_37_141_30-80\n\tbind 65.37.141.30:80"
-        sb = new StringBuilder();
-        sb.append("listen ").append(poolName);
-        result.add(sb.toString());
+        boolean sslOffloading = lbTO.getSslCert() != null && !lbTO.getSslCert().isRevoked()
+                && NetUtils.SSL_PROTO.equals(lbTO.getLbProtocol());
+
+        final List<String> frontendConfigs = new ArrayList<>();
+        final List<String> backendConfigs = new ArrayList<>();
+        final List<String> result = new ArrayList<>();
+
         sb = new StringBuilder();
         sb.append("\tbind ").append(publicIP).append(":").append(publicPort);
-        result.add(sb.toString());
+
+        if (sslOffloading) {
+            sb.append(" ssl crt ").append(SSL_CERTS_DIR).append(poolName).append(".pem");
+            // check for http2 support
+            sb.append(" alpn h2,http/1.1");

Review Comment:
   Can you explain this, @weizhouapache ? is `alpn h2` enough to do the check? And is the backend stretch then http 1.1? or is it just the default for the frontend? (maybe a link to docs?)



##########
core/src/main/java/com/cloud/network/HAProxyConfigurator.java:
##########
@@ -696,4 +728,26 @@ public String[][] generateFwRules(final LoadBalancerConfigCommand lbCmd) {
 
         return result;
     }
+
+    @Override
+    public SslCertEntry[] generateSslCertEntries(LoadBalancerConfigCommand lbCmd) {
+        final Set<SslCertEntry> sslCertEntries = new HashSet<SslCertEntry>();
+        for (final LoadBalancerTO lbTO : lbCmd.getLoadBalancers()) {
+            if (lbTO.getSslCert() != null) {
+                final LbSslCert cert = lbTO.getSslCert();
+                if (cert.isRevoked()) {
+                    continue;
+                }
+                if (lbTO.getLbProtocol() == null || ! lbTO.getLbProtocol().equals(NetUtils.SSL_PROTO)) {
+                    continue;
+                }
+                StringBuilder sb = new StringBuilder();
+                final String name = sb.append(lbTO.getSrcIp().replace(".", "_")).append('-').append(lbTO.getSrcPort()).toString();
+                final SslCertEntry sslCertEntry = new SslCertEntry(name, cert.getCert(), cert.getKey(), cert.getChain(), cert.getPassword());
+                sslCertEntries.add(sslCertEntry);

Review Comment:
   ```suggestion
                   addCertEntry(sslCertEntries, lbTO);
   ```
   
   and then 
   ```
       private void addSslCertEntry(Collection<SslCertEntry> sslCertEntries, LoadBalancerTO lbTO) {
           final LbSslCert cert = lbTO.getSslCert();
           if (cert.isRevoked()) {
               return;
           }
           if (lbTO.getLbProtocol() == null || ! lbTO.getLbProtocol().equals(NetUtils.SSL_PROTO)) {
               return;
           }
           StringBuilder sb = new StringBuilder();
           final String name = lbTO.getSrcIp().replace(".", "_”) + ’-‘ + lbTO.getSrcPort());
           sslCertEntries.add(new SslCertEntry(name, cert.getCert(), cert.getKey(), cert.getChain(), cert.getPassword()));
       }
   ```
   sorry , I know I’m a nag and a purist….



##########
server/src/main/java/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java:
##########
@@ -1294,8 +1294,13 @@ public boolean assignCertToLoadBalancer(long lbRuleId, Long certId) {
 
         //check if the lb is already bound
         LoadBalancerCertMapVO certMapRule = _lbCertMapDao.findByLbRuleId(loadBalancer.getId());
-        if (certMapRule != null)
-            throw new InvalidParameterValueException("Another certificate is already bound to the LB");
+        if (certMapRule != null) {
+            if (!forced) {
+                throw new InvalidParameterValueException("Another certificate is already bound to the LB");
+            }
+            logger.debug("Another certificate is already bound to the LB, removing it");
+            removeCertFromLoadBalancer(lbRuleId);
+        }

Review Comment:
   new method; validatenewMapRule(..)?



##########
server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java:
##########
@@ -929,6 +929,11 @@ public boolean validateHAProxyLBRule(final LoadBalancingRule rule) {
             return false;
         }
 
+        List<String> lbProtocols = Arrays.asList("tcp", "udp", "tcp-proxy", "ssl");
+        if (rule.getLbProtocol() != null && !lbProtocols.contains(rule.getLbProtocol())) {
+            throw new InvalidParameterValueException("protocol " + rule.getLbProtocol() + " is not in valid protocols " + lbProtocols);
+        }

Review Comment:
   new validation method..



##########
core/src/main/java/com/cloud/network/HAProxyConfigurator.java:
##########
@@ -520,61 +544,69 @@ private List<String> getRulesForPool(final LoadBalancerTO lbTO, final boolean ke
             destsAvailable = true;
         }
 
-        Boolean httpbasedStickiness = false;
+        boolean httpbasedStickiness = false;
         /* attach stickiness sub rule only if the destinations are available */
-        if (stickinessSubRule != null && destsAvailable == true) {
+        if (stickinessSubRule != null && destsAvailable) {
             for (final StickinessPolicyTO stickinessPolicy : lbTO.getStickinessPolicies()) {
                 if (stickinessPolicy == null) {
                     continue;
                 }
                 if (StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName()) ||
                         StickinessMethodType.AppCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) {
                     httpbasedStickiness = true;
+                    break;
                 }
             }
             if (httpbasedStickiness) {
-                result.addAll(dstWithCookieSubRule);
+                backendConfigs.addAll(dstWithCookieSubRule);
             } else {
-                result.addAll(dstSubRule);
+                backendConfigs.addAll(dstSubRule);
             }
-            result.add(stickinessSubRule);
+            backendConfigs.add(stickinessSubRule);
         } else {
-            result.addAll(dstSubRule);
+            backendConfigs.addAll(dstSubRule);
         }
         if (stickinessSubRule != null && !destsAvailable) {
             logger.warn("Haproxy stickiness policy for lb rule: " + lbTO.getSrcIp() + ":" + lbTO.getSrcPort() + ": Not Applied, cause:  backends are unavailable");
         }
-        if (publicPort == NetUtils.HTTP_PORT && !keepAliveEnabled || httpbasedStickiness) {
-            sb = new StringBuilder();
-            sb.append("\t").append("mode http");
-            result.add(sb.toString());
-            sb = new StringBuilder();
-            sb.append("\t").append("option httpclose");
-            result.add(sb.toString());
+        boolean keepAliveEnabled = lbCmd.keepAliveEnabled;
+        boolean http = (publicPort == NetUtils.HTTP_PORT && !keepAliveEnabled);
+        if (http || httpbasedStickiness || sslOffloading) {
+            frontendConfigs.add("\tmode http");
+            String keepAliveLine = keepAliveEnabled ? "\tno option forceclose" : "\toption httpclose";
+            frontendConfigs.add(keepAliveLine);
         }
 
+        // add line like this: "listen  65_37_141_30-80\n\tbind 65.37.141.30:80"
+        result.add(String.format("listen %s", poolName));
+        result.addAll(frontendConfigs);
+
         String cidrList = lbTO.getCidrList();
 
         if (StringUtils.isNotBlank(cidrList)) {
             result.add(String.format("\tacl network_allowed src %s \n\ttcp-request connection reject if !network_allowed", cidrList));
         }
 
+        result.addAll(backendConfigs);
         result.add(blankLine);
         return result;
     }
 
     private String generateStatsRule(final LoadBalancerConfigCommand lbCmd, final String ruleName, final String statsIp) {
         final StringBuilder rule = new StringBuilder("\nlisten ").append(ruleName).append("\n\tbind ").append(statsIp).append(":").append(lbCmd.lbStatsPort);
         // TODO DH: write test for this in both cases
-        if (!lbCmd.keepAliveEnabled) {
-            logger.info("Haproxy mode http enabled");
-            rule.append("\n\tmode http\n\toption httpclose");
+        rule.append("\n\tmode http");
+        if (lbCmd.keepAliveEnabled) {
+            logger.info("Haproxy option http-keep-alive enabled");
+        } else {
+            logger.info("Haproxy option httpclose enabled");
+            rule.append("\n\toption httpclose");
         }
         rule.append("\n\tstats enable\n\tstats uri     ")
-        .append(lbCmd.lbStatsUri)
-        .append("\n\tstats realm   Haproxy\\ Statistics\n\tstats auth    ")
-        .append(lbCmd.lbStatsAuth);
-        rule.append("\n");
+                .append(lbCmd.lbStatsUri)
+                .append("\n\tstats realm   Haproxy\\ Statistics\n\tstats auth    ")
+                .append(lbCmd.lbStatsAuth)
+                .append("\n");

Review Comment:
   ```suggestion
               .append(lbCmd.lbStatsUri)
               .append("\n\tstats realm   Haproxy\\ Statistics\n\tstats auth    ")
               .append(lbCmd.lbStatsAuth)
               .append("\n");
   ```



##########
server/src/main/java/org/apache/cloudstack/network/ssl/CertServiceImpl.java:
##########
@@ -423,19 +432,47 @@ private void validateChain(final List<Certificate> chain, final Certificate cert
 
     }
 
-    public PrivateKey parsePrivateKey(final String key) throws IOException {
+    public PrivateKey parsePrivateKey(final String key, String password) throws IOException, OperatorCreationException, PKCSException, NoSuchAlgorithmException, InvalidKeySpecException {
         Preconditions.checkArgument(StringUtils.isNotEmpty(key));
-        try (final PemReader pemReader = new PemReader(new StringReader(key));) {
-            final PemObject pemObject = pemReader.readPemObject();
-            final byte[] content = pemObject.getContent();
-            final PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
-            final KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
-            return factory.generatePrivate(privKeySpec);
-        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
-            throw new IOException("No encryption provider available.", e);
-        } catch (final InvalidKeySpecException e) {
-            throw new IOException("Invalid Key format.", e);
+        PEMParser pemParser = new PEMParser(new StringReader(key));
+        Object privateKeyObj = pemParser.readObject();
+        if (privateKeyObj == null) {
+            throw new CloudRuntimeException("Cannot parse private key");
+        }
+        PrivateKey privateKey;
+        if (privateKeyObj instanceof PKCS8EncryptedPrivateKeyInfo) {
+            if (password == null) {
+                throw new CloudRuntimeException("Key is encrypted by PKCS#8 but password is null");
+            }
+            PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo)privateKeyObj;
+            JceOpenSSLPKCS8DecryptorProviderBuilder builder = new JceOpenSSLPKCS8DecryptorProviderBuilder();
+            InputDecryptorProvider decryptor = builder.build(password.toCharArray());
+
+            PrivateKeyInfo privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(decryptor);
+            String algorithm = privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm().getId();
+            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded());
+            return keyFactory.generatePrivate(keySpec);
+        } else if (privateKeyObj instanceof PEMEncryptedKeyPair) {
+            if (password == null) {
+                throw new CloudRuntimeException("Key is encrypted but password is null");
+            }
+            PEMEncryptedKeyPair encryptedKeyPair = (PEMEncryptedKeyPair)privateKeyObj;
+            privateKey = new JcaPEMKeyConverter().getKeyPair(
+                    encryptedKeyPair.decryptKeyPair(new JcePEMDecryptorProviderBuilder().build(password.toCharArray()))).getPrivate();

Review Comment:
   createPEMEncryptedKey(..)



##########
server/src/main/java/org/apache/cloudstack/network/ssl/CertServiceImpl.java:
##########
@@ -423,19 +432,47 @@ private void validateChain(final List<Certificate> chain, final Certificate cert
 
     }
 
-    public PrivateKey parsePrivateKey(final String key) throws IOException {
+    public PrivateKey parsePrivateKey(final String key, String password) throws IOException, OperatorCreationException, PKCSException, NoSuchAlgorithmException, InvalidKeySpecException {
         Preconditions.checkArgument(StringUtils.isNotEmpty(key));
-        try (final PemReader pemReader = new PemReader(new StringReader(key));) {
-            final PemObject pemObject = pemReader.readPemObject();
-            final byte[] content = pemObject.getContent();
-            final PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
-            final KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
-            return factory.generatePrivate(privKeySpec);
-        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
-            throw new IOException("No encryption provider available.", e);
-        } catch (final InvalidKeySpecException e) {
-            throw new IOException("Invalid Key format.", e);
+        PEMParser pemParser = new PEMParser(new StringReader(key));
+        Object privateKeyObj = pemParser.readObject();
+        if (privateKeyObj == null) {
+            throw new CloudRuntimeException("Cannot parse private key");
+        }
+        PrivateKey privateKey;
+        if (privateKeyObj instanceof PKCS8EncryptedPrivateKeyInfo) {
+            if (password == null) {
+                throw new CloudRuntimeException("Key is encrypted by PKCS#8 but password is null");
+            }
+            PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo)privateKeyObj;
+            JceOpenSSLPKCS8DecryptorProviderBuilder builder = new JceOpenSSLPKCS8DecryptorProviderBuilder();
+            InputDecryptorProvider decryptor = builder.build(password.toCharArray());
+
+            PrivateKeyInfo privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(decryptor);
+            String algorithm = privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm().getId();
+            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded());
+            return keyFactory.generatePrivate(keySpec);
+        } else if (privateKeyObj instanceof PEMEncryptedKeyPair) {
+            if (password == null) {
+                throw new CloudRuntimeException("Key is encrypted but password is null");
+            }
+            PEMEncryptedKeyPair encryptedKeyPair = (PEMEncryptedKeyPair)privateKeyObj;
+            privateKey = new JcaPEMKeyConverter().getKeyPair(
+                    encryptedKeyPair.decryptKeyPair(new JcePEMDecryptorProviderBuilder().build(password.toCharArray()))).getPrivate();
+        } else if (privateKeyObj instanceof PEMKeyPair) {
+            // Key pair
+            PEMKeyPair pemKeyPair = (PEMKeyPair) privateKeyObj;
+            privateKey = new JcaPEMKeyConverter().getKeyPair(pemKeyPair).getPrivate();
+        } else if (privateKeyObj instanceof PrivateKeyInfo) {
+            // Private key only
+            PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo) privateKeyObj;
+            privateKey = new JcaPEMKeyConverter().getPrivateKey(privateKeyInfo);
+        } else {
+            throw new IllegalArgumentException("Unsupported PEM object: " + privateKeyObj.getClass());
         }

Review Comment:
   once we are ready for java21 we should convert to switch on type of `privateKeyObj`



##########
test/integration/smoke/test_ssl_offloading.py:
##########
@@ -0,0 +1,553 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from marvin.codes import FAILED
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import wait_until
+from marvin.lib.base import (Account,
+                             Project,
+                             UserData,
+                             SslCertificate,
+                             Template,
+                             NetworkOffering,
+                             ServiceOffering,
+                             VirtualMachine,
+                             Network,
+                             VPC,
+                             VpcOffering,
+                             PublicIPAddress,
+                             LoadBalancerRule)
+from marvin.lib.common import (get_domain, get_zone, get_test_template)
+from nose.plugins.attrib import attr
+
+import os
+import subprocess
+
+
+_multiprocess_shared_ = True
+
+DOMAIN = "test-ssl-offloading.cloudstack.org"
+CONTENT = "Test page"
+FULL_CHAIN = "/tmp/full_chain.crt"
+
+CERT = {
+    "privatekey": """-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCph7jsoMCQirRn
+3obuvgnnefTXRQYd9tF9k2aCVkTiiisvC39px7MGdgvDXADhD9fmR7oyXVQlfNu0
+rXjjgsVT3r4bv+DVi81YGXnuU7h10yCOZJt21i6QGHN1CS0/TAfg0UhlACCEYNRx
+kB0klwUcj/jk/AKil1DoUGpvAm2gZsek/njb76/AeIfxc+Es4ZOPCVqQOHp6gI0q
+t6KDMkUwv8fyzrpScygMUPVYrLmm6D0pn8yd3ihW07wGxMjND6UgOnao8t6H3LaM
+Pe7eqSFzxunF9NFFjnUrKcHZZSledDM/37Kbqb/8T5f+4SwjioS1OdPCh8ApdiXq
+HNUwYkALAgMBAAECggEAK5JiiQ7X7053B6s96uaVDRVfRGTNKa5iMXBNDHq3wbHZ
+X4IJAVr+PE7ivxdKco3r45fT11X9ZpUsssdTJsZZiTDak69BTiFcaaRCnmqOIlpd
+J7vb6TMrTIW8RvxQ0M/txm6DuNHLibqJX5a2pszZ13l5cwECfF9/v/XLJTTukCbu
+6D/f3fBVFl1tM8y9saOEYLkdb4dILWY61bVSDNswgprz2EV1SFnk5jxz2FuBrM/Q
++7hINvjDcaRvcm59hRb1rkljv7S10VoNw/CFkU451csJkUe4vWZwB8lZK/XxLQG0
+HEdS1zU1XY8H8Y1RCrxjGRyiiWsBtUThhWYlPrGCoQKBgQDkP09YAlKqXhT69Kx5
+keg2i1jV2hA73zWbWXt9xp5jG5r3pl3m170DvKL93YIDnHtpTC56mlzGrzS7DSTN
+p0buY9Qb3fkJxunCpPVFo0HMFkpeR77ax0v34NzSohlRLKFo5R2M1cmDfbVbnSSl
+MB57FfRRMxzjrk+dJvjOeJsxjwKBgQC+JLb4B8CZjpurXYg3ySiRqFsCqkqob+kf
+9dR+rWvcR6vMTEyha0hUlDvTikDepU2smYR4oPHfdcXF9lAJ7T02UmQDeizAqR68
+u9e+yS0q3tdRnPPZmXJfaDCXG1hKMqF4YA5Vs0XAjleF3zHB+vBLrnlPpShtd/Mu
+sWTpxICTxQKBgQDSr/n+pE5IQwYczOO0aFGwn5pF9L9NdPHXz5aleETV+TJn7WL6
+ZiRsoaDWs7SCvtxQS2kP9RM0t5/2FeDmEMXx4aZ2fsSWGM3IxVo+iL+Aswa81n8/
+Ff5y9lb/+29hNdBcsjk/ukwEG3Lf+UNNVAie15oppgPByzJkPwgmFsAy0wKBgHDX
+/TZp82WuerhSw/rHiSoYjhqg0bnw4Ju1Gy0q4q5SYqTWS0wpDT4U0wSSMjlwRQ6/
+9RxZ9/G0RXFc4tdhUkig0PY3VcPpGnLL0BhL8GBW69ZlnVpwdK4meV/UPKucLLPx
+3dACmszSLSMn+LG0qVNg8mHQFJQS8eGuKcOKePw5AoGACuxtefROKdKOALh4lTi2
+VOwPZ+1jxsm6lKNccIEvbUpe3UXPgNWpJiDX8mUcob4/NBLzmV3BUVKbG7Exbo5J
+LoMfp7OsztWUFwt7YAvRfS8fHdhkEsxEf3T72ADieH5ZAuXFF+K0H3r6HtWPD4ws
+mTJjGP4+Bl/dFakA5FJcjHg=
+-----END PRIVATE KEY-----""",
+    "certificate": """-----BEGIN CERTIFICATE-----
+MIIFKjCCAxKgAwIBAgIUJ7BtN56KI8OuzbbM8SdtCLCB2UgwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEG
+A1UECgwKQ2xvdWRTdGFjazEPMA0GA1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFj
+aGUwHhcNMjUwNjIzMTMxMzA3WhcNMzUwNjIxMTMxMzA3WjBoMQswCQYDVQQGEwJY
+WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMQ8wDQYDVQQKDAZBcGFjaGUxEzAR
+BgNVBAsMCkNsb3VkU3RhY2sxGTAXBgNVBAMMECouY2xvdWRzdGFjay5vcmcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCph7jsoMCQirRn3obuvgnnefTX
+RQYd9tF9k2aCVkTiiisvC39px7MGdgvDXADhD9fmR7oyXVQlfNu0rXjjgsVT3r4b
+v+DVi81YGXnuU7h10yCOZJt21i6QGHN1CS0/TAfg0UhlACCEYNRxkB0klwUcj/jk
+/AKil1DoUGpvAm2gZsek/njb76/AeIfxc+Es4ZOPCVqQOHp6gI0qt6KDMkUwv8fy
+zrpScygMUPVYrLmm6D0pn8yd3ihW07wGxMjND6UgOnao8t6H3LaMPe7eqSFzxunF
+9NFFjnUrKcHZZSledDM/37Kbqb/8T5f+4SwjioS1OdPCh8ApdiXqHNUwYkALAgMB
+AAGjgdUwgdIwKwYDVR0RBCQwIoIQKi5jbG91ZHN0YWNrLm9yZ4IOY2xvdWRzdGFj
+ay5vcmcwHQYDVR0OBBYEFCcq7jrdsqTD+Xi85DCqjYdL1gOqMIGDBgNVHSMEfDB6
+oWKkYDBeMQswCQYDVQQGEwJYWDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMRMw
+EQYDVQQKDApDbG91ZFN0YWNrMQ8wDQYDVQQLDAZBcGFjaGUxDzANBgNVBAMMBkFw
+YWNoZYIURVB9+qvRJyOnJnqmYOw467vW3vQwDQYJKoZIhvcNAQELBQADggIBACld
+lEXgn/A4/kZQbLwwMxBvaoPDDaDaYVpPbOoPw7a8YkrL0rmPIc04PyX9GAqxdC+c
+qaEXvmp3I+BdT13XGcBosXO8uEQ3kses9F3MhOHORPS2mJag7t4eLnNX/0CgKTlR
+6yC2Gu7d3xPNJ+CKMxekdoF31StEFNAYI/La/q3D+IGsRCbrVu3xpPaw2XlXI7Ro
+RU7yebVmQPSNc75bm8Ydo1cdYtz9h8PVnc+6ThhSrdS3jYScj9DrX5ZJaKuZqSlu
+0ZqFXoBflme+cYB7nb9HqnIO67r9vzd2dTcErJVAk5jQqG5Y38d1tingDx1A5opU
+z4BkXEbHNV6VXYUQ5VE0dXO2sNvXVJrstwMPE8d3EvbX/1gWj8kuymbskrCjySE4
+4Yztkb0dsJkVU793lz3EV75DsXvj3gevK049nPv2Grt1+rTgFNa6NJnLvKIKk/mv
+fWjxbK2b/AAJ1ci6xtw/vKmIWoEu6uEMIJmhfBwuP+VnVJWJbmYXpNW/L5g21B76
+Fn8RuQa3mlm5lZrxEcJ/b6fF+2NPJwj7sh6l688VtNXoVSSyXUeV5HwqCv+YMjKn
+CtwpEN/eNHMbrkJvgYwSoOzqhV/wpmNi28S7MOm66JMECHOXOhk/eX2chIEjiVna
+MXhvr/Twfj2N4gNVtcgXkrk39HEYjk5+uF7SdNf4
+-----END CERTIFICATE-----""",
+    "certchain": """-----BEGIN CERTIFICATE-----
+MIIFQzCCAysCFEVQffqr0ScjpyZ6pmDsOOu71t70MA0GCSqGSIb3DQEBCwUAMF4x
+CzAJBgNVBAYTAlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxEzARBgNVBAoM
+CkNsb3VkU3RhY2sxDzANBgNVBAsMBkFwYWNoZTEPMA0GA1UEAwwGQXBhY2hlMB4X
+DTI1MDYxNjEwMjc1NloXDTMwMDYxNTEwMjc1NlowXjELMAkGA1UEBhMCWFgxCzAJ
+BgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEGA1UECgwKQ2xvdWRTdGFjazEPMA0G
+A1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFjaGUwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQCLiQmSjrht15R1F+r79m/LZN5hsfQBGp+dy+yrtsWfOOur
+RdXAwgbLxxsyKMQKWCQxlRI7wdhqh0L0ZBrIr9MjltYqsqLAoLmgY4eG/f6G8YGr
+O/rxzfwTLbCeaIseF/OMA6Sz125HXYp1bltYK4LsuC7tihZXbeVa5pUGs3Jwgcfx
+LYm4eB42Hp7Eg05uL8LbwT/1AjcwoWkTewKAWXA83zgLRDFDbl1t0IPHI4cdVvia
+BNwNbG49ZCF6OgmokSarQSe4Vbems1u9T9pAySXAVjEYBqFjKWyswpdr782uNLmB
+lCGm0pDeJ9/WASxbTJr7k9H6ZpnaHr54DG6ZqennWMz8w6r2pf7bp/EGZ3mZQ4s3
+5ylSP4cQt8CSSI8k2CflPGUyytUAiWlDS3qSyIuAOPKXDg7wIpcbwcu4VMeKnH0Z
+x7Uu9j1UDZEZoSu6UI/VInTl47k1/ECD+AO9yBzZSv+pTQmO3/Im3CcxsTHmVd5s
+Tl0CJ/jWNpo9DAMtmGvt6CBWBXGRsO2XNk7djRcq2CubiCpvODg+7CcR6CiZK73L
+1aOisLiq3+ofiJSSXRRuKtJlkQ4eSPSbYWkNJcKmIhbCoYOdH/Pe3/+RHjvNc1kO
+OUb+icmfzcMVAs3C5jybpazsfjDNQZXWAFx4FLDcqOVbrCwom+tMukw+hzlZnwID
+AQABMA0GCSqGSIb3DQEBCwUAA4ICAQAdexoMwn+Ol1A3+NOHk9WJZX+t2Q8/9wWb
+K+jSVleSfXXWsB1mC3fABVJQdCxtXCH3rpt4w7FK6aUes9VjqAHap4tt9WBq0Wqq
+vvMURFHfllxEM31Z35kBOCSQY9xwpGV1rRh/zYs4h55YixomR3nXNZ9cI8xzlSCi
+sMG0mv0y+yxPohKrZj3AzLYz/M11SimSoyRPIANI+cUg1nJXyQoHzVHWEp1Nj0HB
+M/GW05cxsWea7f5YcAW1JQI3FOkpwb72fIZOtMDa4PO8IYWXJAeAc/chw745/MTi
+Rvl2NT4RZBAcrSNbhCOzRPG/ZiG+ArQuCluZ9HHAXRBMTtlLk5DO4+XxZlyGpjwf
+uKniK8dccy9uU0ho73p9SNDhXH0yb9Naj8vd9NWzCUYaaBXt/92cIyhaAHAVFxJu
+o6jr2FLbnhSGF9EO/tHvF7LxZv1dnbInvlWHwoFQjwmoeB+e17lHBdPMnWnPKBZe
+jA2VH/IzGCucWuWQhruummO5GT8Z6F4jBwvafBo+QARKPZgEBpx3LycXrpkYI3LT
+GGOpGCxFt5tVZOEsC/jQ5rIljNSeTzWmzfNRn/yRUW97uWsrzcQIBAUtu/pQnyFQ
+WCnC1ipCp1zhJsXAFUKuqEfLngXodOvC4tAOr76h11S57o5lN4506Poq2mWgAZe/
+JZr9MEn1+w==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFnzCCA4egAwIBAgIUcUNMqgWoDLsvMj0YmEudj60EG5swDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEG
+A1UECgwKQ2xvdWRTdGFjazEPMA0GA1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFj
+aGUwIBcNMjUwNjE2MTAyNzM2WhgPMjEyNTA1MjMxMDI3MzZaMF4xCzAJBgNVBAYT
+AlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxEzARBgNVBAoMCkNsb3VkU3Rh
+Y2sxDzANBgNVBAsMBkFwYWNoZTEPMA0GA1UEAwwGQXBhY2hlMIICIjANBgkqhkiG
+9w0BAQEFAAOCAg8AMIICCgKCAgEAwVQaePulUM523gKw168ToYp+gt05bXbu4Gg8
+uaRDKhnRAX1sEgYwkQ36Q+iTDEM9sKRma8lMNMIqkZMQdk6sIGX6BL+6wUOb7mL0
+5+I0yO9i8ooaGgNaeNvZftNIRlLsnPMGJaeom2/66XV4CsMqoZKaJ1H/I8N+bAeD
+GvrBx+B4l9D3G390nQvot9JUzrJgGuLl0KDHapvhlR39cCgEfIii02uX1iy0qXlV
+b+G1kLvpeC7T+lsJxondPJ69aO3lbDv/izyWw7qqBC57UhT/oKDxJmjQqklqzhgt
+nM/p3YE7M0nkRi3LnRmsZBz7o1DRf+M29zypKzXVk1aJflL46AtLMmpDIzVrEB2M
+q7o47rstXusYRYsBCqGTgdI1fV/CkDsZY5XkPZh2dsjZCHIS4P03OqFGsc6PQha2
++y2AhV1pvywkDl48kPKSukHfV1RtaPZUZtcQKztwHH+aFfo9mD8z0H2HcExdXKzd
+jhRhI9ZSwFj3HEN9f5P8fS3lf5+fV7EEbG4NisieBj/UivW6QiTHpLD7wRLIUt2g
+XgXNF0lfJzYHbIcxQ6kfC5McU2fu6mUC+p/pNN8G0POS3S2T55tEUqLL4N0SadQy
+N1TZlTd2xTn+Hb6WlG0f5m97xGcNlGHKBvntFrHvOIfkEQ9ne3MlOO1Gjlintowo
+fRGf15kCAwEAAaNTMFEwHQYDVR0OBBYEFM4WEQJpN9M07Q8CHq+5owG93Dj8MB8G
+A1UdIwQYMBaAFM4WEQJpN9M07Q8CHq+5owG93Dj8MA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQELBQADggIBABr5RKGc/rKx4fOgyXNJR4aCJCTtPZKs4AUCCBYz
+cWOjJYGNvThOPSVx51nAD8+YP2BwkOIPfhl2u/+vQSSbz4OlauXLki2DUN8E2OFe
+gJfxPDzWOfAo/QOJcyHwSlnIQjiZzG2lK3eyf5IFnfQILQzDvXaUYvMBkl2hb5Q7
+44H6tRw78uuf/KsT4rY0bBFMN5DayjiyvoIDUvzCRqcb2KOi9DnZ7pXjduL7tO0j
+PhlQ24B77LVUUAvydIGUzmbhGC2VvY1qE7uaYgYtgSUZ0zSjJrHjUjVLMzRouNP7
+jpbBQRAcP4FDcOFZBHogunA0hxQdm0d8u3LqDYPNS0rpfW0ddU/72nfBX4bnoDEN
++anw4wOgFuUcoEThALWZ9ESVKxXQ9Fpvd6FRW8fLLqhXAuli1BqP1c1WRxagldYe
+nPGm/FGZyJ2xOak9Uigi9NAQ/vX6CEfgcJgFZmCo8EKH0d4Ut72vGUcPqiUhT2EI
+AFAd6drSyoUdXXniSMWky9Vrt+qtLuAD1nhHTv8ZPdItXokoiD6ea/4xrbUZn0qY
+lLMDyfY76UVF0ruTR2Q6IdSq/zSggdwgkTooOW4XZcRf5l/ZnoeVQ1QH9C85SIKH
+IKZwPeGUm+EntmpuCBDmQSHLRCGEThd64iOAjqLR6arLj4TBJzBrZsGHFJbm0OcI
+dwa9
+-----END CERTIFICATE-----""",
+    "enabledrevocationcheck": False
+}
+
+USER_DATA="""I2Nsb3VkLWNvbmZpZwoKcnVuY21kOgogIC0gc3VkbyBhcHQtZ2V0IHVwZGF0Z
+QogIC0gc3VkbyBhcHQtZ2V0IGluc3RhbGwgLXkgYXBhY2hlMgogIC0gc3Vkby
+BzeXN0ZW1jdGwgZW5hYmxlIGFwYWNoZTIKICAtIHN1ZG8gc3lzdGVtY3RsIHN0
+YXJ0IGFwYWNoZTIKICAtIGVjaG8gIlRlc3QgcGFnZSIgfHN1ZG8gdGVlIC92YX
+Ivd3d3L2h0bWwvaW5kZXguaHRtbAoKCg=="""
+
+class TestSslOffloading(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+
+        testClient = super(TestSslOffloading, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls._cleanup = []
+
+        # Get Zone, Domain and templates
+        cls.domain = get_domain(cls.apiclient)
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.hypervisor = testClient.getHypervisorInfo()
+
+        cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+
+        #Create an account, network, VM and IP addresses
+        cls.account = Account.create(
+                            cls.apiclient,
+                            cls.services["account"],
+                            admin=True,
+                            domainid=cls.domain.id
+                            )
+        cls.user = cls.account.user[0]
+        cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name)
+
+        # Save full chain as a file
+        with open(FULL_CHAIN, "w", encoding="utf-8") as f:
+            f.write(CERT["certchain"])
+
+        # Register template if needed
+        if cls.hypervisor.lower() == 'simulator':
+            cls.template = get_test_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.hypervisor)
+        else:
+            cls.template = Template.register(
+                cls.apiclient,
+                cls.services["test_templates_cloud_init"][cls.hypervisor.lower()],
+                zoneid=cls.zone.id,
+                hypervisor=cls.hypervisor,
+            )
+            cls.template.download(cls.apiclient)
+            cls._cleanup.append(cls.template)
+
+        if cls.template == FAILED:
+            assert False, "get_test_template() failed to return template"
+
+        # Create service offering
+        cls.service_offering = ServiceOffering.create(
+                                        cls.apiclient,
+                                        cls.services["service_offerings"]["big"]    # 512MB memory
+                                        )
+
+        # Create network offering
+        cls.services["isolated_network_offering"]["egress_policy"] = "true"
+        cls.network_offering = NetworkOffering.create(cls.apiclient,
+                                                      cls.services["isolated_network_offering"],
+                                                      conservemode=True)
+        cls.network_offering.update(cls.apiclient, state='Enabled')
+
+        cls._cleanup.append(cls.network_offering)
+        cls._cleanup.append(cls.service_offering)
+        cls._cleanup.append(cls.account)

Review Comment:
   should be right after creation, to deal with the case something goes wrong during initialisation.



##########
server/src/main/java/org/apache/cloudstack/network/ssl/CertServiceImpl.java:
##########
@@ -423,19 +432,47 @@ private void validateChain(final List<Certificate> chain, final Certificate cert
 
     }
 
-    public PrivateKey parsePrivateKey(final String key) throws IOException {
+    public PrivateKey parsePrivateKey(final String key, String password) throws IOException, OperatorCreationException, PKCSException, NoSuchAlgorithmException, InvalidKeySpecException {
         Preconditions.checkArgument(StringUtils.isNotEmpty(key));
-        try (final PemReader pemReader = new PemReader(new StringReader(key));) {
-            final PemObject pemObject = pemReader.readPemObject();
-            final byte[] content = pemObject.getContent();
-            final PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
-            final KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
-            return factory.generatePrivate(privKeySpec);
-        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
-            throw new IOException("No encryption provider available.", e);
-        } catch (final InvalidKeySpecException e) {
-            throw new IOException("Invalid Key format.", e);
+        PEMParser pemParser = new PEMParser(new StringReader(key));
+        Object privateKeyObj = pemParser.readObject();
+        if (privateKeyObj == null) {
+            throw new CloudRuntimeException("Cannot parse private key");
+        }
+        PrivateKey privateKey;
+        if (privateKeyObj instanceof PKCS8EncryptedPrivateKeyInfo) {
+            if (password == null) {
+                throw new CloudRuntimeException("Key is encrypted by PKCS#8 but password is null");
+            }
+            PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo)privateKeyObj;
+            JceOpenSSLPKCS8DecryptorProviderBuilder builder = new JceOpenSSLPKCS8DecryptorProviderBuilder();
+            InputDecryptorProvider decryptor = builder.build(password.toCharArray());
+
+            PrivateKeyInfo privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(decryptor);
+            String algorithm = privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm().getId();
+            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded());
+            return keyFactory.generatePrivate(keySpec);

Review Comment:
   method createPKCS8Key(..)



##########
test/integration/smoke/test_ssl_offloading.py:
##########
@@ -0,0 +1,553 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from marvin.codes import FAILED
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import wait_until
+from marvin.lib.base import (Account,
+                             Project,
+                             UserData,
+                             SslCertificate,
+                             Template,
+                             NetworkOffering,
+                             ServiceOffering,
+                             VirtualMachine,
+                             Network,
+                             VPC,
+                             VpcOffering,
+                             PublicIPAddress,
+                             LoadBalancerRule)
+from marvin.lib.common import (get_domain, get_zone, get_test_template)
+from nose.plugins.attrib import attr
+
+import os
+import subprocess
+
+
+_multiprocess_shared_ = True
+
+DOMAIN = "test-ssl-offloading.cloudstack.org"
+CONTENT = "Test page"
+FULL_CHAIN = "/tmp/full_chain.crt"
+
+CERT = {
+    "privatekey": """-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCph7jsoMCQirRn
+3obuvgnnefTXRQYd9tF9k2aCVkTiiisvC39px7MGdgvDXADhD9fmR7oyXVQlfNu0
+rXjjgsVT3r4bv+DVi81YGXnuU7h10yCOZJt21i6QGHN1CS0/TAfg0UhlACCEYNRx
+kB0klwUcj/jk/AKil1DoUGpvAm2gZsek/njb76/AeIfxc+Es4ZOPCVqQOHp6gI0q
+t6KDMkUwv8fyzrpScygMUPVYrLmm6D0pn8yd3ihW07wGxMjND6UgOnao8t6H3LaM
+Pe7eqSFzxunF9NFFjnUrKcHZZSledDM/37Kbqb/8T5f+4SwjioS1OdPCh8ApdiXq
+HNUwYkALAgMBAAECggEAK5JiiQ7X7053B6s96uaVDRVfRGTNKa5iMXBNDHq3wbHZ
+X4IJAVr+PE7ivxdKco3r45fT11X9ZpUsssdTJsZZiTDak69BTiFcaaRCnmqOIlpd
+J7vb6TMrTIW8RvxQ0M/txm6DuNHLibqJX5a2pszZ13l5cwECfF9/v/XLJTTukCbu
+6D/f3fBVFl1tM8y9saOEYLkdb4dILWY61bVSDNswgprz2EV1SFnk5jxz2FuBrM/Q
++7hINvjDcaRvcm59hRb1rkljv7S10VoNw/CFkU451csJkUe4vWZwB8lZK/XxLQG0
+HEdS1zU1XY8H8Y1RCrxjGRyiiWsBtUThhWYlPrGCoQKBgQDkP09YAlKqXhT69Kx5
+keg2i1jV2hA73zWbWXt9xp5jG5r3pl3m170DvKL93YIDnHtpTC56mlzGrzS7DSTN
+p0buY9Qb3fkJxunCpPVFo0HMFkpeR77ax0v34NzSohlRLKFo5R2M1cmDfbVbnSSl
+MB57FfRRMxzjrk+dJvjOeJsxjwKBgQC+JLb4B8CZjpurXYg3ySiRqFsCqkqob+kf
+9dR+rWvcR6vMTEyha0hUlDvTikDepU2smYR4oPHfdcXF9lAJ7T02UmQDeizAqR68
+u9e+yS0q3tdRnPPZmXJfaDCXG1hKMqF4YA5Vs0XAjleF3zHB+vBLrnlPpShtd/Mu
+sWTpxICTxQKBgQDSr/n+pE5IQwYczOO0aFGwn5pF9L9NdPHXz5aleETV+TJn7WL6
+ZiRsoaDWs7SCvtxQS2kP9RM0t5/2FeDmEMXx4aZ2fsSWGM3IxVo+iL+Aswa81n8/
+Ff5y9lb/+29hNdBcsjk/ukwEG3Lf+UNNVAie15oppgPByzJkPwgmFsAy0wKBgHDX
+/TZp82WuerhSw/rHiSoYjhqg0bnw4Ju1Gy0q4q5SYqTWS0wpDT4U0wSSMjlwRQ6/
+9RxZ9/G0RXFc4tdhUkig0PY3VcPpGnLL0BhL8GBW69ZlnVpwdK4meV/UPKucLLPx
+3dACmszSLSMn+LG0qVNg8mHQFJQS8eGuKcOKePw5AoGACuxtefROKdKOALh4lTi2
+VOwPZ+1jxsm6lKNccIEvbUpe3UXPgNWpJiDX8mUcob4/NBLzmV3BUVKbG7Exbo5J
+LoMfp7OsztWUFwt7YAvRfS8fHdhkEsxEf3T72ADieH5ZAuXFF+K0H3r6HtWPD4ws
+mTJjGP4+Bl/dFakA5FJcjHg=
+-----END PRIVATE KEY-----""",
+    "certificate": """-----BEGIN CERTIFICATE-----
+MIIFKjCCAxKgAwIBAgIUJ7BtN56KI8OuzbbM8SdtCLCB2UgwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEG
+A1UECgwKQ2xvdWRTdGFjazEPMA0GA1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFj
+aGUwHhcNMjUwNjIzMTMxMzA3WhcNMzUwNjIxMTMxMzA3WjBoMQswCQYDVQQGEwJY
+WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMQ8wDQYDVQQKDAZBcGFjaGUxEzAR
+BgNVBAsMCkNsb3VkU3RhY2sxGTAXBgNVBAMMECouY2xvdWRzdGFjay5vcmcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCph7jsoMCQirRn3obuvgnnefTX
+RQYd9tF9k2aCVkTiiisvC39px7MGdgvDXADhD9fmR7oyXVQlfNu0rXjjgsVT3r4b
+v+DVi81YGXnuU7h10yCOZJt21i6QGHN1CS0/TAfg0UhlACCEYNRxkB0klwUcj/jk
+/AKil1DoUGpvAm2gZsek/njb76/AeIfxc+Es4ZOPCVqQOHp6gI0qt6KDMkUwv8fy
+zrpScygMUPVYrLmm6D0pn8yd3ihW07wGxMjND6UgOnao8t6H3LaMPe7eqSFzxunF
+9NFFjnUrKcHZZSledDM/37Kbqb/8T5f+4SwjioS1OdPCh8ApdiXqHNUwYkALAgMB
+AAGjgdUwgdIwKwYDVR0RBCQwIoIQKi5jbG91ZHN0YWNrLm9yZ4IOY2xvdWRzdGFj
+ay5vcmcwHQYDVR0OBBYEFCcq7jrdsqTD+Xi85DCqjYdL1gOqMIGDBgNVHSMEfDB6
+oWKkYDBeMQswCQYDVQQGEwJYWDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMRMw
+EQYDVQQKDApDbG91ZFN0YWNrMQ8wDQYDVQQLDAZBcGFjaGUxDzANBgNVBAMMBkFw
+YWNoZYIURVB9+qvRJyOnJnqmYOw467vW3vQwDQYJKoZIhvcNAQELBQADggIBACld
+lEXgn/A4/kZQbLwwMxBvaoPDDaDaYVpPbOoPw7a8YkrL0rmPIc04PyX9GAqxdC+c
+qaEXvmp3I+BdT13XGcBosXO8uEQ3kses9F3MhOHORPS2mJag7t4eLnNX/0CgKTlR
+6yC2Gu7d3xPNJ+CKMxekdoF31StEFNAYI/La/q3D+IGsRCbrVu3xpPaw2XlXI7Ro
+RU7yebVmQPSNc75bm8Ydo1cdYtz9h8PVnc+6ThhSrdS3jYScj9DrX5ZJaKuZqSlu
+0ZqFXoBflme+cYB7nb9HqnIO67r9vzd2dTcErJVAk5jQqG5Y38d1tingDx1A5opU
+z4BkXEbHNV6VXYUQ5VE0dXO2sNvXVJrstwMPE8d3EvbX/1gWj8kuymbskrCjySE4
+4Yztkb0dsJkVU793lz3EV75DsXvj3gevK049nPv2Grt1+rTgFNa6NJnLvKIKk/mv
+fWjxbK2b/AAJ1ci6xtw/vKmIWoEu6uEMIJmhfBwuP+VnVJWJbmYXpNW/L5g21B76
+Fn8RuQa3mlm5lZrxEcJ/b6fF+2NPJwj7sh6l688VtNXoVSSyXUeV5HwqCv+YMjKn
+CtwpEN/eNHMbrkJvgYwSoOzqhV/wpmNi28S7MOm66JMECHOXOhk/eX2chIEjiVna
+MXhvr/Twfj2N4gNVtcgXkrk39HEYjk5+uF7SdNf4
+-----END CERTIFICATE-----""",
+    "certchain": """-----BEGIN CERTIFICATE-----
+MIIFQzCCAysCFEVQffqr0ScjpyZ6pmDsOOu71t70MA0GCSqGSIb3DQEBCwUAMF4x
+CzAJBgNVBAYTAlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxEzARBgNVBAoM
+CkNsb3VkU3RhY2sxDzANBgNVBAsMBkFwYWNoZTEPMA0GA1UEAwwGQXBhY2hlMB4X
+DTI1MDYxNjEwMjc1NloXDTMwMDYxNTEwMjc1NlowXjELMAkGA1UEBhMCWFgxCzAJ
+BgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEGA1UECgwKQ2xvdWRTdGFjazEPMA0G
+A1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFjaGUwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQCLiQmSjrht15R1F+r79m/LZN5hsfQBGp+dy+yrtsWfOOur
+RdXAwgbLxxsyKMQKWCQxlRI7wdhqh0L0ZBrIr9MjltYqsqLAoLmgY4eG/f6G8YGr
+O/rxzfwTLbCeaIseF/OMA6Sz125HXYp1bltYK4LsuC7tihZXbeVa5pUGs3Jwgcfx
+LYm4eB42Hp7Eg05uL8LbwT/1AjcwoWkTewKAWXA83zgLRDFDbl1t0IPHI4cdVvia
+BNwNbG49ZCF6OgmokSarQSe4Vbems1u9T9pAySXAVjEYBqFjKWyswpdr782uNLmB
+lCGm0pDeJ9/WASxbTJr7k9H6ZpnaHr54DG6ZqennWMz8w6r2pf7bp/EGZ3mZQ4s3
+5ylSP4cQt8CSSI8k2CflPGUyytUAiWlDS3qSyIuAOPKXDg7wIpcbwcu4VMeKnH0Z
+x7Uu9j1UDZEZoSu6UI/VInTl47k1/ECD+AO9yBzZSv+pTQmO3/Im3CcxsTHmVd5s
+Tl0CJ/jWNpo9DAMtmGvt6CBWBXGRsO2XNk7djRcq2CubiCpvODg+7CcR6CiZK73L
+1aOisLiq3+ofiJSSXRRuKtJlkQ4eSPSbYWkNJcKmIhbCoYOdH/Pe3/+RHjvNc1kO
+OUb+icmfzcMVAs3C5jybpazsfjDNQZXWAFx4FLDcqOVbrCwom+tMukw+hzlZnwID
+AQABMA0GCSqGSIb3DQEBCwUAA4ICAQAdexoMwn+Ol1A3+NOHk9WJZX+t2Q8/9wWb
+K+jSVleSfXXWsB1mC3fABVJQdCxtXCH3rpt4w7FK6aUes9VjqAHap4tt9WBq0Wqq
+vvMURFHfllxEM31Z35kBOCSQY9xwpGV1rRh/zYs4h55YixomR3nXNZ9cI8xzlSCi
+sMG0mv0y+yxPohKrZj3AzLYz/M11SimSoyRPIANI+cUg1nJXyQoHzVHWEp1Nj0HB
+M/GW05cxsWea7f5YcAW1JQI3FOkpwb72fIZOtMDa4PO8IYWXJAeAc/chw745/MTi
+Rvl2NT4RZBAcrSNbhCOzRPG/ZiG+ArQuCluZ9HHAXRBMTtlLk5DO4+XxZlyGpjwf
+uKniK8dccy9uU0ho73p9SNDhXH0yb9Naj8vd9NWzCUYaaBXt/92cIyhaAHAVFxJu
+o6jr2FLbnhSGF9EO/tHvF7LxZv1dnbInvlWHwoFQjwmoeB+e17lHBdPMnWnPKBZe
+jA2VH/IzGCucWuWQhruummO5GT8Z6F4jBwvafBo+QARKPZgEBpx3LycXrpkYI3LT
+GGOpGCxFt5tVZOEsC/jQ5rIljNSeTzWmzfNRn/yRUW97uWsrzcQIBAUtu/pQnyFQ
+WCnC1ipCp1zhJsXAFUKuqEfLngXodOvC4tAOr76h11S57o5lN4506Poq2mWgAZe/
+JZr9MEn1+w==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFnzCCA4egAwIBAgIUcUNMqgWoDLsvMj0YmEudj60EG5swDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEG
+A1UECgwKQ2xvdWRTdGFjazEPMA0GA1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFj
+aGUwIBcNMjUwNjE2MTAyNzM2WhgPMjEyNTA1MjMxMDI3MzZaMF4xCzAJBgNVBAYT
+AlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxEzARBgNVBAoMCkNsb3VkU3Rh
+Y2sxDzANBgNVBAsMBkFwYWNoZTEPMA0GA1UEAwwGQXBhY2hlMIICIjANBgkqhkiG
+9w0BAQEFAAOCAg8AMIICCgKCAgEAwVQaePulUM523gKw168ToYp+gt05bXbu4Gg8
+uaRDKhnRAX1sEgYwkQ36Q+iTDEM9sKRma8lMNMIqkZMQdk6sIGX6BL+6wUOb7mL0
+5+I0yO9i8ooaGgNaeNvZftNIRlLsnPMGJaeom2/66XV4CsMqoZKaJ1H/I8N+bAeD
+GvrBx+B4l9D3G390nQvot9JUzrJgGuLl0KDHapvhlR39cCgEfIii02uX1iy0qXlV
+b+G1kLvpeC7T+lsJxondPJ69aO3lbDv/izyWw7qqBC57UhT/oKDxJmjQqklqzhgt
+nM/p3YE7M0nkRi3LnRmsZBz7o1DRf+M29zypKzXVk1aJflL46AtLMmpDIzVrEB2M
+q7o47rstXusYRYsBCqGTgdI1fV/CkDsZY5XkPZh2dsjZCHIS4P03OqFGsc6PQha2
++y2AhV1pvywkDl48kPKSukHfV1RtaPZUZtcQKztwHH+aFfo9mD8z0H2HcExdXKzd
+jhRhI9ZSwFj3HEN9f5P8fS3lf5+fV7EEbG4NisieBj/UivW6QiTHpLD7wRLIUt2g
+XgXNF0lfJzYHbIcxQ6kfC5McU2fu6mUC+p/pNN8G0POS3S2T55tEUqLL4N0SadQy
+N1TZlTd2xTn+Hb6WlG0f5m97xGcNlGHKBvntFrHvOIfkEQ9ne3MlOO1Gjlintowo
+fRGf15kCAwEAAaNTMFEwHQYDVR0OBBYEFM4WEQJpN9M07Q8CHq+5owG93Dj8MB8G
+A1UdIwQYMBaAFM4WEQJpN9M07Q8CHq+5owG93Dj8MA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQELBQADggIBABr5RKGc/rKx4fOgyXNJR4aCJCTtPZKs4AUCCBYz
+cWOjJYGNvThOPSVx51nAD8+YP2BwkOIPfhl2u/+vQSSbz4OlauXLki2DUN8E2OFe
+gJfxPDzWOfAo/QOJcyHwSlnIQjiZzG2lK3eyf5IFnfQILQzDvXaUYvMBkl2hb5Q7
+44H6tRw78uuf/KsT4rY0bBFMN5DayjiyvoIDUvzCRqcb2KOi9DnZ7pXjduL7tO0j
+PhlQ24B77LVUUAvydIGUzmbhGC2VvY1qE7uaYgYtgSUZ0zSjJrHjUjVLMzRouNP7
+jpbBQRAcP4FDcOFZBHogunA0hxQdm0d8u3LqDYPNS0rpfW0ddU/72nfBX4bnoDEN
++anw4wOgFuUcoEThALWZ9ESVKxXQ9Fpvd6FRW8fLLqhXAuli1BqP1c1WRxagldYe
+nPGm/FGZyJ2xOak9Uigi9NAQ/vX6CEfgcJgFZmCo8EKH0d4Ut72vGUcPqiUhT2EI
+AFAd6drSyoUdXXniSMWky9Vrt+qtLuAD1nhHTv8ZPdItXokoiD6ea/4xrbUZn0qY
+lLMDyfY76UVF0ruTR2Q6IdSq/zSggdwgkTooOW4XZcRf5l/ZnoeVQ1QH9C85SIKH
+IKZwPeGUm+EntmpuCBDmQSHLRCGEThd64iOAjqLR6arLj4TBJzBrZsGHFJbm0OcI
+dwa9
+-----END CERTIFICATE-----""",
+    "enabledrevocationcheck": False
+}
+
+USER_DATA="""I2Nsb3VkLWNvbmZpZwoKcnVuY21kOgogIC0gc3VkbyBhcHQtZ2V0IHVwZGF0Z
+QogIC0gc3VkbyBhcHQtZ2V0IGluc3RhbGwgLXkgYXBhY2hlMgogIC0gc3Vkby
+BzeXN0ZW1jdGwgZW5hYmxlIGFwYWNoZTIKICAtIHN1ZG8gc3lzdGVtY3RsIHN0
+YXJ0IGFwYWNoZTIKICAtIGVjaG8gIlRlc3QgcGFnZSIgfHN1ZG8gdGVlIC92YX
+Ivd3d3L2h0bWwvaW5kZXguaHRtbAoKCg=="""
+
+class TestSslOffloading(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+
+        testClient = super(TestSslOffloading, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls._cleanup = []
+
+        # Get Zone, Domain and templates
+        cls.domain = get_domain(cls.apiclient)
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.hypervisor = testClient.getHypervisorInfo()
+
+        cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+
+        #Create an account, network, VM and IP addresses
+        cls.account = Account.create(
+                            cls.apiclient,
+                            cls.services["account"],
+                            admin=True,
+                            domainid=cls.domain.id
+                            )
+        cls.user = cls.account.user[0]
+        cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name)
+
+        # Save full chain as a file
+        with open(FULL_CHAIN, "w", encoding="utf-8") as f:
+            f.write(CERT["certchain"])
+
+        # Register template if needed
+        if cls.hypervisor.lower() == 'simulator':
+            cls.template = get_test_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.hypervisor)
+        else:
+            cls.template = Template.register(
+                cls.apiclient,
+                cls.services["test_templates_cloud_init"][cls.hypervisor.lower()],
+                zoneid=cls.zone.id,
+                hypervisor=cls.hypervisor,
+            )
+            cls.template.download(cls.apiclient)
+            cls._cleanup.append(cls.template)
+
+        if cls.template == FAILED:
+            assert False, "get_test_template() failed to return template"
+
+        # Create service offering
+        cls.service_offering = ServiceOffering.create(
+                                        cls.apiclient,
+                                        cls.services["service_offerings"]["big"]    # 512MB memory
+                                        )
+
+        # Create network offering
+        cls.services["isolated_network_offering"]["egress_policy"] = "true"
+        cls.network_offering = NetworkOffering.create(cls.apiclient,
+                                                      cls.services["isolated_network_offering"],
+                                                      conservemode=True)
+        cls.network_offering.update(cls.apiclient, state='Enabled')
+
+        cls._cleanup.append(cls.network_offering)
+        cls._cleanup.append(cls.service_offering)
+        cls._cleanup.append(cls.account)
+
+    def setUp(self):
+        self.apiclient = self.testClient.getApiClient()
+        self.cleanup = []
+
+    def tearDown(self):
+        super(TestSslOffloading, self).tearDown()
+
+    @classmethod
+    def tearDownClass(cls):
+        super(TestSslOffloading, cls).tearDownClass()
+        if os.path.exists(FULL_CHAIN):
+            os.remove(FULL_CHAIN)
+
+    def wait_for_service_ready(self, command, expected, retries=60):
+        output = None
+        def check_output():
+            try:
+                output = subprocess.check_output(command, shell=True).strip().decode('utf-8')
+            except Exception as e:
+                print("Failed to get output of command %s: %s" % (command, e))
+                if expected is None:
+                    print("But it is expected")
+                    return True, None
+                return False, None
+            print("Output of command %s: \n %s" %(command, output))
+            if expected is None:
+                print("But it is expected to be None")
+                return False, None
+            return (expected in output), None
+
+        res = wait_until(10, retries, check_output)
+        if not res:
+            self.fail("Failed to wait for http server to show content '%s'. The output is '%s'" % (expected, output))
+        return res
+
+    @attr(tags = ["advanced", "advancedns", "smoke"], required_hardware="true")
+    def test_01_ssl_offloading_isolated_network(self):
+        """Test to create Load balancing rule with SSL offloading"""
+
+        # Validate:
+        # 1. Create isolated network and vm instance
+        # 2. create LB with port 80 -> 80, verify the website (should get expected content)
+        # 3. create LB with port 443 -> 80, verify the website (should not work)
+        # 4. add cert to LB with port 443
+        # 5. verify the website (should get expected content)
+        # 6. remove cert from LB with port 443
+        # 7. delete SSL certificate
+
+        # Register Userdata
+        self.userdata = UserData.register(self.apiclient,
+                                         name="test-userdata",
+                                         userdata=USER_DATA,
+                                         account=self.account.name,
+                                         domainid=self.account.domainid
+                                         )
+
+        # Upload SSL Certificate
+        self.sslcert = SslCertificate.create(self.apiclient,
+                                            CERT,
+                                            name="test-ssl-certificate",
+                                            account=self.account.name,
+                                            domainid=self.account.domainid)
+
+        # 1. Create network
+        self.network = Network.create(self.apiclient,
+                                      zoneid=self.zone.id,
+                                      services=self.services["network"],
+                                      domainid=self.domain.id,
+                                      account=self.account.name,
+                                      networkofferingid=self.network_offering.id)
+        self.cleanup.append(self.network)
+
+        self.services["virtual_machine"]["networkids"] = [str(self.network.id)]
+
+        # Create vm instance
+        self.vm_1 = VirtualMachine.create(
+            self.apiclient,
+            self.services["virtual_machine"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            userdataid=self.userdata.userdata.id,
+            serviceofferingid=self.service_offering.id
+        )
+        self.cleanup.append(self.vm_1)
+
+        self.public_ip = PublicIPAddress.create(
+            self.apiclient,
+            self.account.name,
+            self.zone.id,
+            self.account.domainid,
+            self.services["virtual_machine"],
+            self.network.id)
+
+        # 2. create LB with port 80 -> 80, verify the website (should get expected content).
+        # firewall is open by default
+        lb_http = {
+            "name": "http",
+            "alg": "roundrobin",
+            "privateport": 80,
+            "publicport": 80,
+            "protocol": "tcp"
+        }
+        lb_rule_http = LoadBalancerRule.create(
+            self.apiclient,
+            lb_http,
+            self.public_ip.ipaddress.id,
+            accountid=self.account.name,
+            domainid=self.domain.id,
+            networkid=self.network.id
+        )
+        lb_rule_http.assign(self.apiclient, [self.vm_1])
+        command = "curl -L --connect-timeout 3 http://%s/" % self.public_ip.ipaddress.ipaddress
+        # wait 10 minutes until the webpage is available. it returns "503 Service Unavailable" if not available
+        self.wait_for_service_ready(command, CONTENT, 60)
+
+        # 3. create LB with port 443 -> 80, verify the website (should not work)
+        # firewall is open by default
+        lb_https = {
+            "name": "https",
+            "alg": "roundrobin",
+            "privateport": 80,
+            "publicport": 443,
+            "protocol": "ssl"
+        }
+        lb_rule_https = LoadBalancerRule.create(
+            self.apiclient,
+            lb_https,
+            self.public_ip.ipaddress.id,
+            accountid=self.account.name,
+            domainid=self.domain.id,
+            networkid=self.network.id
+        )
+        lb_rule_https.assign(self.apiclient, [self.vm_1])
+
+        command = "curl -L --connect-timeout 3 -k --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, None, 1)
+
+        command = "curl -L --connect-timeout 3 --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, None, 1)
+
+        # 4. add cert to LB with port 443
+        lb_rule_https.assignCert(self.apiclient, self.sslcert.id)
+
+        # 5. verify the website (should get expected content)
+        command = "curl -L --connect-timeout 3 --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, "SSL certificate problem", 1)
+
+        command = "curl -L --connect-timeout 3 -k --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, CONTENT, 1)
+
+        command = "curl -L --connect-timeout 3 --cacert %s --resolve %s:443:%s https://%s/" % (FULL_CHAIN, DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, CONTENT, 1)
+
+        # 6. remove cert from LB with port 443
+        lb_rule_https.removeCert(self.apiclient)
+
+        # 7. delete SSL certificate
+        self.sslcert.delete(self.apiclient)
+
+    @attr(tags = ["advanced", "advancedns", "smoke"], required_hardware="true")
+    def test_02_ssl_offloading_project_vpc(self):
+        """Test to create Load balancing rule with SSL offloading in VPC in user project"""
+
+        # Validate:
+        # 1. Create VPC, VPC tier and vm instance
+        # 2. create LB with port 80 -> 80, verify the website (should get expected content)
+        # 3. create LB with port 443 -> 80, verify the website (should not work)
+        # 4. add cert to LB with port 443
+        # 5. verify the website (should get expected content)
+        # 6. remove cert from LB with port 443
+        # 7. delete SSL certificate
+
+        # Create project by user
+        self.project = Project.create(
+            self.userapiclient,
+            self.services["project"]
+        )
+        self.cleanup.append(self.project)
+
+        # Register Userdata by user
+        self.userdata = UserData.register(self.userapiclient,
+                                          name="test-user-userdata",
+                                          userdata=USER_DATA,
+                                          projectid=self.project.id
+                                          )
+
+        # Upload SSL Certificate by user
+        self.sslcert = SslCertificate.create(self.userapiclient,
+                                             CERT,
+                                             name="test-user-ssl-certificate",
+                                             projectid=self.project.id
+                                             )
+
+        # 1. Create VPC and VPC tier
+        vpcOffering = VpcOffering.list(self.userapiclient, name="Default VPC offering")
+        self.assertTrue(vpcOffering is not None and len(
+            vpcOffering) > 0, "No VPC offerings found")
+
+        self.vpc = VPC.create(
+            apiclient=self.userapiclient,
+            services=self.services["vpc_vpn"]["vpc"],
+            vpcofferingid=vpcOffering[0].id,
+            zoneid=self.zone.id,
+            projectid=self.project.id
+        )
+        self.cleanup.append(self.vpc)
+
+        networkOffering = NetworkOffering.list(
+            self.userapiclient, name="DefaultIsolatedNetworkOfferingForVpcNetworks")
+        self.assertTrue(networkOffering is not None and len(
+            networkOffering) > 0, "No VPC based network offering")
+
+        self.network = Network.create(
+            apiclient=self.userapiclient,
+            services=self.services["vpc_vpn"]["network_1"],
+            networkofferingid=networkOffering[0].id,
+            zoneid=self.zone.id,
+            vpcid=self.vpc.id,
+            projectid=self.project.id
+        )
+        self.cleanup.append(self.network)
+
+        self.services["virtual_machine"]["networkids"] = [str(self.network.id)]
+
+        # Create vm instance
+        self.vm_2 = VirtualMachine.create(
+            self.userapiclient,
+            self.services["virtual_machine"],
+            templateid=self.template.id,
+            userdataid=self.userdata.userdata.id,
+            serviceofferingid=self.service_offering.id,
+            projectid=self.project.id
+        )
+        self.cleanup.append(self.vm_2)
+
+        self.public_ip = PublicIPAddress.create(
+            self.userapiclient,
+            zoneid=self.zone.id,
+            services=self.services["virtual_machine"],
+            networkid=self.network.id,
+            vpcid=self.vpc.id,
+            projectid=self.project.id
+        )
+
+        # 2. create LB with port 80 -> 80, verify the website (should get expected content).
+        # firewall is open by default
+        lb_http = {
+            "name": "http",
+            "alg": "roundrobin",
+            "privateport": 80,
+            "publicport": 80,
+            "protocol": "tcp"
+        }
+        lb_rule_http = LoadBalancerRule.create(
+            self.userapiclient,
+            lb_http,
+            self.public_ip.ipaddress.id,
+            networkid=self.network.id,
+            projectid=self.project.id
+        )
+        lb_rule_http.assign(self.userapiclient, [self.vm_2])
+        command = "curl -L --connect-timeout 3 http://%s/" % self.public_ip.ipaddress.ipaddress
+        # wait 10 minutes until the webpage is available. it returns "503 Service Unavailable" if not available
+        self.wait_for_service_ready(command, CONTENT, 60)
+
+        # 3. create LB with port 443 -> 80, verify the website (should not work)
+        # firewall is open by default
+        lb_https = {
+            "name": "https",
+            "alg": "roundrobin",
+            "privateport": 80,
+            "publicport": 443,
+            "protocol": "ssl"
+        }
+        lb_rule_https = LoadBalancerRule.create(
+            self.userapiclient,
+            lb_https,
+            self.public_ip.ipaddress.id,
+            networkid=self.network.id,
+            projectid=self.project.id
+        )
+        lb_rule_https.assign(self.userapiclient, [self.vm_2])
+
+        command = "curl -L --connect-timeout 3 -k --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, None, 1)
+
+        command = "curl -L --connect-timeout 3 --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, None, 1)
+
+        # 4. add cert to LB with port 443
+        lb_rule_https.assignCert(self.userapiclient, self.sslcert.id)
+
+        # 5. verify the website (should get expected content)
+        command = "curl -L --connect-timeout 3 --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, "SSL certificate problem", 1)
+
+        command = "curl -L --connect-timeout 3 -k --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, CONTENT, 1)
+
+        command = "curl -L --connect-timeout 3 --cacert %s --resolve %s:443:%s https://%s/" % (FULL_CHAIN, DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, CONTENT, 1)
+
+        # 6. remove cert from LB with port 443
+        lb_rule_https.removeCert(self.userapiclient)
+
+        # 7. delete SSL certificate
+        self.sslcert.delete(self.userapiclient)

Review Comment:
   same question as on the previous test..



##########
test/integration/smoke/test_ssl_offloading.py:
##########
@@ -0,0 +1,553 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from marvin.codes import FAILED
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import wait_until
+from marvin.lib.base import (Account,
+                             Project,
+                             UserData,
+                             SslCertificate,
+                             Template,
+                             NetworkOffering,
+                             ServiceOffering,
+                             VirtualMachine,
+                             Network,
+                             VPC,
+                             VpcOffering,
+                             PublicIPAddress,
+                             LoadBalancerRule)
+from marvin.lib.common import (get_domain, get_zone, get_test_template)
+from nose.plugins.attrib import attr
+
+import os
+import subprocess
+
+
+_multiprocess_shared_ = True
+
+DOMAIN = "test-ssl-offloading.cloudstack.org"
+CONTENT = "Test page"
+FULL_CHAIN = "/tmp/full_chain.crt"
+
+CERT = {
+    "privatekey": """-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCph7jsoMCQirRn
+3obuvgnnefTXRQYd9tF9k2aCVkTiiisvC39px7MGdgvDXADhD9fmR7oyXVQlfNu0
+rXjjgsVT3r4bv+DVi81YGXnuU7h10yCOZJt21i6QGHN1CS0/TAfg0UhlACCEYNRx
+kB0klwUcj/jk/AKil1DoUGpvAm2gZsek/njb76/AeIfxc+Es4ZOPCVqQOHp6gI0q
+t6KDMkUwv8fyzrpScygMUPVYrLmm6D0pn8yd3ihW07wGxMjND6UgOnao8t6H3LaM
+Pe7eqSFzxunF9NFFjnUrKcHZZSledDM/37Kbqb/8T5f+4SwjioS1OdPCh8ApdiXq
+HNUwYkALAgMBAAECggEAK5JiiQ7X7053B6s96uaVDRVfRGTNKa5iMXBNDHq3wbHZ
+X4IJAVr+PE7ivxdKco3r45fT11X9ZpUsssdTJsZZiTDak69BTiFcaaRCnmqOIlpd
+J7vb6TMrTIW8RvxQ0M/txm6DuNHLibqJX5a2pszZ13l5cwECfF9/v/XLJTTukCbu
+6D/f3fBVFl1tM8y9saOEYLkdb4dILWY61bVSDNswgprz2EV1SFnk5jxz2FuBrM/Q
++7hINvjDcaRvcm59hRb1rkljv7S10VoNw/CFkU451csJkUe4vWZwB8lZK/XxLQG0
+HEdS1zU1XY8H8Y1RCrxjGRyiiWsBtUThhWYlPrGCoQKBgQDkP09YAlKqXhT69Kx5
+keg2i1jV2hA73zWbWXt9xp5jG5r3pl3m170DvKL93YIDnHtpTC56mlzGrzS7DSTN
+p0buY9Qb3fkJxunCpPVFo0HMFkpeR77ax0v34NzSohlRLKFo5R2M1cmDfbVbnSSl
+MB57FfRRMxzjrk+dJvjOeJsxjwKBgQC+JLb4B8CZjpurXYg3ySiRqFsCqkqob+kf
+9dR+rWvcR6vMTEyha0hUlDvTikDepU2smYR4oPHfdcXF9lAJ7T02UmQDeizAqR68
+u9e+yS0q3tdRnPPZmXJfaDCXG1hKMqF4YA5Vs0XAjleF3zHB+vBLrnlPpShtd/Mu
+sWTpxICTxQKBgQDSr/n+pE5IQwYczOO0aFGwn5pF9L9NdPHXz5aleETV+TJn7WL6
+ZiRsoaDWs7SCvtxQS2kP9RM0t5/2FeDmEMXx4aZ2fsSWGM3IxVo+iL+Aswa81n8/
+Ff5y9lb/+29hNdBcsjk/ukwEG3Lf+UNNVAie15oppgPByzJkPwgmFsAy0wKBgHDX
+/TZp82WuerhSw/rHiSoYjhqg0bnw4Ju1Gy0q4q5SYqTWS0wpDT4U0wSSMjlwRQ6/
+9RxZ9/G0RXFc4tdhUkig0PY3VcPpGnLL0BhL8GBW69ZlnVpwdK4meV/UPKucLLPx
+3dACmszSLSMn+LG0qVNg8mHQFJQS8eGuKcOKePw5AoGACuxtefROKdKOALh4lTi2
+VOwPZ+1jxsm6lKNccIEvbUpe3UXPgNWpJiDX8mUcob4/NBLzmV3BUVKbG7Exbo5J
+LoMfp7OsztWUFwt7YAvRfS8fHdhkEsxEf3T72ADieH5ZAuXFF+K0H3r6HtWPD4ws
+mTJjGP4+Bl/dFakA5FJcjHg=
+-----END PRIVATE KEY-----""",
+    "certificate": """-----BEGIN CERTIFICATE-----
+MIIFKjCCAxKgAwIBAgIUJ7BtN56KI8OuzbbM8SdtCLCB2UgwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEG
+A1UECgwKQ2xvdWRTdGFjazEPMA0GA1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFj
+aGUwHhcNMjUwNjIzMTMxMzA3WhcNMzUwNjIxMTMxMzA3WjBoMQswCQYDVQQGEwJY
+WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMQ8wDQYDVQQKDAZBcGFjaGUxEzAR
+BgNVBAsMCkNsb3VkU3RhY2sxGTAXBgNVBAMMECouY2xvdWRzdGFjay5vcmcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCph7jsoMCQirRn3obuvgnnefTX
+RQYd9tF9k2aCVkTiiisvC39px7MGdgvDXADhD9fmR7oyXVQlfNu0rXjjgsVT3r4b
+v+DVi81YGXnuU7h10yCOZJt21i6QGHN1CS0/TAfg0UhlACCEYNRxkB0klwUcj/jk
+/AKil1DoUGpvAm2gZsek/njb76/AeIfxc+Es4ZOPCVqQOHp6gI0qt6KDMkUwv8fy
+zrpScygMUPVYrLmm6D0pn8yd3ihW07wGxMjND6UgOnao8t6H3LaMPe7eqSFzxunF
+9NFFjnUrKcHZZSledDM/37Kbqb/8T5f+4SwjioS1OdPCh8ApdiXqHNUwYkALAgMB
+AAGjgdUwgdIwKwYDVR0RBCQwIoIQKi5jbG91ZHN0YWNrLm9yZ4IOY2xvdWRzdGFj
+ay5vcmcwHQYDVR0OBBYEFCcq7jrdsqTD+Xi85DCqjYdL1gOqMIGDBgNVHSMEfDB6
+oWKkYDBeMQswCQYDVQQGEwJYWDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMRMw
+EQYDVQQKDApDbG91ZFN0YWNrMQ8wDQYDVQQLDAZBcGFjaGUxDzANBgNVBAMMBkFw
+YWNoZYIURVB9+qvRJyOnJnqmYOw467vW3vQwDQYJKoZIhvcNAQELBQADggIBACld
+lEXgn/A4/kZQbLwwMxBvaoPDDaDaYVpPbOoPw7a8YkrL0rmPIc04PyX9GAqxdC+c
+qaEXvmp3I+BdT13XGcBosXO8uEQ3kses9F3MhOHORPS2mJag7t4eLnNX/0CgKTlR
+6yC2Gu7d3xPNJ+CKMxekdoF31StEFNAYI/La/q3D+IGsRCbrVu3xpPaw2XlXI7Ro
+RU7yebVmQPSNc75bm8Ydo1cdYtz9h8PVnc+6ThhSrdS3jYScj9DrX5ZJaKuZqSlu
+0ZqFXoBflme+cYB7nb9HqnIO67r9vzd2dTcErJVAk5jQqG5Y38d1tingDx1A5opU
+z4BkXEbHNV6VXYUQ5VE0dXO2sNvXVJrstwMPE8d3EvbX/1gWj8kuymbskrCjySE4
+4Yztkb0dsJkVU793lz3EV75DsXvj3gevK049nPv2Grt1+rTgFNa6NJnLvKIKk/mv
+fWjxbK2b/AAJ1ci6xtw/vKmIWoEu6uEMIJmhfBwuP+VnVJWJbmYXpNW/L5g21B76
+Fn8RuQa3mlm5lZrxEcJ/b6fF+2NPJwj7sh6l688VtNXoVSSyXUeV5HwqCv+YMjKn
+CtwpEN/eNHMbrkJvgYwSoOzqhV/wpmNi28S7MOm66JMECHOXOhk/eX2chIEjiVna
+MXhvr/Twfj2N4gNVtcgXkrk39HEYjk5+uF7SdNf4
+-----END CERTIFICATE-----""",
+    "certchain": """-----BEGIN CERTIFICATE-----
+MIIFQzCCAysCFEVQffqr0ScjpyZ6pmDsOOu71t70MA0GCSqGSIb3DQEBCwUAMF4x
+CzAJBgNVBAYTAlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxEzARBgNVBAoM
+CkNsb3VkU3RhY2sxDzANBgNVBAsMBkFwYWNoZTEPMA0GA1UEAwwGQXBhY2hlMB4X
+DTI1MDYxNjEwMjc1NloXDTMwMDYxNTEwMjc1NlowXjELMAkGA1UEBhMCWFgxCzAJ
+BgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEGA1UECgwKQ2xvdWRTdGFjazEPMA0G
+A1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFjaGUwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQCLiQmSjrht15R1F+r79m/LZN5hsfQBGp+dy+yrtsWfOOur
+RdXAwgbLxxsyKMQKWCQxlRI7wdhqh0L0ZBrIr9MjltYqsqLAoLmgY4eG/f6G8YGr
+O/rxzfwTLbCeaIseF/OMA6Sz125HXYp1bltYK4LsuC7tihZXbeVa5pUGs3Jwgcfx
+LYm4eB42Hp7Eg05uL8LbwT/1AjcwoWkTewKAWXA83zgLRDFDbl1t0IPHI4cdVvia
+BNwNbG49ZCF6OgmokSarQSe4Vbems1u9T9pAySXAVjEYBqFjKWyswpdr782uNLmB
+lCGm0pDeJ9/WASxbTJr7k9H6ZpnaHr54DG6ZqennWMz8w6r2pf7bp/EGZ3mZQ4s3
+5ylSP4cQt8CSSI8k2CflPGUyytUAiWlDS3qSyIuAOPKXDg7wIpcbwcu4VMeKnH0Z
+x7Uu9j1UDZEZoSu6UI/VInTl47k1/ECD+AO9yBzZSv+pTQmO3/Im3CcxsTHmVd5s
+Tl0CJ/jWNpo9DAMtmGvt6CBWBXGRsO2XNk7djRcq2CubiCpvODg+7CcR6CiZK73L
+1aOisLiq3+ofiJSSXRRuKtJlkQ4eSPSbYWkNJcKmIhbCoYOdH/Pe3/+RHjvNc1kO
+OUb+icmfzcMVAs3C5jybpazsfjDNQZXWAFx4FLDcqOVbrCwom+tMukw+hzlZnwID
+AQABMA0GCSqGSIb3DQEBCwUAA4ICAQAdexoMwn+Ol1A3+NOHk9WJZX+t2Q8/9wWb
+K+jSVleSfXXWsB1mC3fABVJQdCxtXCH3rpt4w7FK6aUes9VjqAHap4tt9WBq0Wqq
+vvMURFHfllxEM31Z35kBOCSQY9xwpGV1rRh/zYs4h55YixomR3nXNZ9cI8xzlSCi
+sMG0mv0y+yxPohKrZj3AzLYz/M11SimSoyRPIANI+cUg1nJXyQoHzVHWEp1Nj0HB
+M/GW05cxsWea7f5YcAW1JQI3FOkpwb72fIZOtMDa4PO8IYWXJAeAc/chw745/MTi
+Rvl2NT4RZBAcrSNbhCOzRPG/ZiG+ArQuCluZ9HHAXRBMTtlLk5DO4+XxZlyGpjwf
+uKniK8dccy9uU0ho73p9SNDhXH0yb9Naj8vd9NWzCUYaaBXt/92cIyhaAHAVFxJu
+o6jr2FLbnhSGF9EO/tHvF7LxZv1dnbInvlWHwoFQjwmoeB+e17lHBdPMnWnPKBZe
+jA2VH/IzGCucWuWQhruummO5GT8Z6F4jBwvafBo+QARKPZgEBpx3LycXrpkYI3LT
+GGOpGCxFt5tVZOEsC/jQ5rIljNSeTzWmzfNRn/yRUW97uWsrzcQIBAUtu/pQnyFQ
+WCnC1ipCp1zhJsXAFUKuqEfLngXodOvC4tAOr76h11S57o5lN4506Poq2mWgAZe/
+JZr9MEn1+w==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFnzCCA4egAwIBAgIUcUNMqgWoDLsvMj0YmEudj60EG5swDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEG
+A1UECgwKQ2xvdWRTdGFjazEPMA0GA1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFj
+aGUwIBcNMjUwNjE2MTAyNzM2WhgPMjEyNTA1MjMxMDI3MzZaMF4xCzAJBgNVBAYT
+AlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxEzARBgNVBAoMCkNsb3VkU3Rh
+Y2sxDzANBgNVBAsMBkFwYWNoZTEPMA0GA1UEAwwGQXBhY2hlMIICIjANBgkqhkiG
+9w0BAQEFAAOCAg8AMIICCgKCAgEAwVQaePulUM523gKw168ToYp+gt05bXbu4Gg8
+uaRDKhnRAX1sEgYwkQ36Q+iTDEM9sKRma8lMNMIqkZMQdk6sIGX6BL+6wUOb7mL0
+5+I0yO9i8ooaGgNaeNvZftNIRlLsnPMGJaeom2/66XV4CsMqoZKaJ1H/I8N+bAeD
+GvrBx+B4l9D3G390nQvot9JUzrJgGuLl0KDHapvhlR39cCgEfIii02uX1iy0qXlV
+b+G1kLvpeC7T+lsJxondPJ69aO3lbDv/izyWw7qqBC57UhT/oKDxJmjQqklqzhgt
+nM/p3YE7M0nkRi3LnRmsZBz7o1DRf+M29zypKzXVk1aJflL46AtLMmpDIzVrEB2M
+q7o47rstXusYRYsBCqGTgdI1fV/CkDsZY5XkPZh2dsjZCHIS4P03OqFGsc6PQha2
++y2AhV1pvywkDl48kPKSukHfV1RtaPZUZtcQKztwHH+aFfo9mD8z0H2HcExdXKzd
+jhRhI9ZSwFj3HEN9f5P8fS3lf5+fV7EEbG4NisieBj/UivW6QiTHpLD7wRLIUt2g
+XgXNF0lfJzYHbIcxQ6kfC5McU2fu6mUC+p/pNN8G0POS3S2T55tEUqLL4N0SadQy
+N1TZlTd2xTn+Hb6WlG0f5m97xGcNlGHKBvntFrHvOIfkEQ9ne3MlOO1Gjlintowo
+fRGf15kCAwEAAaNTMFEwHQYDVR0OBBYEFM4WEQJpN9M07Q8CHq+5owG93Dj8MB8G
+A1UdIwQYMBaAFM4WEQJpN9M07Q8CHq+5owG93Dj8MA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQELBQADggIBABr5RKGc/rKx4fOgyXNJR4aCJCTtPZKs4AUCCBYz
+cWOjJYGNvThOPSVx51nAD8+YP2BwkOIPfhl2u/+vQSSbz4OlauXLki2DUN8E2OFe
+gJfxPDzWOfAo/QOJcyHwSlnIQjiZzG2lK3eyf5IFnfQILQzDvXaUYvMBkl2hb5Q7
+44H6tRw78uuf/KsT4rY0bBFMN5DayjiyvoIDUvzCRqcb2KOi9DnZ7pXjduL7tO0j
+PhlQ24B77LVUUAvydIGUzmbhGC2VvY1qE7uaYgYtgSUZ0zSjJrHjUjVLMzRouNP7
+jpbBQRAcP4FDcOFZBHogunA0hxQdm0d8u3LqDYPNS0rpfW0ddU/72nfBX4bnoDEN
++anw4wOgFuUcoEThALWZ9ESVKxXQ9Fpvd6FRW8fLLqhXAuli1BqP1c1WRxagldYe
+nPGm/FGZyJ2xOak9Uigi9NAQ/vX6CEfgcJgFZmCo8EKH0d4Ut72vGUcPqiUhT2EI
+AFAd6drSyoUdXXniSMWky9Vrt+qtLuAD1nhHTv8ZPdItXokoiD6ea/4xrbUZn0qY
+lLMDyfY76UVF0ruTR2Q6IdSq/zSggdwgkTooOW4XZcRf5l/ZnoeVQ1QH9C85SIKH
+IKZwPeGUm+EntmpuCBDmQSHLRCGEThd64iOAjqLR6arLj4TBJzBrZsGHFJbm0OcI
+dwa9
+-----END CERTIFICATE-----""",
+    "enabledrevocationcheck": False
+}
+
+USER_DATA="""I2Nsb3VkLWNvbmZpZwoKcnVuY21kOgogIC0gc3VkbyBhcHQtZ2V0IHVwZGF0Z
+QogIC0gc3VkbyBhcHQtZ2V0IGluc3RhbGwgLXkgYXBhY2hlMgogIC0gc3Vkby
+BzeXN0ZW1jdGwgZW5hYmxlIGFwYWNoZTIKICAtIHN1ZG8gc3lzdGVtY3RsIHN0
+YXJ0IGFwYWNoZTIKICAtIGVjaG8gIlRlc3QgcGFnZSIgfHN1ZG8gdGVlIC92YX
+Ivd3d3L2h0bWwvaW5kZXguaHRtbAoKCg=="""
+
+class TestSslOffloading(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+
+        testClient = super(TestSslOffloading, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls._cleanup = []
+
+        # Get Zone, Domain and templates
+        cls.domain = get_domain(cls.apiclient)
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.hypervisor = testClient.getHypervisorInfo()
+
+        cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+
+        #Create an account, network, VM and IP addresses
+        cls.account = Account.create(
+                            cls.apiclient,
+                            cls.services["account"],
+                            admin=True,
+                            domainid=cls.domain.id
+                            )
+        cls.user = cls.account.user[0]
+        cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name)
+
+        # Save full chain as a file
+        with open(FULL_CHAIN, "w", encoding="utf-8") as f:
+            f.write(CERT["certchain"])
+
+        # Register template if needed
+        if cls.hypervisor.lower() == 'simulator':
+            cls.template = get_test_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.hypervisor)
+        else:
+            cls.template = Template.register(
+                cls.apiclient,
+                cls.services["test_templates_cloud_init"][cls.hypervisor.lower()],
+                zoneid=cls.zone.id,
+                hypervisor=cls.hypervisor,
+            )
+            cls.template.download(cls.apiclient)
+            cls._cleanup.append(cls.template)
+
+        if cls.template == FAILED:
+            assert False, "get_test_template() failed to return template"
+
+        # Create service offering
+        cls.service_offering = ServiceOffering.create(
+                                        cls.apiclient,
+                                        cls.services["service_offerings"]["big"]    # 512MB memory
+                                        )
+
+        # Create network offering
+        cls.services["isolated_network_offering"]["egress_policy"] = "true"
+        cls.network_offering = NetworkOffering.create(cls.apiclient,
+                                                      cls.services["isolated_network_offering"],
+                                                      conservemode=True)
+        cls.network_offering.update(cls.apiclient, state='Enabled')
+
+        cls._cleanup.append(cls.network_offering)
+        cls._cleanup.append(cls.service_offering)
+        cls._cleanup.append(cls.account)
+
+    def setUp(self):
+        self.apiclient = self.testClient.getApiClient()
+        self.cleanup = []
+
+    def tearDown(self):
+        super(TestSslOffloading, self).tearDown()
+
+    @classmethod
+    def tearDownClass(cls):
+        super(TestSslOffloading, cls).tearDownClass()
+        if os.path.exists(FULL_CHAIN):
+            os.remove(FULL_CHAIN)
+
+    def wait_for_service_ready(self, command, expected, retries=60):
+        output = None
+        def check_output():
+            try:
+                output = subprocess.check_output(command, shell=True).strip().decode('utf-8')
+            except Exception as e:
+                print("Failed to get output of command %s: %s" % (command, e))
+                if expected is None:
+                    print("But it is expected")
+                    return True, None
+                return False, None
+            print("Output of command %s: \n %s" %(command, output))
+            if expected is None:
+                print("But it is expected to be None")
+                return False, None
+            return (expected in output), None
+
+        res = wait_until(10, retries, check_output)
+        if not res:
+            self.fail("Failed to wait for http server to show content '%s'. The output is '%s'" % (expected, output))
+        return res
+
+    @attr(tags = ["advanced", "advancedns", "smoke"], required_hardware="true")
+    def test_01_ssl_offloading_isolated_network(self):
+        """Test to create Load balancing rule with SSL offloading"""
+
+        # Validate:
+        # 1. Create isolated network and vm instance
+        # 2. create LB with port 80 -> 80, verify the website (should get expected content)
+        # 3. create LB with port 443 -> 80, verify the website (should not work)
+        # 4. add cert to LB with port 443
+        # 5. verify the website (should get expected content)
+        # 6. remove cert from LB with port 443
+        # 7. delete SSL certificate
+
+        # Register Userdata
+        self.userdata = UserData.register(self.apiclient,
+                                         name="test-userdata",
+                                         userdata=USER_DATA,
+                                         account=self.account.name,
+                                         domainid=self.account.domainid
+                                         )
+
+        # Upload SSL Certificate
+        self.sslcert = SslCertificate.create(self.apiclient,
+                                            CERT,
+                                            name="test-ssl-certificate",
+                                            account=self.account.name,
+                                            domainid=self.account.domainid)
+
+        # 1. Create network
+        self.network = Network.create(self.apiclient,
+                                      zoneid=self.zone.id,
+                                      services=self.services["network"],
+                                      domainid=self.domain.id,
+                                      account=self.account.name,
+                                      networkofferingid=self.network_offering.id)
+        self.cleanup.append(self.network)
+
+        self.services["virtual_machine"]["networkids"] = [str(self.network.id)]
+
+        # Create vm instance
+        self.vm_1 = VirtualMachine.create(
+            self.apiclient,
+            self.services["virtual_machine"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            userdataid=self.userdata.userdata.id,
+            serviceofferingid=self.service_offering.id
+        )
+        self.cleanup.append(self.vm_1)
+
+        self.public_ip = PublicIPAddress.create(
+            self.apiclient,
+            self.account.name,
+            self.zone.id,
+            self.account.domainid,
+            self.services["virtual_machine"],
+            self.network.id)
+
+        # 2. create LB with port 80 -> 80, verify the website (should get expected content).
+        # firewall is open by default
+        lb_http = {
+            "name": "http",
+            "alg": "roundrobin",
+            "privateport": 80,
+            "publicport": 80,
+            "protocol": "tcp"
+        }
+        lb_rule_http = LoadBalancerRule.create(
+            self.apiclient,
+            lb_http,
+            self.public_ip.ipaddress.id,
+            accountid=self.account.name,
+            domainid=self.domain.id,
+            networkid=self.network.id
+        )
+        lb_rule_http.assign(self.apiclient, [self.vm_1])
+        command = "curl -L --connect-timeout 3 http://%s/" % self.public_ip.ipaddress.ipaddress
+        # wait 10 minutes until the webpage is available. it returns "503 Service Unavailable" if not available
+        self.wait_for_service_ready(command, CONTENT, 60)
+
+        # 3. create LB with port 443 -> 80, verify the website (should not work)
+        # firewall is open by default
+        lb_https = {
+            "name": "https",
+            "alg": "roundrobin",
+            "privateport": 80,
+            "publicport": 443,
+            "protocol": "ssl"
+        }
+        lb_rule_https = LoadBalancerRule.create(
+            self.apiclient,
+            lb_https,
+            self.public_ip.ipaddress.id,
+            accountid=self.account.name,
+            domainid=self.domain.id,
+            networkid=self.network.id
+        )
+        lb_rule_https.assign(self.apiclient, [self.vm_1])
+
+        command = "curl -L --connect-timeout 3 -k --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, None, 1)
+
+        command = "curl -L --connect-timeout 3 --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, None, 1)
+
+        # 4. add cert to LB with port 443
+        lb_rule_https.assignCert(self.apiclient, self.sslcert.id)
+
+        # 5. verify the website (should get expected content)
+        command = "curl -L --connect-timeout 3 --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, "SSL certificate problem", 1)
+
+        command = "curl -L --connect-timeout 3 -k --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, CONTENT, 1)
+
+        command = "curl -L --connect-timeout 3 --cacert %s --resolve %s:443:%s https://%s/" % (FULL_CHAIN, DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, CONTENT, 1)
+
+        # 6. remove cert from LB with port 443
+        lb_rule_https.removeCert(self.apiclient)
+
+        # 7. delete SSL certificate
+        self.sslcert.delete(self.apiclient)

Review Comment:
   if the delete fails or an exception occurs before here, will the cert be deleted with the network?
   
   and how about the lb-rules?



##########
server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java:
##########
@@ -1737,11 +1737,19 @@ private void updateWithLbRules(final DomainRouterJoinVO routerJoinVO, final Stri
                         .append(",sourcePortEnd=").append(firewallRuleVO.getSourcePortEnd());
                 if (firewallRuleVO instanceof LoadBalancerVO) {
                     LoadBalancerVO loadBalancerVO = (LoadBalancerVO) firewallRuleVO;
-                    loadBalancingData.append(",sourceIp=").append(_ipAddressDao.findById(loadBalancerVO.getSourceIpAddressId()).getAddress().toString())
+                    String sourceIp = _ipAddressDao.findById(loadBalancerVO.getSourceIpAddressId()).getAddress().toString();
+                    loadBalancingData.append(",sourceIp=").append(sourceIp)
                             .append(",destPortStart=").append(loadBalancerVO.getDefaultPortStart())
                             .append(",destPortEnd=").append(loadBalancerVO.getDefaultPortEnd())
                             .append(",algorithm=").append(loadBalancerVO.getAlgorithm())
                             .append(",protocol=").append(loadBalancerVO.getLbProtocol());
+                    if (loadBalancerVO.getLbProtocol() != null && loadBalancerVO.getLbProtocol().equals(NetUtils.SSL_PROTO)) {
+                        final LbSslCert sslCert = _lbMgr.getLbSslCert(firewallRuleVO.getId());
+                        if (sslCert != null && ! sslCert.isRevoked()) {
+                            loadBalancingData.append(",sslcert=").append(sourceIp.replace(".", "_")).append('-')
+                                    .append(loadBalancerVO.getSourcePortStart()).append(".pem");
+                        }
+                    }

Review Comment:
   `conditionallyAddLbProtocol(LoadBalancerVO loadBalancerVO, StringBuilder loadBalancingData)`..



##########
server/src/main/java/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java:
##########
@@ -2257,12 +2262,21 @@ public LoadBalancer updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd) {
         LoadBalancerVO tmplbVo = _lbDao.findById(lbRuleId);
         boolean success = _lbDao.update(lbRuleId, lb);
 
-        // If algorithm is changed, have to reapply the lb config
-        if ((algorithm != null) && (tmplbVo.getAlgorithm().compareTo(algorithm) != 0)){
+        // If algorithm or lb protocol is changed, have to reapply the lb config
+        boolean needToReApplyRule = (algorithm != null && algorithm.equals(tmplbVo.getAlgorithm()))
+                || (lbProtocol != null && lbProtocol.equals(tmplbVo.getLbProtocol()));
+        if (needToReApplyRule) {
             try {
                 lb.setState(FirewallRule.State.Add);
                 _lbDao.persist(lb);
                 applyLoadBalancerConfig(lbRuleId);
+                if (!lb.getLbProtocol().equals(NetUtils.SSL_PROTO)) {
+                    LoadBalancerCertMapVO loadBalancerCertMapVO = _lbCertMapDao.findByLbRuleId(lbRuleId);
+                    if (loadBalancerCertMapVO != null) {
+                        logger.debug("Removing SSL cert for load balancer %s as the new protocol is not ssl but %s", lbRuleId, lb.getLbProtocol());
+                        _lbCertMapDao.remove(loadBalancerCertMapVO.getId());
+                    }
+                }

Review Comment:
   new method ..



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291186546


##########
server/src/main/java/org/apache/cloudstack/network/ssl/CertServiceImpl.java:
##########
@@ -423,19 +432,47 @@ private void validateChain(final List<Certificate> chain, final Certificate cert
 
     }
 
-    public PrivateKey parsePrivateKey(final String key) throws IOException {
+    public PrivateKey parsePrivateKey(final String key, String password) throws IOException, OperatorCreationException, PKCSException, NoSuchAlgorithmException, InvalidKeySpecException {
         Preconditions.checkArgument(StringUtils.isNotEmpty(key));
-        try (final PemReader pemReader = new PemReader(new StringReader(key));) {
-            final PemObject pemObject = pemReader.readPemObject();
-            final byte[] content = pemObject.getContent();
-            final PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
-            final KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
-            return factory.generatePrivate(privKeySpec);
-        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
-            throw new IOException("No encryption provider available.", e);
-        } catch (final InvalidKeySpecException e) {
-            throw new IOException("Invalid Key format.", e);
+        PEMParser pemParser = new PEMParser(new StringReader(key));
+        Object privateKeyObj = pemParser.readObject();
+        if (privateKeyObj == null) {
+            throw new CloudRuntimeException("Cannot parse private key");
+        }
+        PrivateKey privateKey;
+        if (privateKeyObj instanceof PKCS8EncryptedPrivateKeyInfo) {
+            if (password == null) {
+                throw new CloudRuntimeException("Key is encrypted by PKCS#8 but password is null");
+            }
+            PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo)privateKeyObj;
+            JceOpenSSLPKCS8DecryptorProviderBuilder builder = new JceOpenSSLPKCS8DecryptorProviderBuilder();
+            InputDecryptorProvider decryptor = builder.build(password.toCharArray());
+
+            PrivateKeyInfo privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(decryptor);
+            String algorithm = privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm().getId();
+            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded());
+            return keyFactory.generatePrivate(keySpec);
+        } else if (privateKeyObj instanceof PEMEncryptedKeyPair) {
+            if (password == null) {
+                throw new CloudRuntimeException("Key is encrypted but password is null");
+            }
+            PEMEncryptedKeyPair encryptedKeyPair = (PEMEncryptedKeyPair)privateKeyObj;
+            privateKey = new JcaPEMKeyConverter().getKeyPair(
+                    encryptedKeyPair.decryptKeyPair(new JcePEMDecryptorProviderBuilder().build(password.toCharArray()))).getPrivate();

Review Comment:
   added method `parsePEMEncryptedKeyPair`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3213712116

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ debian ✔️ suse15. SL-JID 14709


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3233011081

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✖️ debian ✔️ suse15. SL-JID 14751


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3239884826

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ debian ✔️ suse15. SL-JID 14792


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "borisstoyanov (via GitHub)" <gi...@apache.org>.
borisstoyanov commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3273781510

   > [SF] Trillian test result (tid-14236) Environment: vmware-80u3 (x2), zone: Advanced Networking with Mgmt server ol8 Total time taken: 80726 seconds Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14236-vmware-80u3.zip Smoke tests completed. 145 look OK, 2 have errors, 0 did not run Only failed and skipped tests results shown below:
   > 
   > Test	Result	Time (s)	Test File
   > ContextSuite context=TestSharedFSLifecycle>:setup	`Error`	0.00	test_sharedfs_lifecycle.py
   > test_01_ssl_offloading_isolated_network	`Failure`	1882.23	test_ssl_offloading.py
   > test_01_ssl_offloading_isolated_network	`Error`	1882.26	test_ssl_offloading.py
   > test_02_ssl_offloading_project_vpc	`Error`	712.65	test_ssl_offloading.py
   > test_02_ssl_offloading_project_vpc	`Error`	712.66	test_ssl_offloading.py
   > ContextSuite context=TestSslOffloading>:teardown	`Error`	843.72	test_ssl_offloading.py
   
   @weizhouapache this might be a potential issue, in Marvin logs I see bunch of: 
   `"Exception: Warning: Exception during cleanup : HTTPConnectionPool(host='10.0.34.57', port=8080): Max retries exceeded with url: /client/api?jobid=f30b4774-a137-4419-8b08-92ab4fbf418c&command=queryAsyncJobResult&response=json&apiKey=LIN6rqXuaJwMPfGYFh13qDwYz5VNNz1J2J6qIOWcd3oLQOq0WtD4CwRundBL6rzXToa3lQOC_vKjI3nkHtiD8Q&signature=RzxkJU6oHq5zTGOYHIfarU%2BnNTo%3D (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f0bfa438550>: Failed to establish a new connection: [Errno 110] Connection timed out'))\n"]`
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "codecov[bot] (via GitHub)" <gi...@apache.org>.
codecov[bot] commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3199974334

   ## [Codecov](https://app.codecov.io/gh/apache/cloudstack/pull/11468?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) Report
   :white_check_mark: All modified and coverable lines are covered by tests.
   :white_check_mark: Project coverage is 3.62%. Comparing base ([`f2d6356`](https://app.codecov.io/gh/apache/cloudstack/commit/f2d635683bf75baf1251c4326a8947572df13ba6?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)) to head ([`b590b74`](https://app.codecov.io/gh/apache/cloudstack/commit/b590b746a9765d9991c31ed51c08626c8676ad3e?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)).
   > :exclamation:  There is a different number of reports uploaded between BASE (f2d6356) and HEAD (b590b74). Click for more details.
   > 
   > <details><summary>HEAD has 1 upload less than BASE</summary>
   >
   >| Flag | BASE (f2d6356) | HEAD (b590b74) |
   >|------|------|------|
   >|unittests|1|0|
   ></details>
   
   <details><summary>Additional details and impacted files</summary>
   
   
   
   ```diff
   @@              Coverage Diff              @@
   ##               main   #11468       +/-   ##
   =============================================
   - Coverage     17.35%    3.62%   -13.74%     
   =============================================
     Files          5886      441     -5445     
     Lines        525685    37110   -488575     
     Branches      64159     6798    -57361     
   =============================================
   - Hits          91247     1345    -89902     
   + Misses       424138    35604   -388534     
   + Partials      10300      161    -10139     
   ```
   
   | [Flag](https://app.codecov.io/gh/apache/cloudstack/pull/11468/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | Coverage Δ | |
   |---|---|---|
   | [uitests](https://app.codecov.io/gh/apache/cloudstack/pull/11468/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `3.62% <ø> (-0.01%)` | :arrow_down: |
   | [unittests](https://app.codecov.io/gh/apache/cloudstack/pull/11468/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `?` | |
   
   Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#carryforward-flags-in-the-pull-request-comment) to find out more.
   </details>
   
   [:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/apache/cloudstack/pull/11468?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache).   
   :loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache).
   <details><summary> :rocket: New features to boost your workflow: </summary>
   
   - :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
   - :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
   </details>


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3200288723

   @blueorangutan test


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3239448021

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✖️ debian ✔️ suse15. SL-JID 14788


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3239932015

   @weizhouapache a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3245714393

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3265533603

   @weizhouapache a [SL] Trillian-Jenkins test job (ol8 mgmt + vmware-80u3) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "rohityadavcloud (via GitHub)" <gi...@apache.org>.
rohityadavcloud merged PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3289232555

   <b>[SF] Trillian test result (tid-14315)</b>
   Environment: vmware-80u3 (x2), zone: Advanced Networking with Mgmt server ol8
   Total time taken: 79654 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14315-vmware-80u3.zip
   Smoke tests completed. 145 look OK, 2 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   test_05_ping_in_cpvm_success | `Failure` | 15.43 | test_diagnostics.py
   test_08_arping_in_ssvm | `Failure` | 5.22 | test_diagnostics.py
   test_09_arping_in_cpvm | `Failure` | 5.19 | test_diagnostics.py
   test_16_retrieve_ssvm_single_file | `Failure` | 9.28 | test_diagnostics.py
   test_17_retrieve_cpvm_default_files | `Failure` | 2.16 | test_diagnostics.py
   test_18_retrieve_cpvm_single_file | `Failure` | 1.13 | test_diagnostics.py
   test_04_extract_Iso | `Failure` | 1.13 | test_iso.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3250606270

   <b>[SF] Trillian test result (tid-14189)</b>
   Environment: vmware-80u3 (x2), zone: Advanced Networking with Mgmt server ol8
   Total time taken: 116075 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14189-vmware-80u3.zip
   Smoke tests completed. 138 look OK, 9 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   test_DeployVmAntiAffinityGroup_in_project | `Error` | 159.84 | test_affinity_groups_projects.py
   test_DeployVmAntiAffinityGroup | `Error` | 29.75 | test_affinity_groups.py
   test_03_deploy_and_scale_kubernetes_cluster | `Failure` | 54.52 | test_kubernetes_clusters.py
   test_08_upgrade_kubernetes_ha_cluster | `Failure` | 0.10 | test_kubernetes_clusters.py
   test_12_test_deploy_cluster_different_offerings_per_node_type | `Failure` | 147.35 | test_kubernetes_clusters.py
   test_13_test_add_external_nodes_to_cluster | `Failure` | 117.42 | test_kubernetes_clusters.py
   test_01_non_strict_host_anti_affinity | `Failure` | 212.93 | test_nonstrict_affinity_group.py
   test_02_non_strict_host_affinity | `Error` | 35.22 | test_nonstrict_affinity_group.py
   test_03_restore_vm_with_disk_offering_custom_size | `Error` | 28.55 | test_restore_vm.py
   test_01_vpn_usage | `Error` | 1.12 | test_usage.py
   test_01_deploy_vm_on_specific_host | `Error` | 20.76 | test_vm_deployment_planner.py
   test_02_deploy_vm_on_specific_cluster | `Error` | 3602.62 | test_vm_deployment_planner.py
   test_03_deploy_vm_on_specific_pod | `Error` | 2.71 | test_vm_deployment_planner.py
   test_04_deploy_vm_on_host_override_pod_and_cluster | `Error` | 2.38 | test_vm_deployment_planner.py
   test_05_deploy_vm_on_cluster_override_pod | `Error` | 1.31 | test_vm_deployment_planner.py
   ContextSuite context=TestMigrateVMStrictTags>:setup | `Error` | 0.00 | test_vm_strict_host_tags.py
   test_01_restore_vm_strict_tags_success | `Error` | 18.15 | test_vm_strict_host_tags.py
   test_02_restore_vm_strict_tags_failure | `Error` | 3605.92 | test_vm_strict_host_tags.py
   test_01_scale_vm_strict_tags_success | `Error` | 16.15 | test_vm_strict_host_tags.py
   test_02_scale_vm_strict_tags_failure | `Error` | 3605.76 | test_vm_strict_host_tags.py
   test_01_deploy_vm_on_specific_host_without_strict_tags | `Error` | 15.12 | test_vm_strict_host_tags.py
   test_02_deploy_vm_on_any_host_without_strict_tags | `Error` | 3606.07 | test_vm_strict_host_tags.py
   test_03_deploy_vm_on_specific_host_with_strict_tags_success | `Error` | 4.00 | test_vm_strict_host_tags.py
   test_04_deploy_vm_on_any_host_with_strict_tags_success | `Error` | 5.92 | test_vm_strict_host_tags.py
   test_04_rvpc_network_garbage_collector_nics | `Failure` | 1545.42 | test_vpc_redundant.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3258097345

   <b>[SF] Trillian Build Failed (tid-14225)<b/>


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291158889


##########
server/src/main/java/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java:
##########
@@ -2257,12 +2262,21 @@ public LoadBalancer updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd) {
         LoadBalancerVO tmplbVo = _lbDao.findById(lbRuleId);
         boolean success = _lbDao.update(lbRuleId, lb);
 
-        // If algorithm is changed, have to reapply the lb config
-        if ((algorithm != null) && (tmplbVo.getAlgorithm().compareTo(algorithm) != 0)){
+        // If algorithm or lb protocol is changed, have to reapply the lb config
+        boolean needToReApplyRule = (algorithm != null && algorithm.equals(tmplbVo.getAlgorithm()))
+                || (lbProtocol != null && lbProtocol.equals(tmplbVo.getLbProtocol()));
+        if (needToReApplyRule) {
             try {
                 lb.setState(FirewallRule.State.Add);
                 _lbDao.persist(lb);
                 applyLoadBalancerConfig(lbRuleId);
+                if (!lb.getLbProtocol().equals(NetUtils.SSL_PROTO)) {
+                    LoadBalancerCertMapVO loadBalancerCertMapVO = _lbCertMapDao.findByLbRuleId(lbRuleId);
+                    if (loadBalancerCertMapVO != null) {
+                        logger.debug("Removing SSL cert for load balancer %s as the new protocol is not ssl but %s", lbRuleId, lb.getLbProtocol());
+                        _lbCertMapDao.remove(loadBalancerCertMapVO.getId());
+                    }
+                }

Review Comment:
   will do



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3211012796

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3210045854

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✖️ debian ✔️ suse15. SL-JID 14689


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3213853839

   @weizhouapache a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3252087958

   <b>[SF] Trillian test result (tid-14200)</b>
   Environment: vmware-70u3 (x2), zone: Advanced Networking with Mgmt server ol8
   Total time taken: 61317 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14200-vmware-70u3.zip
   Smoke tests completed. 124 look OK, 5 have errors, 18 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   test_08_arping_in_ssvm | `Failure` | 5.21 | test_diagnostics.py
   test_list_vms_metrics_admin | `Error` | 3620.36 | test_metrics_api.py
   test_list_vms_metrics_history | `Error` | 4.93 | test_metrics_api.py
   test_list_volumes_metrics_history | `Error` | 3619.17 | test_metrics_api.py
   test_01_ssl_offloading_isolated_network | `Failure` | 783.80 | test_ssl_offloading.py
   test_02_ssl_offloading_project_vpc | `Failure` | 742.05 | test_ssl_offloading.py
   test_01_vpn_usage | `Error` | 1.11 | test_usage.py
   ContextSuite context=TestVmAutoScaling>:setup | `Error` | 0.00 | test_vm_autoscaling.py
   all_test_vm_deployment_planner | `Skipped` | --- | test_vm_deployment_planner.py
   all_test_vm_life_cycle | `Skipped` | --- | test_vm_life_cycle.py
   all_test_vm_lifecycle_unmanage_import | `Skipped` | --- | test_vm_lifecycle_unmanage_import.py
   all_test_vm_lifecycle_with_snapshot_or_volume | `Skipped` | --- | test_vm_lifecycle_with_snapshot_or_volume.py
   all_test_vm_schedule | `Skipped` | --- | test_vm_schedule.py
   all_test_vm_snapshot_kvm | `Skipped` | --- | test_vm_snapshot_kvm.py
   all_test_vm_snapshots | `Skipped` | --- | test_vm_snapshots.py
   all_test_vm_strict_host_tags | `Skipped` | --- | test_vm_strict_host_tags.py
   all_test_vnf_templates | `Skipped` | --- | test_vnf_templates.py
   all_test_volumes | `Skipped` | --- | test_volumes.py
   all_test_vpc_ipv6 | `Skipped` | --- | test_vpc_ipv6.py
   all_test_vpc_redundant | `Skipped` | --- | test_vpc_redundant.py
   all_test_vpc_router_nics | `Skipped` | --- | test_vpc_router_nics.py
   all_test_vpc_vpn | `Skipped` | --- | test_vpc_vpn.py
   all_test_webhook_delivery | `Skipped` | --- | test_webhook_delivery.py
   all_test_webhook_lifecycle | `Skipped` | --- | test_webhook_lifecycle.py
   all_test_host_maintenance | `Skipped` | --- | test_host_maintenance.py
   all_test_hostha_kvm | `Skipped` | --- | test_hostha_kvm.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3255930715

   @weizhouapache a [SL] Trillian-Jenkins matrix job (EL8 mgmt + EL8 KVM, Ubuntu22 mgmt + Ubuntu22 KVM, EL8 mgmt + VMware 7.0u3, EL9 mgmt + XCP-ng 8.2 ) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3257264208

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3257996109

   @weizhouapache a [SL] Trillian-Jenkins test job (ol8 mgmt + vmware-80u3) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3239825569

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3233058638

   @borisstoyanov a [SL] Trillian-Jenkins matrix job (EL8 mgmt + EL8 KVM, Ubuntu22 mgmt + Ubuntu22 KVM, EL8 mgmt + VMware 7.0u3, EL9 mgmt + XCP-ng 8.2 ) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3236138374

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3200291414

   @weizhouapache a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3199801554

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291330992


##########
server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java:
##########
@@ -1737,11 +1737,19 @@ private void updateWithLbRules(final DomainRouterJoinVO routerJoinVO, final Stri
                         .append(",sourcePortEnd=").append(firewallRuleVO.getSourcePortEnd());
                 if (firewallRuleVO instanceof LoadBalancerVO) {
                     LoadBalancerVO loadBalancerVO = (LoadBalancerVO) firewallRuleVO;
-                    loadBalancingData.append(",sourceIp=").append(_ipAddressDao.findById(loadBalancerVO.getSourceIpAddressId()).getAddress().toString())
+                    String sourceIp = _ipAddressDao.findById(loadBalancerVO.getSourceIpAddressId()).getAddress().toString();
+                    loadBalancingData.append(",sourceIp=").append(sourceIp)
                             .append(",destPortStart=").append(loadBalancerVO.getDefaultPortStart())
                             .append(",destPortEnd=").append(loadBalancerVO.getDefaultPortEnd())
                             .append(",algorithm=").append(loadBalancerVO.getAlgorithm())
                             .append(",protocol=").append(loadBalancerVO.getLbProtocol());
+                    if (loadBalancerVO.getLbProtocol() != null && loadBalancerVO.getLbProtocol().equals(NetUtils.SSL_PROTO)) {
+                        final LbSslCert sslCert = _lbMgr.getLbSslCert(firewallRuleVO.getId());
+                        if (sslCert != null && ! sslCert.isRevoked()) {
+                            loadBalancingData.append(",sslcert=").append(sourceIp.replace(".", "_")).append('-')
+                                    .append(loadBalancerVO.getSourcePortStart()).append(".pem");
+                        }
+                    }

Review Comment:
   add a method `updateWithLbRuleSslCertificates`



##########
test/integration/smoke/test_ssl_offloading.py:
##########
@@ -0,0 +1,553 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from marvin.codes import FAILED
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import wait_until
+from marvin.lib.base import (Account,
+                             Project,
+                             UserData,
+                             SslCertificate,
+                             Template,
+                             NetworkOffering,
+                             ServiceOffering,
+                             VirtualMachine,
+                             Network,
+                             VPC,
+                             VpcOffering,
+                             PublicIPAddress,
+                             LoadBalancerRule)
+from marvin.lib.common import (get_domain, get_zone, get_test_template)
+from nose.plugins.attrib import attr
+
+import os
+import subprocess
+
+
+_multiprocess_shared_ = True
+
+DOMAIN = "test-ssl-offloading.cloudstack.org"
+CONTENT = "Test page"
+FULL_CHAIN = "/tmp/full_chain.crt"
+
+CERT = {
+    "privatekey": """-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCph7jsoMCQirRn
+3obuvgnnefTXRQYd9tF9k2aCVkTiiisvC39px7MGdgvDXADhD9fmR7oyXVQlfNu0
+rXjjgsVT3r4bv+DVi81YGXnuU7h10yCOZJt21i6QGHN1CS0/TAfg0UhlACCEYNRx
+kB0klwUcj/jk/AKil1DoUGpvAm2gZsek/njb76/AeIfxc+Es4ZOPCVqQOHp6gI0q
+t6KDMkUwv8fyzrpScygMUPVYrLmm6D0pn8yd3ihW07wGxMjND6UgOnao8t6H3LaM
+Pe7eqSFzxunF9NFFjnUrKcHZZSledDM/37Kbqb/8T5f+4SwjioS1OdPCh8ApdiXq
+HNUwYkALAgMBAAECggEAK5JiiQ7X7053B6s96uaVDRVfRGTNKa5iMXBNDHq3wbHZ
+X4IJAVr+PE7ivxdKco3r45fT11X9ZpUsssdTJsZZiTDak69BTiFcaaRCnmqOIlpd
+J7vb6TMrTIW8RvxQ0M/txm6DuNHLibqJX5a2pszZ13l5cwECfF9/v/XLJTTukCbu
+6D/f3fBVFl1tM8y9saOEYLkdb4dILWY61bVSDNswgprz2EV1SFnk5jxz2FuBrM/Q
++7hINvjDcaRvcm59hRb1rkljv7S10VoNw/CFkU451csJkUe4vWZwB8lZK/XxLQG0
+HEdS1zU1XY8H8Y1RCrxjGRyiiWsBtUThhWYlPrGCoQKBgQDkP09YAlKqXhT69Kx5
+keg2i1jV2hA73zWbWXt9xp5jG5r3pl3m170DvKL93YIDnHtpTC56mlzGrzS7DSTN
+p0buY9Qb3fkJxunCpPVFo0HMFkpeR77ax0v34NzSohlRLKFo5R2M1cmDfbVbnSSl
+MB57FfRRMxzjrk+dJvjOeJsxjwKBgQC+JLb4B8CZjpurXYg3ySiRqFsCqkqob+kf
+9dR+rWvcR6vMTEyha0hUlDvTikDepU2smYR4oPHfdcXF9lAJ7T02UmQDeizAqR68
+u9e+yS0q3tdRnPPZmXJfaDCXG1hKMqF4YA5Vs0XAjleF3zHB+vBLrnlPpShtd/Mu
+sWTpxICTxQKBgQDSr/n+pE5IQwYczOO0aFGwn5pF9L9NdPHXz5aleETV+TJn7WL6
+ZiRsoaDWs7SCvtxQS2kP9RM0t5/2FeDmEMXx4aZ2fsSWGM3IxVo+iL+Aswa81n8/
+Ff5y9lb/+29hNdBcsjk/ukwEG3Lf+UNNVAie15oppgPByzJkPwgmFsAy0wKBgHDX
+/TZp82WuerhSw/rHiSoYjhqg0bnw4Ju1Gy0q4q5SYqTWS0wpDT4U0wSSMjlwRQ6/
+9RxZ9/G0RXFc4tdhUkig0PY3VcPpGnLL0BhL8GBW69ZlnVpwdK4meV/UPKucLLPx
+3dACmszSLSMn+LG0qVNg8mHQFJQS8eGuKcOKePw5AoGACuxtefROKdKOALh4lTi2
+VOwPZ+1jxsm6lKNccIEvbUpe3UXPgNWpJiDX8mUcob4/NBLzmV3BUVKbG7Exbo5J
+LoMfp7OsztWUFwt7YAvRfS8fHdhkEsxEf3T72ADieH5ZAuXFF+K0H3r6HtWPD4ws
+mTJjGP4+Bl/dFakA5FJcjHg=
+-----END PRIVATE KEY-----""",
+    "certificate": """-----BEGIN CERTIFICATE-----
+MIIFKjCCAxKgAwIBAgIUJ7BtN56KI8OuzbbM8SdtCLCB2UgwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEG
+A1UECgwKQ2xvdWRTdGFjazEPMA0GA1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFj
+aGUwHhcNMjUwNjIzMTMxMzA3WhcNMzUwNjIxMTMxMzA3WjBoMQswCQYDVQQGEwJY
+WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMQ8wDQYDVQQKDAZBcGFjaGUxEzAR
+BgNVBAsMCkNsb3VkU3RhY2sxGTAXBgNVBAMMECouY2xvdWRzdGFjay5vcmcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCph7jsoMCQirRn3obuvgnnefTX
+RQYd9tF9k2aCVkTiiisvC39px7MGdgvDXADhD9fmR7oyXVQlfNu0rXjjgsVT3r4b
+v+DVi81YGXnuU7h10yCOZJt21i6QGHN1CS0/TAfg0UhlACCEYNRxkB0klwUcj/jk
+/AKil1DoUGpvAm2gZsek/njb76/AeIfxc+Es4ZOPCVqQOHp6gI0qt6KDMkUwv8fy
+zrpScygMUPVYrLmm6D0pn8yd3ihW07wGxMjND6UgOnao8t6H3LaMPe7eqSFzxunF
+9NFFjnUrKcHZZSledDM/37Kbqb/8T5f+4SwjioS1OdPCh8ApdiXqHNUwYkALAgMB
+AAGjgdUwgdIwKwYDVR0RBCQwIoIQKi5jbG91ZHN0YWNrLm9yZ4IOY2xvdWRzdGFj
+ay5vcmcwHQYDVR0OBBYEFCcq7jrdsqTD+Xi85DCqjYdL1gOqMIGDBgNVHSMEfDB6
+oWKkYDBeMQswCQYDVQQGEwJYWDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMRMw
+EQYDVQQKDApDbG91ZFN0YWNrMQ8wDQYDVQQLDAZBcGFjaGUxDzANBgNVBAMMBkFw
+YWNoZYIURVB9+qvRJyOnJnqmYOw467vW3vQwDQYJKoZIhvcNAQELBQADggIBACld
+lEXgn/A4/kZQbLwwMxBvaoPDDaDaYVpPbOoPw7a8YkrL0rmPIc04PyX9GAqxdC+c
+qaEXvmp3I+BdT13XGcBosXO8uEQ3kses9F3MhOHORPS2mJag7t4eLnNX/0CgKTlR
+6yC2Gu7d3xPNJ+CKMxekdoF31StEFNAYI/La/q3D+IGsRCbrVu3xpPaw2XlXI7Ro
+RU7yebVmQPSNc75bm8Ydo1cdYtz9h8PVnc+6ThhSrdS3jYScj9DrX5ZJaKuZqSlu
+0ZqFXoBflme+cYB7nb9HqnIO67r9vzd2dTcErJVAk5jQqG5Y38d1tingDx1A5opU
+z4BkXEbHNV6VXYUQ5VE0dXO2sNvXVJrstwMPE8d3EvbX/1gWj8kuymbskrCjySE4
+4Yztkb0dsJkVU793lz3EV75DsXvj3gevK049nPv2Grt1+rTgFNa6NJnLvKIKk/mv
+fWjxbK2b/AAJ1ci6xtw/vKmIWoEu6uEMIJmhfBwuP+VnVJWJbmYXpNW/L5g21B76
+Fn8RuQa3mlm5lZrxEcJ/b6fF+2NPJwj7sh6l688VtNXoVSSyXUeV5HwqCv+YMjKn
+CtwpEN/eNHMbrkJvgYwSoOzqhV/wpmNi28S7MOm66JMECHOXOhk/eX2chIEjiVna
+MXhvr/Twfj2N4gNVtcgXkrk39HEYjk5+uF7SdNf4
+-----END CERTIFICATE-----""",
+    "certchain": """-----BEGIN CERTIFICATE-----
+MIIFQzCCAysCFEVQffqr0ScjpyZ6pmDsOOu71t70MA0GCSqGSIb3DQEBCwUAMF4x
+CzAJBgNVBAYTAlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxEzARBgNVBAoM
+CkNsb3VkU3RhY2sxDzANBgNVBAsMBkFwYWNoZTEPMA0GA1UEAwwGQXBhY2hlMB4X
+DTI1MDYxNjEwMjc1NloXDTMwMDYxNTEwMjc1NlowXjELMAkGA1UEBhMCWFgxCzAJ
+BgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEGA1UECgwKQ2xvdWRTdGFjazEPMA0G
+A1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFjaGUwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQCLiQmSjrht15R1F+r79m/LZN5hsfQBGp+dy+yrtsWfOOur
+RdXAwgbLxxsyKMQKWCQxlRI7wdhqh0L0ZBrIr9MjltYqsqLAoLmgY4eG/f6G8YGr
+O/rxzfwTLbCeaIseF/OMA6Sz125HXYp1bltYK4LsuC7tihZXbeVa5pUGs3Jwgcfx
+LYm4eB42Hp7Eg05uL8LbwT/1AjcwoWkTewKAWXA83zgLRDFDbl1t0IPHI4cdVvia
+BNwNbG49ZCF6OgmokSarQSe4Vbems1u9T9pAySXAVjEYBqFjKWyswpdr782uNLmB
+lCGm0pDeJ9/WASxbTJr7k9H6ZpnaHr54DG6ZqennWMz8w6r2pf7bp/EGZ3mZQ4s3
+5ylSP4cQt8CSSI8k2CflPGUyytUAiWlDS3qSyIuAOPKXDg7wIpcbwcu4VMeKnH0Z
+x7Uu9j1UDZEZoSu6UI/VInTl47k1/ECD+AO9yBzZSv+pTQmO3/Im3CcxsTHmVd5s
+Tl0CJ/jWNpo9DAMtmGvt6CBWBXGRsO2XNk7djRcq2CubiCpvODg+7CcR6CiZK73L
+1aOisLiq3+ofiJSSXRRuKtJlkQ4eSPSbYWkNJcKmIhbCoYOdH/Pe3/+RHjvNc1kO
+OUb+icmfzcMVAs3C5jybpazsfjDNQZXWAFx4FLDcqOVbrCwom+tMukw+hzlZnwID
+AQABMA0GCSqGSIb3DQEBCwUAA4ICAQAdexoMwn+Ol1A3+NOHk9WJZX+t2Q8/9wWb
+K+jSVleSfXXWsB1mC3fABVJQdCxtXCH3rpt4w7FK6aUes9VjqAHap4tt9WBq0Wqq
+vvMURFHfllxEM31Z35kBOCSQY9xwpGV1rRh/zYs4h55YixomR3nXNZ9cI8xzlSCi
+sMG0mv0y+yxPohKrZj3AzLYz/M11SimSoyRPIANI+cUg1nJXyQoHzVHWEp1Nj0HB
+M/GW05cxsWea7f5YcAW1JQI3FOkpwb72fIZOtMDa4PO8IYWXJAeAc/chw745/MTi
+Rvl2NT4RZBAcrSNbhCOzRPG/ZiG+ArQuCluZ9HHAXRBMTtlLk5DO4+XxZlyGpjwf
+uKniK8dccy9uU0ho73p9SNDhXH0yb9Naj8vd9NWzCUYaaBXt/92cIyhaAHAVFxJu
+o6jr2FLbnhSGF9EO/tHvF7LxZv1dnbInvlWHwoFQjwmoeB+e17lHBdPMnWnPKBZe
+jA2VH/IzGCucWuWQhruummO5GT8Z6F4jBwvafBo+QARKPZgEBpx3LycXrpkYI3LT
+GGOpGCxFt5tVZOEsC/jQ5rIljNSeTzWmzfNRn/yRUW97uWsrzcQIBAUtu/pQnyFQ
+WCnC1ipCp1zhJsXAFUKuqEfLngXodOvC4tAOr76h11S57o5lN4506Poq2mWgAZe/
+JZr9MEn1+w==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFnzCCA4egAwIBAgIUcUNMqgWoDLsvMj0YmEudj60EG5swDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEG
+A1UECgwKQ2xvdWRTdGFjazEPMA0GA1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFj
+aGUwIBcNMjUwNjE2MTAyNzM2WhgPMjEyNTA1MjMxMDI3MzZaMF4xCzAJBgNVBAYT
+AlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxEzARBgNVBAoMCkNsb3VkU3Rh
+Y2sxDzANBgNVBAsMBkFwYWNoZTEPMA0GA1UEAwwGQXBhY2hlMIICIjANBgkqhkiG
+9w0BAQEFAAOCAg8AMIICCgKCAgEAwVQaePulUM523gKw168ToYp+gt05bXbu4Gg8
+uaRDKhnRAX1sEgYwkQ36Q+iTDEM9sKRma8lMNMIqkZMQdk6sIGX6BL+6wUOb7mL0
+5+I0yO9i8ooaGgNaeNvZftNIRlLsnPMGJaeom2/66XV4CsMqoZKaJ1H/I8N+bAeD
+GvrBx+B4l9D3G390nQvot9JUzrJgGuLl0KDHapvhlR39cCgEfIii02uX1iy0qXlV
+b+G1kLvpeC7T+lsJxondPJ69aO3lbDv/izyWw7qqBC57UhT/oKDxJmjQqklqzhgt
+nM/p3YE7M0nkRi3LnRmsZBz7o1DRf+M29zypKzXVk1aJflL46AtLMmpDIzVrEB2M
+q7o47rstXusYRYsBCqGTgdI1fV/CkDsZY5XkPZh2dsjZCHIS4P03OqFGsc6PQha2
++y2AhV1pvywkDl48kPKSukHfV1RtaPZUZtcQKztwHH+aFfo9mD8z0H2HcExdXKzd
+jhRhI9ZSwFj3HEN9f5P8fS3lf5+fV7EEbG4NisieBj/UivW6QiTHpLD7wRLIUt2g
+XgXNF0lfJzYHbIcxQ6kfC5McU2fu6mUC+p/pNN8G0POS3S2T55tEUqLL4N0SadQy
+N1TZlTd2xTn+Hb6WlG0f5m97xGcNlGHKBvntFrHvOIfkEQ9ne3MlOO1Gjlintowo
+fRGf15kCAwEAAaNTMFEwHQYDVR0OBBYEFM4WEQJpN9M07Q8CHq+5owG93Dj8MB8G
+A1UdIwQYMBaAFM4WEQJpN9M07Q8CHq+5owG93Dj8MA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQELBQADggIBABr5RKGc/rKx4fOgyXNJR4aCJCTtPZKs4AUCCBYz
+cWOjJYGNvThOPSVx51nAD8+YP2BwkOIPfhl2u/+vQSSbz4OlauXLki2DUN8E2OFe
+gJfxPDzWOfAo/QOJcyHwSlnIQjiZzG2lK3eyf5IFnfQILQzDvXaUYvMBkl2hb5Q7
+44H6tRw78uuf/KsT4rY0bBFMN5DayjiyvoIDUvzCRqcb2KOi9DnZ7pXjduL7tO0j
+PhlQ24B77LVUUAvydIGUzmbhGC2VvY1qE7uaYgYtgSUZ0zSjJrHjUjVLMzRouNP7
+jpbBQRAcP4FDcOFZBHogunA0hxQdm0d8u3LqDYPNS0rpfW0ddU/72nfBX4bnoDEN
++anw4wOgFuUcoEThALWZ9ESVKxXQ9Fpvd6FRW8fLLqhXAuli1BqP1c1WRxagldYe
+nPGm/FGZyJ2xOak9Uigi9NAQ/vX6CEfgcJgFZmCo8EKH0d4Ut72vGUcPqiUhT2EI
+AFAd6drSyoUdXXniSMWky9Vrt+qtLuAD1nhHTv8ZPdItXokoiD6ea/4xrbUZn0qY
+lLMDyfY76UVF0ruTR2Q6IdSq/zSggdwgkTooOW4XZcRf5l/ZnoeVQ1QH9C85SIKH
+IKZwPeGUm+EntmpuCBDmQSHLRCGEThd64iOAjqLR6arLj4TBJzBrZsGHFJbm0OcI
+dwa9
+-----END CERTIFICATE-----""",
+    "enabledrevocationcheck": False
+}
+
+USER_DATA="""I2Nsb3VkLWNvbmZpZwoKcnVuY21kOgogIC0gc3VkbyBhcHQtZ2V0IHVwZGF0Z
+QogIC0gc3VkbyBhcHQtZ2V0IGluc3RhbGwgLXkgYXBhY2hlMgogIC0gc3Vkby
+BzeXN0ZW1jdGwgZW5hYmxlIGFwYWNoZTIKICAtIHN1ZG8gc3lzdGVtY3RsIHN0
+YXJ0IGFwYWNoZTIKICAtIGVjaG8gIlRlc3QgcGFnZSIgfHN1ZG8gdGVlIC92YX
+Ivd3d3L2h0bWwvaW5kZXguaHRtbAoKCg=="""
+
+class TestSslOffloading(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+
+        testClient = super(TestSslOffloading, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls._cleanup = []
+
+        # Get Zone, Domain and templates
+        cls.domain = get_domain(cls.apiclient)
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.hypervisor = testClient.getHypervisorInfo()
+
+        cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+
+        #Create an account, network, VM and IP addresses
+        cls.account = Account.create(
+                            cls.apiclient,
+                            cls.services["account"],
+                            admin=True,
+                            domainid=cls.domain.id
+                            )
+        cls.user = cls.account.user[0]
+        cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name)
+
+        # Save full chain as a file
+        with open(FULL_CHAIN, "w", encoding="utf-8") as f:
+            f.write(CERT["certchain"])
+
+        # Register template if needed
+        if cls.hypervisor.lower() == 'simulator':
+            cls.template = get_test_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.hypervisor)
+        else:
+            cls.template = Template.register(
+                cls.apiclient,
+                cls.services["test_templates_cloud_init"][cls.hypervisor.lower()],
+                zoneid=cls.zone.id,
+                hypervisor=cls.hypervisor,
+            )
+            cls.template.download(cls.apiclient)
+            cls._cleanup.append(cls.template)
+
+        if cls.template == FAILED:
+            assert False, "get_test_template() failed to return template"
+
+        # Create service offering
+        cls.service_offering = ServiceOffering.create(
+                                        cls.apiclient,
+                                        cls.services["service_offerings"]["big"]    # 512MB memory
+                                        )
+
+        # Create network offering
+        cls.services["isolated_network_offering"]["egress_policy"] = "true"
+        cls.network_offering = NetworkOffering.create(cls.apiclient,
+                                                      cls.services["isolated_network_offering"],
+                                                      conservemode=True)
+        cls.network_offering.update(cls.apiclient, state='Enabled')
+
+        cls._cleanup.append(cls.network_offering)
+        cls._cleanup.append(cls.service_offering)
+        cls._cleanup.append(cls.account)
+
+    def setUp(self):
+        self.apiclient = self.testClient.getApiClient()
+        self.cleanup = []
+
+    def tearDown(self):
+        super(TestSslOffloading, self).tearDown()
+
+    @classmethod
+    def tearDownClass(cls):
+        super(TestSslOffloading, cls).tearDownClass()
+        if os.path.exists(FULL_CHAIN):
+            os.remove(FULL_CHAIN)
+
+    def wait_for_service_ready(self, command, expected, retries=60):
+        output = None
+        def check_output():
+            try:
+                output = subprocess.check_output(command, shell=True).strip().decode('utf-8')
+            except Exception as e:
+                print("Failed to get output of command %s: %s" % (command, e))
+                if expected is None:
+                    print("But it is expected")
+                    return True, None
+                return False, None
+            print("Output of command %s: \n %s" %(command, output))
+            if expected is None:
+                print("But it is expected to be None")
+                return False, None
+            return (expected in output), None
+
+        res = wait_until(10, retries, check_output)
+        if not res:
+            self.fail("Failed to wait for http server to show content '%s'. The output is '%s'" % (expected, output))
+        return res
+
+    @attr(tags = ["advanced", "advancedns", "smoke"], required_hardware="true")
+    def test_01_ssl_offloading_isolated_network(self):
+        """Test to create Load balancing rule with SSL offloading"""
+
+        # Validate:
+        # 1. Create isolated network and vm instance
+        # 2. create LB with port 80 -> 80, verify the website (should get expected content)
+        # 3. create LB with port 443 -> 80, verify the website (should not work)
+        # 4. add cert to LB with port 443
+        # 5. verify the website (should get expected content)
+        # 6. remove cert from LB with port 443
+        # 7. delete SSL certificate
+
+        # Register Userdata
+        self.userdata = UserData.register(self.apiclient,
+                                         name="test-userdata",
+                                         userdata=USER_DATA,
+                                         account=self.account.name,
+                                         domainid=self.account.domainid
+                                         )
+
+        # Upload SSL Certificate
+        self.sslcert = SslCertificate.create(self.apiclient,
+                                            CERT,
+                                            name="test-ssl-certificate",
+                                            account=self.account.name,
+                                            domainid=self.account.domainid)
+
+        # 1. Create network
+        self.network = Network.create(self.apiclient,
+                                      zoneid=self.zone.id,
+                                      services=self.services["network"],
+                                      domainid=self.domain.id,
+                                      account=self.account.name,
+                                      networkofferingid=self.network_offering.id)
+        self.cleanup.append(self.network)
+
+        self.services["virtual_machine"]["networkids"] = [str(self.network.id)]
+
+        # Create vm instance
+        self.vm_1 = VirtualMachine.create(
+            self.apiclient,
+            self.services["virtual_machine"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            userdataid=self.userdata.userdata.id,
+            serviceofferingid=self.service_offering.id
+        )
+        self.cleanup.append(self.vm_1)
+
+        self.public_ip = PublicIPAddress.create(
+            self.apiclient,
+            self.account.name,
+            self.zone.id,
+            self.account.domainid,
+            self.services["virtual_machine"],
+            self.network.id)
+
+        # 2. create LB with port 80 -> 80, verify the website (should get expected content).
+        # firewall is open by default
+        lb_http = {
+            "name": "http",
+            "alg": "roundrobin",
+            "privateport": 80,
+            "publicport": 80,
+            "protocol": "tcp"
+        }
+        lb_rule_http = LoadBalancerRule.create(
+            self.apiclient,
+            lb_http,
+            self.public_ip.ipaddress.id,
+            accountid=self.account.name,
+            domainid=self.domain.id,
+            networkid=self.network.id
+        )
+        lb_rule_http.assign(self.apiclient, [self.vm_1])
+        command = "curl -L --connect-timeout 3 http://%s/" % self.public_ip.ipaddress.ipaddress
+        # wait 10 minutes until the webpage is available. it returns "503 Service Unavailable" if not available
+        self.wait_for_service_ready(command, CONTENT, 60)
+
+        # 3. create LB with port 443 -> 80, verify the website (should not work)
+        # firewall is open by default
+        lb_https = {
+            "name": "https",
+            "alg": "roundrobin",
+            "privateport": 80,
+            "publicport": 443,
+            "protocol": "ssl"
+        }
+        lb_rule_https = LoadBalancerRule.create(
+            self.apiclient,
+            lb_https,
+            self.public_ip.ipaddress.id,
+            accountid=self.account.name,
+            domainid=self.domain.id,
+            networkid=self.network.id
+        )
+        lb_rule_https.assign(self.apiclient, [self.vm_1])
+
+        command = "curl -L --connect-timeout 3 -k --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, None, 1)
+
+        command = "curl -L --connect-timeout 3 --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, None, 1)
+
+        # 4. add cert to LB with port 443
+        lb_rule_https.assignCert(self.apiclient, self.sslcert.id)
+
+        # 5. verify the website (should get expected content)
+        command = "curl -L --connect-timeout 3 --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, "SSL certificate problem", 1)
+
+        command = "curl -L --connect-timeout 3 -k --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, CONTENT, 1)
+
+        command = "curl -L --connect-timeout 3 --cacert %s --resolve %s:443:%s https://%s/" % (FULL_CHAIN, DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, CONTENT, 1)
+
+        # 6. remove cert from LB with port 443
+        lb_rule_https.removeCert(self.apiclient)
+
+        # 7. delete SSL certificate
+        self.sslcert.delete(self.apiclient)

Review Comment:
   ssl certificates belong to the account, not the network
   
   when delete a load balancer or a network, the ssl certificate will be removed from the load balancer, but it still exists.
   ssl certificates will be removed when the account is removed.



##########
test/integration/smoke/test_ssl_offloading.py:
##########
@@ -0,0 +1,553 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from marvin.codes import FAILED
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import wait_until
+from marvin.lib.base import (Account,
+                             Project,
+                             UserData,
+                             SslCertificate,
+                             Template,
+                             NetworkOffering,
+                             ServiceOffering,
+                             VirtualMachine,
+                             Network,
+                             VPC,
+                             VpcOffering,
+                             PublicIPAddress,
+                             LoadBalancerRule)
+from marvin.lib.common import (get_domain, get_zone, get_test_template)
+from nose.plugins.attrib import attr
+
+import os
+import subprocess
+
+
+_multiprocess_shared_ = True
+
+DOMAIN = "test-ssl-offloading.cloudstack.org"
+CONTENT = "Test page"
+FULL_CHAIN = "/tmp/full_chain.crt"
+
+CERT = {
+    "privatekey": """-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCph7jsoMCQirRn
+3obuvgnnefTXRQYd9tF9k2aCVkTiiisvC39px7MGdgvDXADhD9fmR7oyXVQlfNu0
+rXjjgsVT3r4bv+DVi81YGXnuU7h10yCOZJt21i6QGHN1CS0/TAfg0UhlACCEYNRx
+kB0klwUcj/jk/AKil1DoUGpvAm2gZsek/njb76/AeIfxc+Es4ZOPCVqQOHp6gI0q
+t6KDMkUwv8fyzrpScygMUPVYrLmm6D0pn8yd3ihW07wGxMjND6UgOnao8t6H3LaM
+Pe7eqSFzxunF9NFFjnUrKcHZZSledDM/37Kbqb/8T5f+4SwjioS1OdPCh8ApdiXq
+HNUwYkALAgMBAAECggEAK5JiiQ7X7053B6s96uaVDRVfRGTNKa5iMXBNDHq3wbHZ
+X4IJAVr+PE7ivxdKco3r45fT11X9ZpUsssdTJsZZiTDak69BTiFcaaRCnmqOIlpd
+J7vb6TMrTIW8RvxQ0M/txm6DuNHLibqJX5a2pszZ13l5cwECfF9/v/XLJTTukCbu
+6D/f3fBVFl1tM8y9saOEYLkdb4dILWY61bVSDNswgprz2EV1SFnk5jxz2FuBrM/Q
++7hINvjDcaRvcm59hRb1rkljv7S10VoNw/CFkU451csJkUe4vWZwB8lZK/XxLQG0
+HEdS1zU1XY8H8Y1RCrxjGRyiiWsBtUThhWYlPrGCoQKBgQDkP09YAlKqXhT69Kx5
+keg2i1jV2hA73zWbWXt9xp5jG5r3pl3m170DvKL93YIDnHtpTC56mlzGrzS7DSTN
+p0buY9Qb3fkJxunCpPVFo0HMFkpeR77ax0v34NzSohlRLKFo5R2M1cmDfbVbnSSl
+MB57FfRRMxzjrk+dJvjOeJsxjwKBgQC+JLb4B8CZjpurXYg3ySiRqFsCqkqob+kf
+9dR+rWvcR6vMTEyha0hUlDvTikDepU2smYR4oPHfdcXF9lAJ7T02UmQDeizAqR68
+u9e+yS0q3tdRnPPZmXJfaDCXG1hKMqF4YA5Vs0XAjleF3zHB+vBLrnlPpShtd/Mu
+sWTpxICTxQKBgQDSr/n+pE5IQwYczOO0aFGwn5pF9L9NdPHXz5aleETV+TJn7WL6
+ZiRsoaDWs7SCvtxQS2kP9RM0t5/2FeDmEMXx4aZ2fsSWGM3IxVo+iL+Aswa81n8/
+Ff5y9lb/+29hNdBcsjk/ukwEG3Lf+UNNVAie15oppgPByzJkPwgmFsAy0wKBgHDX
+/TZp82WuerhSw/rHiSoYjhqg0bnw4Ju1Gy0q4q5SYqTWS0wpDT4U0wSSMjlwRQ6/
+9RxZ9/G0RXFc4tdhUkig0PY3VcPpGnLL0BhL8GBW69ZlnVpwdK4meV/UPKucLLPx
+3dACmszSLSMn+LG0qVNg8mHQFJQS8eGuKcOKePw5AoGACuxtefROKdKOALh4lTi2
+VOwPZ+1jxsm6lKNccIEvbUpe3UXPgNWpJiDX8mUcob4/NBLzmV3BUVKbG7Exbo5J
+LoMfp7OsztWUFwt7YAvRfS8fHdhkEsxEf3T72ADieH5ZAuXFF+K0H3r6HtWPD4ws
+mTJjGP4+Bl/dFakA5FJcjHg=
+-----END PRIVATE KEY-----""",
+    "certificate": """-----BEGIN CERTIFICATE-----
+MIIFKjCCAxKgAwIBAgIUJ7BtN56KI8OuzbbM8SdtCLCB2UgwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEG
+A1UECgwKQ2xvdWRTdGFjazEPMA0GA1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFj
+aGUwHhcNMjUwNjIzMTMxMzA3WhcNMzUwNjIxMTMxMzA3WjBoMQswCQYDVQQGEwJY
+WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMQ8wDQYDVQQKDAZBcGFjaGUxEzAR
+BgNVBAsMCkNsb3VkU3RhY2sxGTAXBgNVBAMMECouY2xvdWRzdGFjay5vcmcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCph7jsoMCQirRn3obuvgnnefTX
+RQYd9tF9k2aCVkTiiisvC39px7MGdgvDXADhD9fmR7oyXVQlfNu0rXjjgsVT3r4b
+v+DVi81YGXnuU7h10yCOZJt21i6QGHN1CS0/TAfg0UhlACCEYNRxkB0klwUcj/jk
+/AKil1DoUGpvAm2gZsek/njb76/AeIfxc+Es4ZOPCVqQOHp6gI0qt6KDMkUwv8fy
+zrpScygMUPVYrLmm6D0pn8yd3ihW07wGxMjND6UgOnao8t6H3LaMPe7eqSFzxunF
+9NFFjnUrKcHZZSledDM/37Kbqb/8T5f+4SwjioS1OdPCh8ApdiXqHNUwYkALAgMB
+AAGjgdUwgdIwKwYDVR0RBCQwIoIQKi5jbG91ZHN0YWNrLm9yZ4IOY2xvdWRzdGFj
+ay5vcmcwHQYDVR0OBBYEFCcq7jrdsqTD+Xi85DCqjYdL1gOqMIGDBgNVHSMEfDB6
+oWKkYDBeMQswCQYDVQQGEwJYWDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMRMw
+EQYDVQQKDApDbG91ZFN0YWNrMQ8wDQYDVQQLDAZBcGFjaGUxDzANBgNVBAMMBkFw
+YWNoZYIURVB9+qvRJyOnJnqmYOw467vW3vQwDQYJKoZIhvcNAQELBQADggIBACld
+lEXgn/A4/kZQbLwwMxBvaoPDDaDaYVpPbOoPw7a8YkrL0rmPIc04PyX9GAqxdC+c
+qaEXvmp3I+BdT13XGcBosXO8uEQ3kses9F3MhOHORPS2mJag7t4eLnNX/0CgKTlR
+6yC2Gu7d3xPNJ+CKMxekdoF31StEFNAYI/La/q3D+IGsRCbrVu3xpPaw2XlXI7Ro
+RU7yebVmQPSNc75bm8Ydo1cdYtz9h8PVnc+6ThhSrdS3jYScj9DrX5ZJaKuZqSlu
+0ZqFXoBflme+cYB7nb9HqnIO67r9vzd2dTcErJVAk5jQqG5Y38d1tingDx1A5opU
+z4BkXEbHNV6VXYUQ5VE0dXO2sNvXVJrstwMPE8d3EvbX/1gWj8kuymbskrCjySE4
+4Yztkb0dsJkVU793lz3EV75DsXvj3gevK049nPv2Grt1+rTgFNa6NJnLvKIKk/mv
+fWjxbK2b/AAJ1ci6xtw/vKmIWoEu6uEMIJmhfBwuP+VnVJWJbmYXpNW/L5g21B76
+Fn8RuQa3mlm5lZrxEcJ/b6fF+2NPJwj7sh6l688VtNXoVSSyXUeV5HwqCv+YMjKn
+CtwpEN/eNHMbrkJvgYwSoOzqhV/wpmNi28S7MOm66JMECHOXOhk/eX2chIEjiVna
+MXhvr/Twfj2N4gNVtcgXkrk39HEYjk5+uF7SdNf4
+-----END CERTIFICATE-----""",
+    "certchain": """-----BEGIN CERTIFICATE-----
+MIIFQzCCAysCFEVQffqr0ScjpyZ6pmDsOOu71t70MA0GCSqGSIb3DQEBCwUAMF4x
+CzAJBgNVBAYTAlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxEzARBgNVBAoM
+CkNsb3VkU3RhY2sxDzANBgNVBAsMBkFwYWNoZTEPMA0GA1UEAwwGQXBhY2hlMB4X
+DTI1MDYxNjEwMjc1NloXDTMwMDYxNTEwMjc1NlowXjELMAkGA1UEBhMCWFgxCzAJ
+BgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEGA1UECgwKQ2xvdWRTdGFjazEPMA0G
+A1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFjaGUwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQCLiQmSjrht15R1F+r79m/LZN5hsfQBGp+dy+yrtsWfOOur
+RdXAwgbLxxsyKMQKWCQxlRI7wdhqh0L0ZBrIr9MjltYqsqLAoLmgY4eG/f6G8YGr
+O/rxzfwTLbCeaIseF/OMA6Sz125HXYp1bltYK4LsuC7tihZXbeVa5pUGs3Jwgcfx
+LYm4eB42Hp7Eg05uL8LbwT/1AjcwoWkTewKAWXA83zgLRDFDbl1t0IPHI4cdVvia
+BNwNbG49ZCF6OgmokSarQSe4Vbems1u9T9pAySXAVjEYBqFjKWyswpdr782uNLmB
+lCGm0pDeJ9/WASxbTJr7k9H6ZpnaHr54DG6ZqennWMz8w6r2pf7bp/EGZ3mZQ4s3
+5ylSP4cQt8CSSI8k2CflPGUyytUAiWlDS3qSyIuAOPKXDg7wIpcbwcu4VMeKnH0Z
+x7Uu9j1UDZEZoSu6UI/VInTl47k1/ECD+AO9yBzZSv+pTQmO3/Im3CcxsTHmVd5s
+Tl0CJ/jWNpo9DAMtmGvt6CBWBXGRsO2XNk7djRcq2CubiCpvODg+7CcR6CiZK73L
+1aOisLiq3+ofiJSSXRRuKtJlkQ4eSPSbYWkNJcKmIhbCoYOdH/Pe3/+RHjvNc1kO
+OUb+icmfzcMVAs3C5jybpazsfjDNQZXWAFx4FLDcqOVbrCwom+tMukw+hzlZnwID
+AQABMA0GCSqGSIb3DQEBCwUAA4ICAQAdexoMwn+Ol1A3+NOHk9WJZX+t2Q8/9wWb
+K+jSVleSfXXWsB1mC3fABVJQdCxtXCH3rpt4w7FK6aUes9VjqAHap4tt9WBq0Wqq
+vvMURFHfllxEM31Z35kBOCSQY9xwpGV1rRh/zYs4h55YixomR3nXNZ9cI8xzlSCi
+sMG0mv0y+yxPohKrZj3AzLYz/M11SimSoyRPIANI+cUg1nJXyQoHzVHWEp1Nj0HB
+M/GW05cxsWea7f5YcAW1JQI3FOkpwb72fIZOtMDa4PO8IYWXJAeAc/chw745/MTi
+Rvl2NT4RZBAcrSNbhCOzRPG/ZiG+ArQuCluZ9HHAXRBMTtlLk5DO4+XxZlyGpjwf
+uKniK8dccy9uU0ho73p9SNDhXH0yb9Naj8vd9NWzCUYaaBXt/92cIyhaAHAVFxJu
+o6jr2FLbnhSGF9EO/tHvF7LxZv1dnbInvlWHwoFQjwmoeB+e17lHBdPMnWnPKBZe
+jA2VH/IzGCucWuWQhruummO5GT8Z6F4jBwvafBo+QARKPZgEBpx3LycXrpkYI3LT
+GGOpGCxFt5tVZOEsC/jQ5rIljNSeTzWmzfNRn/yRUW97uWsrzcQIBAUtu/pQnyFQ
+WCnC1ipCp1zhJsXAFUKuqEfLngXodOvC4tAOr76h11S57o5lN4506Poq2mWgAZe/
+JZr9MEn1+w==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFnzCCA4egAwIBAgIUcUNMqgWoDLsvMj0YmEudj60EG5swDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEG
+A1UECgwKQ2xvdWRTdGFjazEPMA0GA1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFj
+aGUwIBcNMjUwNjE2MTAyNzM2WhgPMjEyNTA1MjMxMDI3MzZaMF4xCzAJBgNVBAYT
+AlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxEzARBgNVBAoMCkNsb3VkU3Rh
+Y2sxDzANBgNVBAsMBkFwYWNoZTEPMA0GA1UEAwwGQXBhY2hlMIICIjANBgkqhkiG
+9w0BAQEFAAOCAg8AMIICCgKCAgEAwVQaePulUM523gKw168ToYp+gt05bXbu4Gg8
+uaRDKhnRAX1sEgYwkQ36Q+iTDEM9sKRma8lMNMIqkZMQdk6sIGX6BL+6wUOb7mL0
+5+I0yO9i8ooaGgNaeNvZftNIRlLsnPMGJaeom2/66XV4CsMqoZKaJ1H/I8N+bAeD
+GvrBx+B4l9D3G390nQvot9JUzrJgGuLl0KDHapvhlR39cCgEfIii02uX1iy0qXlV
+b+G1kLvpeC7T+lsJxondPJ69aO3lbDv/izyWw7qqBC57UhT/oKDxJmjQqklqzhgt
+nM/p3YE7M0nkRi3LnRmsZBz7o1DRf+M29zypKzXVk1aJflL46AtLMmpDIzVrEB2M
+q7o47rstXusYRYsBCqGTgdI1fV/CkDsZY5XkPZh2dsjZCHIS4P03OqFGsc6PQha2
++y2AhV1pvywkDl48kPKSukHfV1RtaPZUZtcQKztwHH+aFfo9mD8z0H2HcExdXKzd
+jhRhI9ZSwFj3HEN9f5P8fS3lf5+fV7EEbG4NisieBj/UivW6QiTHpLD7wRLIUt2g
+XgXNF0lfJzYHbIcxQ6kfC5McU2fu6mUC+p/pNN8G0POS3S2T55tEUqLL4N0SadQy
+N1TZlTd2xTn+Hb6WlG0f5m97xGcNlGHKBvntFrHvOIfkEQ9ne3MlOO1Gjlintowo
+fRGf15kCAwEAAaNTMFEwHQYDVR0OBBYEFM4WEQJpN9M07Q8CHq+5owG93Dj8MB8G
+A1UdIwQYMBaAFM4WEQJpN9M07Q8CHq+5owG93Dj8MA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQELBQADggIBABr5RKGc/rKx4fOgyXNJR4aCJCTtPZKs4AUCCBYz
+cWOjJYGNvThOPSVx51nAD8+YP2BwkOIPfhl2u/+vQSSbz4OlauXLki2DUN8E2OFe
+gJfxPDzWOfAo/QOJcyHwSlnIQjiZzG2lK3eyf5IFnfQILQzDvXaUYvMBkl2hb5Q7
+44H6tRw78uuf/KsT4rY0bBFMN5DayjiyvoIDUvzCRqcb2KOi9DnZ7pXjduL7tO0j
+PhlQ24B77LVUUAvydIGUzmbhGC2VvY1qE7uaYgYtgSUZ0zSjJrHjUjVLMzRouNP7
+jpbBQRAcP4FDcOFZBHogunA0hxQdm0d8u3LqDYPNS0rpfW0ddU/72nfBX4bnoDEN
++anw4wOgFuUcoEThALWZ9ESVKxXQ9Fpvd6FRW8fLLqhXAuli1BqP1c1WRxagldYe
+nPGm/FGZyJ2xOak9Uigi9NAQ/vX6CEfgcJgFZmCo8EKH0d4Ut72vGUcPqiUhT2EI
+AFAd6drSyoUdXXniSMWky9Vrt+qtLuAD1nhHTv8ZPdItXokoiD6ea/4xrbUZn0qY
+lLMDyfY76UVF0ruTR2Q6IdSq/zSggdwgkTooOW4XZcRf5l/ZnoeVQ1QH9C85SIKH
+IKZwPeGUm+EntmpuCBDmQSHLRCGEThd64iOAjqLR6arLj4TBJzBrZsGHFJbm0OcI
+dwa9
+-----END CERTIFICATE-----""",
+    "enabledrevocationcheck": False
+}
+
+USER_DATA="""I2Nsb3VkLWNvbmZpZwoKcnVuY21kOgogIC0gc3VkbyBhcHQtZ2V0IHVwZGF0Z
+QogIC0gc3VkbyBhcHQtZ2V0IGluc3RhbGwgLXkgYXBhY2hlMgogIC0gc3Vkby
+BzeXN0ZW1jdGwgZW5hYmxlIGFwYWNoZTIKICAtIHN1ZG8gc3lzdGVtY3RsIHN0
+YXJ0IGFwYWNoZTIKICAtIGVjaG8gIlRlc3QgcGFnZSIgfHN1ZG8gdGVlIC92YX
+Ivd3d3L2h0bWwvaW5kZXguaHRtbAoKCg=="""
+
+class TestSslOffloading(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+
+        testClient = super(TestSslOffloading, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls._cleanup = []
+
+        # Get Zone, Domain and templates
+        cls.domain = get_domain(cls.apiclient)
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.hypervisor = testClient.getHypervisorInfo()
+
+        cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+
+        #Create an account, network, VM and IP addresses
+        cls.account = Account.create(
+                            cls.apiclient,
+                            cls.services["account"],
+                            admin=True,
+                            domainid=cls.domain.id
+                            )
+        cls.user = cls.account.user[0]
+        cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name)
+
+        # Save full chain as a file
+        with open(FULL_CHAIN, "w", encoding="utf-8") as f:
+            f.write(CERT["certchain"])
+
+        # Register template if needed
+        if cls.hypervisor.lower() == 'simulator':
+            cls.template = get_test_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.hypervisor)
+        else:
+            cls.template = Template.register(
+                cls.apiclient,
+                cls.services["test_templates_cloud_init"][cls.hypervisor.lower()],
+                zoneid=cls.zone.id,
+                hypervisor=cls.hypervisor,
+            )
+            cls.template.download(cls.apiclient)
+            cls._cleanup.append(cls.template)
+
+        if cls.template == FAILED:
+            assert False, "get_test_template() failed to return template"
+
+        # Create service offering
+        cls.service_offering = ServiceOffering.create(
+                                        cls.apiclient,
+                                        cls.services["service_offerings"]["big"]    # 512MB memory
+                                        )
+
+        # Create network offering
+        cls.services["isolated_network_offering"]["egress_policy"] = "true"
+        cls.network_offering = NetworkOffering.create(cls.apiclient,
+                                                      cls.services["isolated_network_offering"],
+                                                      conservemode=True)
+        cls.network_offering.update(cls.apiclient, state='Enabled')
+
+        cls._cleanup.append(cls.network_offering)
+        cls._cleanup.append(cls.service_offering)
+        cls._cleanup.append(cls.account)
+
+    def setUp(self):
+        self.apiclient = self.testClient.getApiClient()
+        self.cleanup = []
+
+    def tearDown(self):
+        super(TestSslOffloading, self).tearDown()
+
+    @classmethod
+    def tearDownClass(cls):
+        super(TestSslOffloading, cls).tearDownClass()
+        if os.path.exists(FULL_CHAIN):
+            os.remove(FULL_CHAIN)
+
+    def wait_for_service_ready(self, command, expected, retries=60):
+        output = None
+        def check_output():
+            try:
+                output = subprocess.check_output(command, shell=True).strip().decode('utf-8')
+            except Exception as e:
+                print("Failed to get output of command %s: %s" % (command, e))
+                if expected is None:
+                    print("But it is expected")
+                    return True, None
+                return False, None
+            print("Output of command %s: \n %s" %(command, output))
+            if expected is None:
+                print("But it is expected to be None")
+                return False, None
+            return (expected in output), None
+
+        res = wait_until(10, retries, check_output)
+        if not res:
+            self.fail("Failed to wait for http server to show content '%s'. The output is '%s'" % (expected, output))
+        return res
+
+    @attr(tags = ["advanced", "advancedns", "smoke"], required_hardware="true")
+    def test_01_ssl_offloading_isolated_network(self):
+        """Test to create Load balancing rule with SSL offloading"""
+
+        # Validate:
+        # 1. Create isolated network and vm instance
+        # 2. create LB with port 80 -> 80, verify the website (should get expected content)
+        # 3. create LB with port 443 -> 80, verify the website (should not work)
+        # 4. add cert to LB with port 443
+        # 5. verify the website (should get expected content)
+        # 6. remove cert from LB with port 443
+        # 7. delete SSL certificate
+
+        # Register Userdata
+        self.userdata = UserData.register(self.apiclient,
+                                         name="test-userdata",
+                                         userdata=USER_DATA,
+                                         account=self.account.name,
+                                         domainid=self.account.domainid
+                                         )
+
+        # Upload SSL Certificate
+        self.sslcert = SslCertificate.create(self.apiclient,
+                                            CERT,
+                                            name="test-ssl-certificate",
+                                            account=self.account.name,
+                                            domainid=self.account.domainid)
+
+        # 1. Create network
+        self.network = Network.create(self.apiclient,
+                                      zoneid=self.zone.id,
+                                      services=self.services["network"],
+                                      domainid=self.domain.id,
+                                      account=self.account.name,
+                                      networkofferingid=self.network_offering.id)
+        self.cleanup.append(self.network)
+
+        self.services["virtual_machine"]["networkids"] = [str(self.network.id)]
+
+        # Create vm instance
+        self.vm_1 = VirtualMachine.create(
+            self.apiclient,
+            self.services["virtual_machine"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            userdataid=self.userdata.userdata.id,
+            serviceofferingid=self.service_offering.id
+        )
+        self.cleanup.append(self.vm_1)
+
+        self.public_ip = PublicIPAddress.create(
+            self.apiclient,
+            self.account.name,
+            self.zone.id,
+            self.account.domainid,
+            self.services["virtual_machine"],
+            self.network.id)
+
+        # 2. create LB with port 80 -> 80, verify the website (should get expected content).
+        # firewall is open by default
+        lb_http = {
+            "name": "http",
+            "alg": "roundrobin",
+            "privateport": 80,
+            "publicport": 80,
+            "protocol": "tcp"
+        }
+        lb_rule_http = LoadBalancerRule.create(
+            self.apiclient,
+            lb_http,
+            self.public_ip.ipaddress.id,
+            accountid=self.account.name,
+            domainid=self.domain.id,
+            networkid=self.network.id
+        )
+        lb_rule_http.assign(self.apiclient, [self.vm_1])
+        command = "curl -L --connect-timeout 3 http://%s/" % self.public_ip.ipaddress.ipaddress
+        # wait 10 minutes until the webpage is available. it returns "503 Service Unavailable" if not available
+        self.wait_for_service_ready(command, CONTENT, 60)
+
+        # 3. create LB with port 443 -> 80, verify the website (should not work)
+        # firewall is open by default
+        lb_https = {
+            "name": "https",
+            "alg": "roundrobin",
+            "privateport": 80,
+            "publicport": 443,
+            "protocol": "ssl"
+        }
+        lb_rule_https = LoadBalancerRule.create(
+            self.apiclient,
+            lb_https,
+            self.public_ip.ipaddress.id,
+            accountid=self.account.name,
+            domainid=self.domain.id,
+            networkid=self.network.id
+        )
+        lb_rule_https.assign(self.apiclient, [self.vm_1])
+
+        command = "curl -L --connect-timeout 3 -k --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, None, 1)
+
+        command = "curl -L --connect-timeout 3 --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, None, 1)
+
+        # 4. add cert to LB with port 443
+        lb_rule_https.assignCert(self.apiclient, self.sslcert.id)
+
+        # 5. verify the website (should get expected content)
+        command = "curl -L --connect-timeout 3 --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, "SSL certificate problem", 1)
+
+        command = "curl -L --connect-timeout 3 -k --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, CONTENT, 1)
+
+        command = "curl -L --connect-timeout 3 --cacert %s --resolve %s:443:%s https://%s/" % (FULL_CHAIN, DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, CONTENT, 1)
+
+        # 6. remove cert from LB with port 443
+        lb_rule_https.removeCert(self.apiclient)
+
+        # 7. delete SSL certificate
+        self.sslcert.delete(self.apiclient)
+
+    @attr(tags = ["advanced", "advancedns", "smoke"], required_hardware="true")
+    def test_02_ssl_offloading_project_vpc(self):
+        """Test to create Load balancing rule with SSL offloading in VPC in user project"""
+
+        # Validate:
+        # 1. Create VPC, VPC tier and vm instance
+        # 2. create LB with port 80 -> 80, verify the website (should get expected content)
+        # 3. create LB with port 443 -> 80, verify the website (should not work)
+        # 4. add cert to LB with port 443
+        # 5. verify the website (should get expected content)
+        # 6. remove cert from LB with port 443
+        # 7. delete SSL certificate
+
+        # Create project by user
+        self.project = Project.create(
+            self.userapiclient,
+            self.services["project"]
+        )
+        self.cleanup.append(self.project)
+
+        # Register Userdata by user
+        self.userdata = UserData.register(self.userapiclient,
+                                          name="test-user-userdata",
+                                          userdata=USER_DATA,
+                                          projectid=self.project.id
+                                          )
+
+        # Upload SSL Certificate by user
+        self.sslcert = SslCertificate.create(self.userapiclient,
+                                             CERT,
+                                             name="test-user-ssl-certificate",
+                                             projectid=self.project.id
+                                             )
+
+        # 1. Create VPC and VPC tier
+        vpcOffering = VpcOffering.list(self.userapiclient, name="Default VPC offering")
+        self.assertTrue(vpcOffering is not None and len(
+            vpcOffering) > 0, "No VPC offerings found")
+
+        self.vpc = VPC.create(
+            apiclient=self.userapiclient,
+            services=self.services["vpc_vpn"]["vpc"],
+            vpcofferingid=vpcOffering[0].id,
+            zoneid=self.zone.id,
+            projectid=self.project.id
+        )
+        self.cleanup.append(self.vpc)
+
+        networkOffering = NetworkOffering.list(
+            self.userapiclient, name="DefaultIsolatedNetworkOfferingForVpcNetworks")
+        self.assertTrue(networkOffering is not None and len(
+            networkOffering) > 0, "No VPC based network offering")
+
+        self.network = Network.create(
+            apiclient=self.userapiclient,
+            services=self.services["vpc_vpn"]["network_1"],
+            networkofferingid=networkOffering[0].id,
+            zoneid=self.zone.id,
+            vpcid=self.vpc.id,
+            projectid=self.project.id
+        )
+        self.cleanup.append(self.network)
+
+        self.services["virtual_machine"]["networkids"] = [str(self.network.id)]
+
+        # Create vm instance
+        self.vm_2 = VirtualMachine.create(
+            self.userapiclient,
+            self.services["virtual_machine"],
+            templateid=self.template.id,
+            userdataid=self.userdata.userdata.id,
+            serviceofferingid=self.service_offering.id,
+            projectid=self.project.id
+        )
+        self.cleanup.append(self.vm_2)
+
+        self.public_ip = PublicIPAddress.create(
+            self.userapiclient,
+            zoneid=self.zone.id,
+            services=self.services["virtual_machine"],
+            networkid=self.network.id,
+            vpcid=self.vpc.id,
+            projectid=self.project.id
+        )
+
+        # 2. create LB with port 80 -> 80, verify the website (should get expected content).
+        # firewall is open by default
+        lb_http = {
+            "name": "http",
+            "alg": "roundrobin",
+            "privateport": 80,
+            "publicport": 80,
+            "protocol": "tcp"
+        }
+        lb_rule_http = LoadBalancerRule.create(
+            self.userapiclient,
+            lb_http,
+            self.public_ip.ipaddress.id,
+            networkid=self.network.id,
+            projectid=self.project.id
+        )
+        lb_rule_http.assign(self.userapiclient, [self.vm_2])
+        command = "curl -L --connect-timeout 3 http://%s/" % self.public_ip.ipaddress.ipaddress
+        # wait 10 minutes until the webpage is available. it returns "503 Service Unavailable" if not available
+        self.wait_for_service_ready(command, CONTENT, 60)
+
+        # 3. create LB with port 443 -> 80, verify the website (should not work)
+        # firewall is open by default
+        lb_https = {
+            "name": "https",
+            "alg": "roundrobin",
+            "privateport": 80,
+            "publicport": 443,
+            "protocol": "ssl"
+        }
+        lb_rule_https = LoadBalancerRule.create(
+            self.userapiclient,
+            lb_https,
+            self.public_ip.ipaddress.id,
+            networkid=self.network.id,
+            projectid=self.project.id
+        )
+        lb_rule_https.assign(self.userapiclient, [self.vm_2])
+
+        command = "curl -L --connect-timeout 3 -k --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, None, 1)
+
+        command = "curl -L --connect-timeout 3 --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, None, 1)
+
+        # 4. add cert to LB with port 443
+        lb_rule_https.assignCert(self.userapiclient, self.sslcert.id)
+
+        # 5. verify the website (should get expected content)
+        command = "curl -L --connect-timeout 3 --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, "SSL certificate problem", 1)
+
+        command = "curl -L --connect-timeout 3 -k --resolve %s:443:%s https://%s/" % (DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, CONTENT, 1)
+
+        command = "curl -L --connect-timeout 3 --cacert %s --resolve %s:443:%s https://%s/" % (FULL_CHAIN, DOMAIN, self.public_ip.ipaddress.ipaddress, DOMAIN)
+        self.wait_for_service_ready(command, CONTENT, 1)
+
+        # 6. remove cert from LB with port 443
+        lb_rule_https.removeCert(self.userapiclient)
+
+        # 7. delete SSL certificate
+        self.sslcert.delete(self.userapiclient)

Review Comment:
   same as above. ssl certificate is removed when cleanup the account



##########
test/integration/smoke/test_ssl_offloading.py:
##########
@@ -0,0 +1,553 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from marvin.codes import FAILED
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import wait_until
+from marvin.lib.base import (Account,
+                             Project,
+                             UserData,
+                             SslCertificate,
+                             Template,
+                             NetworkOffering,
+                             ServiceOffering,
+                             VirtualMachine,
+                             Network,
+                             VPC,
+                             VpcOffering,
+                             PublicIPAddress,
+                             LoadBalancerRule)
+from marvin.lib.common import (get_domain, get_zone, get_test_template)
+from nose.plugins.attrib import attr
+
+import os
+import subprocess
+
+
+_multiprocess_shared_ = True
+
+DOMAIN = "test-ssl-offloading.cloudstack.org"
+CONTENT = "Test page"
+FULL_CHAIN = "/tmp/full_chain.crt"
+
+CERT = {
+    "privatekey": """-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCph7jsoMCQirRn
+3obuvgnnefTXRQYd9tF9k2aCVkTiiisvC39px7MGdgvDXADhD9fmR7oyXVQlfNu0
+rXjjgsVT3r4bv+DVi81YGXnuU7h10yCOZJt21i6QGHN1CS0/TAfg0UhlACCEYNRx
+kB0klwUcj/jk/AKil1DoUGpvAm2gZsek/njb76/AeIfxc+Es4ZOPCVqQOHp6gI0q
+t6KDMkUwv8fyzrpScygMUPVYrLmm6D0pn8yd3ihW07wGxMjND6UgOnao8t6H3LaM
+Pe7eqSFzxunF9NFFjnUrKcHZZSledDM/37Kbqb/8T5f+4SwjioS1OdPCh8ApdiXq
+HNUwYkALAgMBAAECggEAK5JiiQ7X7053B6s96uaVDRVfRGTNKa5iMXBNDHq3wbHZ
+X4IJAVr+PE7ivxdKco3r45fT11X9ZpUsssdTJsZZiTDak69BTiFcaaRCnmqOIlpd
+J7vb6TMrTIW8RvxQ0M/txm6DuNHLibqJX5a2pszZ13l5cwECfF9/v/XLJTTukCbu
+6D/f3fBVFl1tM8y9saOEYLkdb4dILWY61bVSDNswgprz2EV1SFnk5jxz2FuBrM/Q
++7hINvjDcaRvcm59hRb1rkljv7S10VoNw/CFkU451csJkUe4vWZwB8lZK/XxLQG0
+HEdS1zU1XY8H8Y1RCrxjGRyiiWsBtUThhWYlPrGCoQKBgQDkP09YAlKqXhT69Kx5
+keg2i1jV2hA73zWbWXt9xp5jG5r3pl3m170DvKL93YIDnHtpTC56mlzGrzS7DSTN
+p0buY9Qb3fkJxunCpPVFo0HMFkpeR77ax0v34NzSohlRLKFo5R2M1cmDfbVbnSSl
+MB57FfRRMxzjrk+dJvjOeJsxjwKBgQC+JLb4B8CZjpurXYg3ySiRqFsCqkqob+kf
+9dR+rWvcR6vMTEyha0hUlDvTikDepU2smYR4oPHfdcXF9lAJ7T02UmQDeizAqR68
+u9e+yS0q3tdRnPPZmXJfaDCXG1hKMqF4YA5Vs0XAjleF3zHB+vBLrnlPpShtd/Mu
+sWTpxICTxQKBgQDSr/n+pE5IQwYczOO0aFGwn5pF9L9NdPHXz5aleETV+TJn7WL6
+ZiRsoaDWs7SCvtxQS2kP9RM0t5/2FeDmEMXx4aZ2fsSWGM3IxVo+iL+Aswa81n8/
+Ff5y9lb/+29hNdBcsjk/ukwEG3Lf+UNNVAie15oppgPByzJkPwgmFsAy0wKBgHDX
+/TZp82WuerhSw/rHiSoYjhqg0bnw4Ju1Gy0q4q5SYqTWS0wpDT4U0wSSMjlwRQ6/
+9RxZ9/G0RXFc4tdhUkig0PY3VcPpGnLL0BhL8GBW69ZlnVpwdK4meV/UPKucLLPx
+3dACmszSLSMn+LG0qVNg8mHQFJQS8eGuKcOKePw5AoGACuxtefROKdKOALh4lTi2
+VOwPZ+1jxsm6lKNccIEvbUpe3UXPgNWpJiDX8mUcob4/NBLzmV3BUVKbG7Exbo5J
+LoMfp7OsztWUFwt7YAvRfS8fHdhkEsxEf3T72ADieH5ZAuXFF+K0H3r6HtWPD4ws
+mTJjGP4+Bl/dFakA5FJcjHg=
+-----END PRIVATE KEY-----""",
+    "certificate": """-----BEGIN CERTIFICATE-----
+MIIFKjCCAxKgAwIBAgIUJ7BtN56KI8OuzbbM8SdtCLCB2UgwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEG
+A1UECgwKQ2xvdWRTdGFjazEPMA0GA1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFj
+aGUwHhcNMjUwNjIzMTMxMzA3WhcNMzUwNjIxMTMxMzA3WjBoMQswCQYDVQQGEwJY
+WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMQ8wDQYDVQQKDAZBcGFjaGUxEzAR
+BgNVBAsMCkNsb3VkU3RhY2sxGTAXBgNVBAMMECouY2xvdWRzdGFjay5vcmcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCph7jsoMCQirRn3obuvgnnefTX
+RQYd9tF9k2aCVkTiiisvC39px7MGdgvDXADhD9fmR7oyXVQlfNu0rXjjgsVT3r4b
+v+DVi81YGXnuU7h10yCOZJt21i6QGHN1CS0/TAfg0UhlACCEYNRxkB0klwUcj/jk
+/AKil1DoUGpvAm2gZsek/njb76/AeIfxc+Es4ZOPCVqQOHp6gI0qt6KDMkUwv8fy
+zrpScygMUPVYrLmm6D0pn8yd3ihW07wGxMjND6UgOnao8t6H3LaMPe7eqSFzxunF
+9NFFjnUrKcHZZSledDM/37Kbqb/8T5f+4SwjioS1OdPCh8ApdiXqHNUwYkALAgMB
+AAGjgdUwgdIwKwYDVR0RBCQwIoIQKi5jbG91ZHN0YWNrLm9yZ4IOY2xvdWRzdGFj
+ay5vcmcwHQYDVR0OBBYEFCcq7jrdsqTD+Xi85DCqjYdL1gOqMIGDBgNVHSMEfDB6
+oWKkYDBeMQswCQYDVQQGEwJYWDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMRMw
+EQYDVQQKDApDbG91ZFN0YWNrMQ8wDQYDVQQLDAZBcGFjaGUxDzANBgNVBAMMBkFw
+YWNoZYIURVB9+qvRJyOnJnqmYOw467vW3vQwDQYJKoZIhvcNAQELBQADggIBACld
+lEXgn/A4/kZQbLwwMxBvaoPDDaDaYVpPbOoPw7a8YkrL0rmPIc04PyX9GAqxdC+c
+qaEXvmp3I+BdT13XGcBosXO8uEQ3kses9F3MhOHORPS2mJag7t4eLnNX/0CgKTlR
+6yC2Gu7d3xPNJ+CKMxekdoF31StEFNAYI/La/q3D+IGsRCbrVu3xpPaw2XlXI7Ro
+RU7yebVmQPSNc75bm8Ydo1cdYtz9h8PVnc+6ThhSrdS3jYScj9DrX5ZJaKuZqSlu
+0ZqFXoBflme+cYB7nb9HqnIO67r9vzd2dTcErJVAk5jQqG5Y38d1tingDx1A5opU
+z4BkXEbHNV6VXYUQ5VE0dXO2sNvXVJrstwMPE8d3EvbX/1gWj8kuymbskrCjySE4
+4Yztkb0dsJkVU793lz3EV75DsXvj3gevK049nPv2Grt1+rTgFNa6NJnLvKIKk/mv
+fWjxbK2b/AAJ1ci6xtw/vKmIWoEu6uEMIJmhfBwuP+VnVJWJbmYXpNW/L5g21B76
+Fn8RuQa3mlm5lZrxEcJ/b6fF+2NPJwj7sh6l688VtNXoVSSyXUeV5HwqCv+YMjKn
+CtwpEN/eNHMbrkJvgYwSoOzqhV/wpmNi28S7MOm66JMECHOXOhk/eX2chIEjiVna
+MXhvr/Twfj2N4gNVtcgXkrk39HEYjk5+uF7SdNf4
+-----END CERTIFICATE-----""",
+    "certchain": """-----BEGIN CERTIFICATE-----
+MIIFQzCCAysCFEVQffqr0ScjpyZ6pmDsOOu71t70MA0GCSqGSIb3DQEBCwUAMF4x
+CzAJBgNVBAYTAlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxEzARBgNVBAoM
+CkNsb3VkU3RhY2sxDzANBgNVBAsMBkFwYWNoZTEPMA0GA1UEAwwGQXBhY2hlMB4X
+DTI1MDYxNjEwMjc1NloXDTMwMDYxNTEwMjc1NlowXjELMAkGA1UEBhMCWFgxCzAJ
+BgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEGA1UECgwKQ2xvdWRTdGFjazEPMA0G
+A1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFjaGUwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQCLiQmSjrht15R1F+r79m/LZN5hsfQBGp+dy+yrtsWfOOur
+RdXAwgbLxxsyKMQKWCQxlRI7wdhqh0L0ZBrIr9MjltYqsqLAoLmgY4eG/f6G8YGr
+O/rxzfwTLbCeaIseF/OMA6Sz125HXYp1bltYK4LsuC7tihZXbeVa5pUGs3Jwgcfx
+LYm4eB42Hp7Eg05uL8LbwT/1AjcwoWkTewKAWXA83zgLRDFDbl1t0IPHI4cdVvia
+BNwNbG49ZCF6OgmokSarQSe4Vbems1u9T9pAySXAVjEYBqFjKWyswpdr782uNLmB
+lCGm0pDeJ9/WASxbTJr7k9H6ZpnaHr54DG6ZqennWMz8w6r2pf7bp/EGZ3mZQ4s3
+5ylSP4cQt8CSSI8k2CflPGUyytUAiWlDS3qSyIuAOPKXDg7wIpcbwcu4VMeKnH0Z
+x7Uu9j1UDZEZoSu6UI/VInTl47k1/ECD+AO9yBzZSv+pTQmO3/Im3CcxsTHmVd5s
+Tl0CJ/jWNpo9DAMtmGvt6CBWBXGRsO2XNk7djRcq2CubiCpvODg+7CcR6CiZK73L
+1aOisLiq3+ofiJSSXRRuKtJlkQ4eSPSbYWkNJcKmIhbCoYOdH/Pe3/+RHjvNc1kO
+OUb+icmfzcMVAs3C5jybpazsfjDNQZXWAFx4FLDcqOVbrCwom+tMukw+hzlZnwID
+AQABMA0GCSqGSIb3DQEBCwUAA4ICAQAdexoMwn+Ol1A3+NOHk9WJZX+t2Q8/9wWb
+K+jSVleSfXXWsB1mC3fABVJQdCxtXCH3rpt4w7FK6aUes9VjqAHap4tt9WBq0Wqq
+vvMURFHfllxEM31Z35kBOCSQY9xwpGV1rRh/zYs4h55YixomR3nXNZ9cI8xzlSCi
+sMG0mv0y+yxPohKrZj3AzLYz/M11SimSoyRPIANI+cUg1nJXyQoHzVHWEp1Nj0HB
+M/GW05cxsWea7f5YcAW1JQI3FOkpwb72fIZOtMDa4PO8IYWXJAeAc/chw745/MTi
+Rvl2NT4RZBAcrSNbhCOzRPG/ZiG+ArQuCluZ9HHAXRBMTtlLk5DO4+XxZlyGpjwf
+uKniK8dccy9uU0ho73p9SNDhXH0yb9Naj8vd9NWzCUYaaBXt/92cIyhaAHAVFxJu
+o6jr2FLbnhSGF9EO/tHvF7LxZv1dnbInvlWHwoFQjwmoeB+e17lHBdPMnWnPKBZe
+jA2VH/IzGCucWuWQhruummO5GT8Z6F4jBwvafBo+QARKPZgEBpx3LycXrpkYI3LT
+GGOpGCxFt5tVZOEsC/jQ5rIljNSeTzWmzfNRn/yRUW97uWsrzcQIBAUtu/pQnyFQ
+WCnC1ipCp1zhJsXAFUKuqEfLngXodOvC4tAOr76h11S57o5lN4506Poq2mWgAZe/
+JZr9MEn1+w==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFnzCCA4egAwIBAgIUcUNMqgWoDLsvMj0YmEudj60EG5swDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEG
+A1UECgwKQ2xvdWRTdGFjazEPMA0GA1UECwwGQXBhY2hlMQ8wDQYDVQQDDAZBcGFj
+aGUwIBcNMjUwNjE2MTAyNzM2WhgPMjEyNTA1MjMxMDI3MzZaMF4xCzAJBgNVBAYT
+AlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxEzARBgNVBAoMCkNsb3VkU3Rh
+Y2sxDzANBgNVBAsMBkFwYWNoZTEPMA0GA1UEAwwGQXBhY2hlMIICIjANBgkqhkiG
+9w0BAQEFAAOCAg8AMIICCgKCAgEAwVQaePulUM523gKw168ToYp+gt05bXbu4Gg8
+uaRDKhnRAX1sEgYwkQ36Q+iTDEM9sKRma8lMNMIqkZMQdk6sIGX6BL+6wUOb7mL0
+5+I0yO9i8ooaGgNaeNvZftNIRlLsnPMGJaeom2/66XV4CsMqoZKaJ1H/I8N+bAeD
+GvrBx+B4l9D3G390nQvot9JUzrJgGuLl0KDHapvhlR39cCgEfIii02uX1iy0qXlV
+b+G1kLvpeC7T+lsJxondPJ69aO3lbDv/izyWw7qqBC57UhT/oKDxJmjQqklqzhgt
+nM/p3YE7M0nkRi3LnRmsZBz7o1DRf+M29zypKzXVk1aJflL46AtLMmpDIzVrEB2M
+q7o47rstXusYRYsBCqGTgdI1fV/CkDsZY5XkPZh2dsjZCHIS4P03OqFGsc6PQha2
++y2AhV1pvywkDl48kPKSukHfV1RtaPZUZtcQKztwHH+aFfo9mD8z0H2HcExdXKzd
+jhRhI9ZSwFj3HEN9f5P8fS3lf5+fV7EEbG4NisieBj/UivW6QiTHpLD7wRLIUt2g
+XgXNF0lfJzYHbIcxQ6kfC5McU2fu6mUC+p/pNN8G0POS3S2T55tEUqLL4N0SadQy
+N1TZlTd2xTn+Hb6WlG0f5m97xGcNlGHKBvntFrHvOIfkEQ9ne3MlOO1Gjlintowo
+fRGf15kCAwEAAaNTMFEwHQYDVR0OBBYEFM4WEQJpN9M07Q8CHq+5owG93Dj8MB8G
+A1UdIwQYMBaAFM4WEQJpN9M07Q8CHq+5owG93Dj8MA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQELBQADggIBABr5RKGc/rKx4fOgyXNJR4aCJCTtPZKs4AUCCBYz
+cWOjJYGNvThOPSVx51nAD8+YP2BwkOIPfhl2u/+vQSSbz4OlauXLki2DUN8E2OFe
+gJfxPDzWOfAo/QOJcyHwSlnIQjiZzG2lK3eyf5IFnfQILQzDvXaUYvMBkl2hb5Q7
+44H6tRw78uuf/KsT4rY0bBFMN5DayjiyvoIDUvzCRqcb2KOi9DnZ7pXjduL7tO0j
+PhlQ24B77LVUUAvydIGUzmbhGC2VvY1qE7uaYgYtgSUZ0zSjJrHjUjVLMzRouNP7
+jpbBQRAcP4FDcOFZBHogunA0hxQdm0d8u3LqDYPNS0rpfW0ddU/72nfBX4bnoDEN
++anw4wOgFuUcoEThALWZ9ESVKxXQ9Fpvd6FRW8fLLqhXAuli1BqP1c1WRxagldYe
+nPGm/FGZyJ2xOak9Uigi9NAQ/vX6CEfgcJgFZmCo8EKH0d4Ut72vGUcPqiUhT2EI
+AFAd6drSyoUdXXniSMWky9Vrt+qtLuAD1nhHTv8ZPdItXokoiD6ea/4xrbUZn0qY
+lLMDyfY76UVF0ruTR2Q6IdSq/zSggdwgkTooOW4XZcRf5l/ZnoeVQ1QH9C85SIKH
+IKZwPeGUm+EntmpuCBDmQSHLRCGEThd64iOAjqLR6arLj4TBJzBrZsGHFJbm0OcI
+dwa9
+-----END CERTIFICATE-----""",
+    "enabledrevocationcheck": False
+}
+
+USER_DATA="""I2Nsb3VkLWNvbmZpZwoKcnVuY21kOgogIC0gc3VkbyBhcHQtZ2V0IHVwZGF0Z
+QogIC0gc3VkbyBhcHQtZ2V0IGluc3RhbGwgLXkgYXBhY2hlMgogIC0gc3Vkby
+BzeXN0ZW1jdGwgZW5hYmxlIGFwYWNoZTIKICAtIHN1ZG8gc3lzdGVtY3RsIHN0
+YXJ0IGFwYWNoZTIKICAtIGVjaG8gIlRlc3QgcGFnZSIgfHN1ZG8gdGVlIC92YX
+Ivd3d3L2h0bWwvaW5kZXguaHRtbAoKCg=="""
+
+class TestSslOffloading(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+
+        testClient = super(TestSslOffloading, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls._cleanup = []
+
+        # Get Zone, Domain and templates
+        cls.domain = get_domain(cls.apiclient)
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.hypervisor = testClient.getHypervisorInfo()
+
+        cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+
+        #Create an account, network, VM and IP addresses
+        cls.account = Account.create(
+                            cls.apiclient,
+                            cls.services["account"],
+                            admin=True,
+                            domainid=cls.domain.id
+                            )
+        cls.user = cls.account.user[0]
+        cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name)
+
+        # Save full chain as a file
+        with open(FULL_CHAIN, "w", encoding="utf-8") as f:
+            f.write(CERT["certchain"])
+
+        # Register template if needed
+        if cls.hypervisor.lower() == 'simulator':
+            cls.template = get_test_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.hypervisor)
+        else:
+            cls.template = Template.register(
+                cls.apiclient,
+                cls.services["test_templates_cloud_init"][cls.hypervisor.lower()],
+                zoneid=cls.zone.id,
+                hypervisor=cls.hypervisor,
+            )
+            cls.template.download(cls.apiclient)
+            cls._cleanup.append(cls.template)
+
+        if cls.template == FAILED:
+            assert False, "get_test_template() failed to return template"
+
+        # Create service offering
+        cls.service_offering = ServiceOffering.create(
+                                        cls.apiclient,
+                                        cls.services["service_offerings"]["big"]    # 512MB memory
+                                        )
+
+        # Create network offering
+        cls.services["isolated_network_offering"]["egress_policy"] = "true"
+        cls.network_offering = NetworkOffering.create(cls.apiclient,
+                                                      cls.services["isolated_network_offering"],
+                                                      conservemode=True)
+        cls.network_offering.update(cls.apiclient, state='Enabled')
+
+        cls._cleanup.append(cls.network_offering)
+        cls._cleanup.append(cls.service_offering)
+        cls._cleanup.append(cls.account)

Review Comment:
   moved account creation to the last



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3210988687

   @DaanHoogland 
   thanks for the review
   
   I have addressed your comments, can you review again ? thanks


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3213501396

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3210093980

   @weizhouapache a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3217343528

   <b>[LL]Trillian test result (tid-7120)</b>
   Environment: kvm-rocky8 (x2), Advanced Networking with Mgmt server r8
   Total time taken: 44209 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t7120-kvm-rocky8.zip
   Smoke tests completed. 145 look OK, 2 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   test_oobm_issue_power_cycle | `Error` | 2.19 | test_outofbandmanagement_nestedplugin.py
   test_oobm_issue_power_off | `Error` | 2.18 | test_outofbandmanagement_nestedplugin.py
   test_oobm_issue_power_on | `Error` | 1.15 | test_outofbandmanagement_nestedplugin.py
   test_oobm_issue_power_reset | `Error` | 1.16 | test_outofbandmanagement_nestedplugin.py
   test_oobm_issue_power_soft | `Error` | 2.16 | test_outofbandmanagement_nestedplugin.py
   test_oobm_issue_power_status | `Error` | 1.15 | test_outofbandmanagement_nestedplugin.py
   test_01_webhook_deliveries | `Failure` | 7.90 | test_webhook_delivery.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3238959087

   <b>[SF] Trillian test result (tid-14145)</b>
   Environment: vmware-70u3 (x2), zone: Advanced Networking with Mgmt server ol8
   Total time taken: 57185 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14145-vmware-70u3.zip
   Smoke tests completed. 145 look OK, 2 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   test_01_ssl_offloading_isolated_network | `Failure` | 768.71 | test_ssl_offloading.py
   test_02_ssl_offloading_project_vpc | `Failure` | 723.91 | test_ssl_offloading.py
   test_01_vpn_usage | `Error` | 1.13 | test_usage.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3199795498

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3199925127

   Packaging result [SF]: ✖️ el8 ✖️ el9 ✖️ debian ✖️ suse15. SL-JID 14670


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3199956226

   
   @blueorangutan package
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3210999096

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3211476084

   @weizhouapache a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3232821194

   @borisstoyanov a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3239411987

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3239930814

   @weizhouapache a [SL] Trillian-Jenkins test job (ol8 mgmt + vmware-80u3) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "borisstoyanov (via GitHub)" <gi...@apache.org>.
borisstoyanov commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3236385058

   @blueorangutan test matrix


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3236096463

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✖️ debian ✔️ suse15. SL-JID 14761


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3212750139

   <b>[SF] Trillian test result (tid-14093)</b>
   Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
   Total time taken: 50158 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14093-kvm-ol8.zip
   Smoke tests completed. 147 look OK, 0 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3216083035

   <b>[SF] Trillian test result (tid-14103)</b>
   Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
   Total time taken: 52329 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14103-kvm-ol8.zip
   Smoke tests completed. 144 look OK, 3 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   test_01_invalid_upgrade_kubernetes_cluster | `Failure` | 127.33 | test_kubernetes_clusters.py
   test_02_upgrade_kubernetes_cluster | `Failure` | 122.23 | test_kubernetes_clusters.py
   test_03_deploy_and_scale_kubernetes_cluster | `Failure` | 117.19 | test_kubernetes_clusters.py
   test_04_autoscale_kubernetes_cluster | `Failure` | 120.07 | test_kubernetes_clusters.py
   test_05_basic_lifecycle_kubernetes_cluster | `Failure` | 122.20 | test_kubernetes_clusters.py
   test_06_delete_kubernetes_cluster | `Failure` | 122.15 | test_kubernetes_clusters.py
   test_08_upgrade_kubernetes_ha_cluster | `Failure` | 185.70 | test_kubernetes_clusters.py
   test_10_vpc_tier_kubernetes_cluster | `Failure` | 136.36 | test_kubernetes_clusters.py
   test_12_test_deploy_cluster_different_offerings_per_node_type | `Failure` | 129.69 | test_kubernetes_clusters.py
   ContextSuite context=TestKubernetesCluster>:teardown | `Error` | 19.73 | test_kubernetes_clusters.py
   test_oobm_issue_power_cycle | `Error` | 2.25 | test_outofbandmanagement_nestedplugin.py
   test_oobm_issue_power_off | `Error` | 2.22 | test_outofbandmanagement_nestedplugin.py
   test_oobm_issue_power_on | `Error` | 1.24 | test_outofbandmanagement_nestedplugin.py
   test_oobm_issue_power_reset | `Error` | 1.21 | test_outofbandmanagement_nestedplugin.py
   test_oobm_issue_power_soft | `Error` | 2.23 | test_outofbandmanagement_nestedplugin.py
   test_oobm_issue_power_status | `Error` | 2.27 | test_outofbandmanagement_nestedplugin.py
   test_01_webhook_deliveries | `Failure` | 8.73 | test_webhook_delivery.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3254342785

   @weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3291221557

   > [SF] Trillian test result (tid-14315) Environment: vmware-80u3 (x2), zone: Advanced Networking with Mgmt server ol8 Total time taken: 79654 seconds Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14315-vmware-80u3.zip Smoke tests completed. 145 look OK, 2 have errors, 0 did not run Only failed and skipped tests results shown below:
   > 
   > Test	Result	Time (s)	Test File
   > test_05_ping_in_cpvm_success	`Failure`	15.43	test_diagnostics.py
   > test_08_arping_in_ssvm	`Failure`	5.22	test_diagnostics.py
   > test_09_arping_in_cpvm	`Failure`	5.19	test_diagnostics.py
   > test_16_retrieve_ssvm_single_file	`Failure`	9.28	test_diagnostics.py
   > test_17_retrieve_cpvm_default_files	`Failure`	2.16	test_diagnostics.py
   > test_18_retrieve_cpvm_single_file	`Failure`	1.13	test_diagnostics.py
   > test_04_extract_Iso	`Failure`	1.13	test_iso.py
   
   manual check looks good
   ```
   [root@pr11468-t14315-vmware-80u3-marvin ~]# cat /marvin//MarvinLogs/test_diagnostics_7VWRMC/results.txt 
   test_01_1_create_iso_with_checksum_sha1_negative (smoke.test_iso.TestCreateISOWithChecksum) ... === TestName: test_01_1_create_iso_with_checksum_sha1_negative | Status : SUCCESS ===
   ok
   test_01_create_iso_with_checksum_sha1 (smoke.test_iso.TestCreateISOWithChecksum) ... === TestName: test_01_create_iso_with_checksum_sha1 | Status : SUCCESS ===
   ok
   test_02_1_create_iso_with_checksum_sha256_negative (smoke.test_iso.TestCreateISOWithChecksum) ... === TestName: test_02_1_create_iso_with_checksum_sha256_negative | Status : SUCCESS ===
   ok
   test_02_create_iso_with_checksum_sha256 (smoke.test_iso.TestCreateISOWithChecksum) ... === TestName: test_02_create_iso_with_checksum_sha256 | Status : SUCCESS ===
   ok
   test_03_1_create_iso_with_checksum_md5_negative (smoke.test_iso.TestCreateISOWithChecksum) ... === TestName: test_03_1_create_iso_with_checksum_md5_negative | Status : SUCCESS ===
   ok
   test_03_create_iso_with_checksum_md5 (smoke.test_iso.TestCreateISOWithChecksum) ... === TestName: test_03_create_iso_with_checksum_md5 | Status : SUCCESS ===
   ok
   test_04_create_iso_with_no_checksum (smoke.test_iso.TestCreateISOWithChecksum) ... === TestName: test_04_create_iso_with_no_checksum | Status : SUCCESS ===
   ok
   Test create public & private ISO ... === TestName: test_01_create_iso | Status : SUCCESS ===
   ok
   Test Edit ISO ... === TestName: test_02_edit_iso | Status : SUCCESS ===
   ok
   Test delete ISO ... === TestName: test_03_delete_iso | Status : SUCCESS ===
   ok
   Test for extract ISO ... === TestName: test_04_extract_Iso | Status : SUCCESS ===
   ok
   Update & Test for ISO permissions ... === TestName: test_05_iso_permissions | Status : SUCCESS ===
   ok
   Test for copy ISO from one zone to another ... SKIP: Not enough zones available to perform copy template
   Test delete ISO ... === TestName: test_07_list_default_iso | Status : SUCCESS ===
   ok
   Test Ping command execution in VR ... === TestName: test_01_ping_in_vr_success | Status : SUCCESS ===
   ok
   Test Ping command execution in VR ... === TestName: test_02_ping_in_vr_failure | Status : SUCCESS ===
   ok
   Test Ping command execution in SSVM ... === TestName: test_03_ping_in_ssvm_success | Status : SUCCESS ===
   ok
   Test Ping command execution in SSVM ... === TestName: test_04_ping_in_ssvm_failure | Status : SUCCESS ===
   ok
   Test Ping command execution in CPVM ... === TestName: test_05_ping_in_cpvm_success | Status : SUCCESS ===
   ok
   Test Ping command execution in CPVM ... === TestName: test_06_ping_in_cpvm_failure | Status : SUCCESS ===
   ok
   Test Arping command execution in VR ... === TestName: test_07_arping_in_vr | Status : SUCCESS ===
   ok
   Test Arping command execution in SSVM ... === TestName: test_08_arping_in_ssvm | Status : SUCCESS ===
   ok
   Test Arping command execution in CPVM ... === TestName: test_09_arping_in_cpvm | Status : SUCCESS ===
   ok
   Test traceroute command execution in VR ... === TestName: test_10_traceroute_in_vr | Status : SUCCESS ===
   ok
   Test Traceroute command execution in SSVM ... === TestName: test_11_traceroute_in_ssvm | Status : SUCCESS ===
   ok
   Test Traceroute command execution in CPVMM ... === TestName: test_12_traceroute_in_cpvm | Status : SUCCESS ===
   ok
   test_13_retrieve_vr_default_files (smoke.test_diagnostics.TestRemoteDiagnostics) ... === TestName: test_13_retrieve_vr_default_files | Status : SUCCESS ===
   ok
   test_14_retrieve_vr_one_file (smoke.test_diagnostics.TestRemoteDiagnostics) ... === TestName: test_14_retrieve_vr_one_file | Status : SUCCESS ===
   ok
   test_15_retrieve_ssvm_default_files (smoke.test_diagnostics.TestRemoteDiagnostics) ... === TestName: test_15_retrieve_ssvm_default_files | Status : SUCCESS ===
   ok
   test_16_retrieve_ssvm_single_file (smoke.test_diagnostics.TestRemoteDiagnostics) ... === TestName: test_16_retrieve_ssvm_single_file | Status : SUCCESS ===
   ok
   test_17_retrieve_cpvm_default_files (smoke.test_diagnostics.TestRemoteDiagnostics) ... === TestName: test_17_retrieve_cpvm_default_files | Status : SUCCESS ===
   ok
   test_18_retrieve_cpvm_single_file (smoke.test_diagnostics.TestRemoteDiagnostics) ... === TestName: test_18_retrieve_cpvm_single_file | Status : SUCCESS ===
   ok
   
   ----------------------------------------------------------------------
   Ran 32 tests in 624.346s
   
   OK (SKIP=1)
   
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "rohityadavcloud (via GitHub)" <gi...@apache.org>.
rohityadavcloud commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3279974082

   LGTM, merging this based on reviews and QA.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3244860614

   <b>[SF] Trillian Build Failed (tid-14188)<b/>


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3265523376

   
   @blueorangutan test ol8 vmware-80u3
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3239156240

   <b>[SF] Trillian test result (tid-14146)</b>
   Environment: xcpng82 (x2), zone: Advanced Networking with Mgmt server ol9
   Total time taken: 73155 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14146-xcpng82.zip
   Smoke tests completed. 140 look OK, 7 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   test_01_events_resource | `Error` | 200.92 | test_events_resource.py
   test_01_non_strict_host_anti_affinity | `Error` | 211.99 | test_nonstrict_affinity_group.py
   test_02_non_strict_host_affinity | `Error` | 58.29 | test_nonstrict_affinity_group.py
   test_01_primary_storage_iscsi | `Error` | 0.72 | test_primary_storage.py
   test_create_pvlan_network | `Error` | 0.10 | test_pvlan.py
   test_01_vpn_usage | `Error` | 1.10 | test_usage.py
   test_11_destroy_vm_and_volumes | `Error` | 41.33 | test_vm_life_cycle.py
   test_01_migrate_vm_strict_tags_success | `Error` | 59.00 | test_vm_strict_host_tags.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3255981233

   <b>[SF] Trillian Build Failed (tid-14218)<b/>


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3253652009

   @borisstoyanov a [SL] Jenkins job has been kicked to build packages. It will be bundled with  KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3253642505

   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "borisstoyanov (via GitHub)" <gi...@apache.org>.
borisstoyanov commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3249055271

   @blueorangutan test matrix 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3269665602

   <b>[SF] Trillian test result (tid-14236)</b>
   Environment: vmware-80u3 (x2), zone: Advanced Networking with Mgmt server ol8
   Total time taken: 80726 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr11468-t14236-vmware-80u3.zip
   Smoke tests completed. 145 look OK, 2 have errors, 0 did not run
   Only failed and skipped tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   ContextSuite context=TestSharedFSLifecycle>:setup | `Error` | 0.00 | test_sharedfs_lifecycle.py
   test_01_ssl_offloading_isolated_network | `Failure` | 1882.23 | test_ssl_offloading.py
   test_01_ssl_offloading_isolated_network | `Error` | 1882.26 | test_ssl_offloading.py
   test_02_ssl_offloading_project_vpc | `Error` | 712.65 | test_ssl_offloading.py
   test_02_ssl_offloading_project_vpc | `Error` | 712.66 | test_ssl_offloading.py
   ContextSuite context=TestSslOffloading>:teardown | `Error` | 843.72 | test_ssl_offloading.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "blueorangutan (via GitHub)" <gi...@apache.org>.
blueorangutan commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3200282192

   Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ debian ✔️ suse15. SL-JID 14671


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291067732


##########
core/src/main/java/com/cloud/network/HAProxyConfigurator.java:
##########
@@ -469,46 +477,62 @@ private String getLbSubRuleForStickiness(final LoadBalancerTO lbTO) {
         return sb.toString();
     }
 
-    private List<String> getRulesForPool(final LoadBalancerTO lbTO, final boolean keepAliveEnabled) {
+    private List<String> getRulesForPool(final LoadBalancerTO lbTO, final LoadBalancerConfigCommand lbCmd) {
         StringBuilder sb = new StringBuilder();
         final String poolName = sb.append(lbTO.getSrcIp().replace(".", "_")).append('-').append(lbTO.getSrcPort()).toString();
         final String publicIP = lbTO.getSrcIp();
         final int publicPort = lbTO.getSrcPort();
         final String algorithm = lbTO.getAlgorithm();
 
-        final List<String> result = new ArrayList<String>();
-        // add line like this: "listen  65_37_141_30-80\n\tbind 65.37.141.30:80"
-        sb = new StringBuilder();
-        sb.append("listen ").append(poolName);
-        result.add(sb.toString());
+        boolean sslOffloading = lbTO.getSslCert() != null && !lbTO.getSslCert().isRevoked()
+                && NetUtils.SSL_PROTO.equals(lbTO.getLbProtocol());
+
+        final List<String> frontendConfigs = new ArrayList<>();
+        final List<String> backendConfigs = new ArrayList<>();
+        final List<String> result = new ArrayList<>();
+
         sb = new StringBuilder();
         sb.append("\tbind ").append(publicIP).append(":").append(publicPort);
-        result.add(sb.toString());
+
+        if (sslOffloading) {
+            sb.append(" ssl crt ").append(SSL_CERTS_DIR).append(poolName).append(".pem");
+            // check for http2 support
+            sb.append(" alpn h2,http/1.1");

Review Comment:
   `h2` means `http2`.
   we need to support both `http2` and `http 1.1`
   
   this is an example of the settings
   https://ssl-config.mozilla.org/#server=haproxy&version=2.6&config=intermediate&openssl=3.0.16&guideline=5.4
   
   
   @DaanHoogland 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291107577


##########
core/src/main/java/com/cloud/network/HAProxyConfigurator.java:
##########
@@ -520,61 +544,69 @@ private List<String> getRulesForPool(final LoadBalancerTO lbTO, final boolean ke
             destsAvailable = true;
         }
 
-        Boolean httpbasedStickiness = false;
+        boolean httpbasedStickiness = false;
         /* attach stickiness sub rule only if the destinations are available */
-        if (stickinessSubRule != null && destsAvailable == true) {
+        if (stickinessSubRule != null && destsAvailable) {
             for (final StickinessPolicyTO stickinessPolicy : lbTO.getStickinessPolicies()) {
                 if (stickinessPolicy == null) {
                     continue;
                 }
                 if (StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName()) ||
                         StickinessMethodType.AppCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) {
                     httpbasedStickiness = true;
+                    break;
                 }
             }
             if (httpbasedStickiness) {
-                result.addAll(dstWithCookieSubRule);
+                backendConfigs.addAll(dstWithCookieSubRule);
             } else {
-                result.addAll(dstSubRule);
+                backendConfigs.addAll(dstSubRule);
             }
-            result.add(stickinessSubRule);
+            backendConfigs.add(stickinessSubRule);
         } else {
-            result.addAll(dstSubRule);
+            backendConfigs.addAll(dstSubRule);
         }
         if (stickinessSubRule != null && !destsAvailable) {
             logger.warn("Haproxy stickiness policy for lb rule: " + lbTO.getSrcIp() + ":" + lbTO.getSrcPort() + ": Not Applied, cause:  backends are unavailable");
         }
-        if (publicPort == NetUtils.HTTP_PORT && !keepAliveEnabled || httpbasedStickiness) {
-            sb = new StringBuilder();
-            sb.append("\t").append("mode http");
-            result.add(sb.toString());
-            sb = new StringBuilder();
-            sb.append("\t").append("option httpclose");
-            result.add(sb.toString());
+        boolean keepAliveEnabled = lbCmd.keepAliveEnabled;
+        boolean http = (publicPort == NetUtils.HTTP_PORT && !keepAliveEnabled);
+        if (http || httpbasedStickiness || sslOffloading) {
+            frontendConfigs.add("\tmode http");
+            String keepAliveLine = keepAliveEnabled ? "\tno option forceclose" : "\toption httpclose";
+            frontendConfigs.add(keepAliveLine);
         }
 
+        // add line like this: "listen  65_37_141_30-80\n\tbind 65.37.141.30:80"
+        result.add(String.format("listen %s", poolName));
+        result.addAll(frontendConfigs);
+
         String cidrList = lbTO.getCidrList();
 
         if (StringUtils.isNotBlank(cidrList)) {
             result.add(String.format("\tacl network_allowed src %s \n\ttcp-request connection reject if !network_allowed", cidrList));
         }
 
+        result.addAll(backendConfigs);
         result.add(blankLine);
         return result;
     }
 
     private String generateStatsRule(final LoadBalancerConfigCommand lbCmd, final String ruleName, final String statsIp) {
         final StringBuilder rule = new StringBuilder("\nlisten ").append(ruleName).append("\n\tbind ").append(statsIp).append(":").append(lbCmd.lbStatsPort);
         // TODO DH: write test for this in both cases
-        if (!lbCmd.keepAliveEnabled) {
-            logger.info("Haproxy mode http enabled");
-            rule.append("\n\tmode http\n\toption httpclose");
+        rule.append("\n\tmode http");
+        if (lbCmd.keepAliveEnabled) {
+            logger.info("Haproxy option http-keep-alive enabled");
+        } else {
+            logger.info("Haproxy option httpclose enabled");
+            rule.append("\n\toption httpclose");
         }
         rule.append("\n\tstats enable\n\tstats uri     ")
-        .append(lbCmd.lbStatsUri)
-        .append("\n\tstats realm   Haproxy\\ Statistics\n\tstats auth    ")
-        .append(lbCmd.lbStatsAuth);
-        rule.append("\n");
+                .append(lbCmd.lbStatsUri)
+                .append("\n\tstats realm   Haproxy\\ Statistics\n\tstats auth    ")
+                .append(lbCmd.lbStatsAuth)
+                .append("\n");

Review Comment:
   this is auto-format by intelliJ IDEA. I guess it is ok ?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291114686


##########
core/src/main/java/com/cloud/network/HAProxyConfigurator.java:
##########
@@ -696,4 +728,26 @@ public String[][] generateFwRules(final LoadBalancerConfigCommand lbCmd) {
 
         return result;
     }
+
+    @Override
+    public SslCertEntry[] generateSslCertEntries(LoadBalancerConfigCommand lbCmd) {
+        final Set<SslCertEntry> sslCertEntries = new HashSet<SslCertEntry>();
+        for (final LoadBalancerTO lbTO : lbCmd.getLoadBalancers()) {
+            if (lbTO.getSslCert() != null) {
+                final LbSslCert cert = lbTO.getSslCert();
+                if (cert.isRevoked()) {
+                    continue;
+                }
+                if (lbTO.getLbProtocol() == null || ! lbTO.getLbProtocol().equals(NetUtils.SSL_PROTO)) {
+                    continue;
+                }
+                StringBuilder sb = new StringBuilder();
+                final String name = sb.append(lbTO.getSrcIp().replace(".", "_")).append('-').append(lbTO.getSrcPort()).toString();
+                final SslCertEntry sslCertEntry = new SslCertEntry(name, cert.getCert(), cert.getKey(), cert.getChain(), cert.getPassword());
+                sslCertEntries.add(sslCertEntry);

Review Comment:
   will commit



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#issuecomment-3210090143

   @blueorangutan test


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Improvement: SSL offloading with Virtual Router [cloudstack]

Posted by "weizhouapache (via GitHub)" <gi...@apache.org>.
weizhouapache commented on code in PR #11468:
URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291172189


##########
server/src/main/java/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java:
##########
@@ -2257,12 +2262,21 @@ public LoadBalancer updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd) {
         LoadBalancerVO tmplbVo = _lbDao.findById(lbRuleId);
         boolean success = _lbDao.update(lbRuleId, lb);
 
-        // If algorithm is changed, have to reapply the lb config
-        if ((algorithm != null) && (tmplbVo.getAlgorithm().compareTo(algorithm) != 0)){
+        // If algorithm or lb protocol is changed, have to reapply the lb config
+        boolean needToReApplyRule = (algorithm != null && algorithm.equals(tmplbVo.getAlgorithm()))
+                || (lbProtocol != null && lbProtocol.equals(tmplbVo.getLbProtocol()));
+        if (needToReApplyRule) {
             try {
                 lb.setState(FirewallRule.State.Add);
                 _lbDao.persist(lb);
                 applyLoadBalancerConfig(lbRuleId);
+                if (!lb.getLbProtocol().equals(NetUtils.SSL_PROTO)) {
+                    LoadBalancerCertMapVO loadBalancerCertMapVO = _lbCertMapDao.findByLbRuleId(lbRuleId);
+                    if (loadBalancerCertMapVO != null) {
+                        logger.debug("Removing SSL cert for load balancer %s as the new protocol is not ssl but %s", lbRuleId, lb.getLbProtocol());
+                        _lbCertMapDao.remove(loadBalancerCertMapVO.getId());
+                    }
+                }

Review Comment:
   added method `removeCertMapIfExists`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org