cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From d...@apache.org
Subject git commit: updated refs/heads/master to c0c4626
Date Tue, 22 Oct 2013 10:45:06 GMT
Updated Branches:
  refs/heads/master 3f656b043 -> c0c46268a


CLOUDSTACK-4328 httpclose/mode as keepAliveEnabled


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/c0c46268
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/c0c46268
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/c0c46268

Branch: refs/heads/master
Commit: c0c46268acce36643d9a65f8a9a626e81508dcde
Parents: 3f656b0
Author: dhoogland <dhoogland@SBPLT101.sbp.lan>
Authored: Mon Sep 23 16:49:20 2013 +0200
Committer: Daan Hoogland <dhoogland@schubergphilis.com>
Committed: Tue Oct 22 12:44:23 2013 +0200

----------------------------------------------------------------------
 api/src/com/cloud/offering/NetworkOffering.java |  2 +
 .../org/apache/cloudstack/api/ApiConstants.java |  1 +
 .../admin/network/CreateNetworkOfferingCmd.java |  9 +-
 .../admin/network/UpdateNetworkOfferingCmd.java |  7 ++
 .../api/routing/LoadBalancerConfigCommand.java  |  4 +-
 .../com/cloud/network/HAProxyConfigurator.java  | 54 +++++++++--
 .../cloud/network/HAProxyConfiguratorTest.java  | 97 ++++++++++++++++++++
 .../configuration/ConfigurationManager.java     |  2 +-
 .../orchestration/NetworkOrchestrator.java      | 18 ++--
 .../com/cloud/offerings/NetworkOfferingVO.java  | 12 +++
 .../lb/ElasticLoadBalancerManagerImpl.java      |  2 +-
 .../lb/InternalLoadBalancerVMManagerImpl.java   |  2 +-
 .../configuration/ConfigurationManagerImpl.java |  9 +-
 .../VirtualNetworkApplianceManagerImpl.java     |  3 +-
 .../cloud/vpc/MockConfigurationManagerImpl.java |  2 +-
 .../CreateNetworkOfferingTest.java              | 20 ++--
 setup/db/db/schema-421to430.sql                 |  2 +
 17 files changed, 211 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/api/src/com/cloud/offering/NetworkOffering.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/offering/NetworkOffering.java b/api/src/com/cloud/offering/NetworkOffering.java
index 6c5573e..749dae3 100644
--- a/api/src/com/cloud/offering/NetworkOffering.java
+++ b/api/src/com/cloud/offering/NetworkOffering.java
@@ -130,4 +130,6 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
     boolean getEgressDefaultPolicy();
 
     Integer getConcurrentConnections();
+
+    boolean isKeepAliveEnabled();
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/api/src/org/apache/cloudstack/api/ApiConstants.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 8e88a38..c75e6a0 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -142,6 +142,7 @@ public class ApiConstants {
     public static final String MAX_SNAPS = "maxsnaps";
     public static final String MEMORY = "memory";
     public static final String MODE = "mode";
+    public static final String KEEPALIVE_ENABLED = "keepaliveenabled";
     public static final String NAME = "name";
     public static final String METHOD_NAME = "methodname";
     public static final String NETWORK_DOMAIN = "networkdomain";

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java
b/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java
index bdad904..7296d53 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java
@@ -96,12 +96,15 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
     private Boolean isPersistent;
     
     @Parameter(name=ApiConstants.DETAILS, type=CommandType.MAP, since="4.2.0", description="Network
offering details in key/value pairs." +
-    		" Supported keys are internallbprovider/publiclbprovider with service provider as a
value")
+            " Supported keys are internallbprovider/publiclbprovider with service provider
as a value")
     protected Map details;
 
     @Parameter(name=ApiConstants.EGRESS_DEFAULT_POLICY, type=CommandType.BOOLEAN, description="true
if default guest network egress policy is allow; false if default egress policy is deny")
     private Boolean egressDefaultPolicy;
 
+    @Parameter(name=ApiConstants.KEEPALIVE_ENABLED, type=CommandType.BOOLEAN, required=false,
description="if true keepalive will be turned on in the loadbalancer. At the time of writing
this has only an effect on haproxy; the mode http and httpclose options are unset in the haproxy
conf file.")
+    private Boolean keepAliveEnabled;
+
     @Parameter(name=ApiConstants.MAX_CONNECTIONS, type=CommandType.INTEGER, description="maximum
number of concurrent connections supported by the network offering")
     private Integer maxConnections;
 
@@ -175,6 +178,10 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
         return egressDefaultPolicy;
     }
 
+    public Boolean getKeepAliveEnabled() {
+        return keepAliveEnabled;
+    }
+
     public Integer getMaxconnections() {
         return maxConnections;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/api/src/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java
b/api/src/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java
index c9c4c8a..f9bdadb 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java
@@ -57,6 +57,9 @@ public class UpdateNetworkOfferingCmd extends BaseCmd {
     @Parameter(name=ApiConstants.STATE, type=CommandType.STRING, description="update state
for the network offering")
     private String state;
 
+    @Parameter(name=ApiConstants.KEEPALIVE_ENABLED, type=CommandType.BOOLEAN, required=false,
description="if true keepalive will be turned on in the loadbalancer. At the time of writing
this has only an effect on haproxy; the mode http and httpclose options are unset in the haproxy
conf file.")
+    private Boolean keepAliveEnabled;
+
     @Parameter(name=ApiConstants.MAX_CONNECTIONS, type=CommandType.INTEGER, description="maximum
number of concurrent connections supported by the network offering")
     private Integer maxConnections;
 
@@ -91,6 +94,10 @@ public class UpdateNetworkOfferingCmd extends BaseCmd {
     public Integer getMaxconnections() {
         return maxConnections;
     }
+
+    public Boolean getKeepAliveEnabled() {
+        return keepAliveEnabled;
+    }
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/core/src/com/cloud/agent/api/routing/LoadBalancerConfigCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/routing/LoadBalancerConfigCommand.java b/core/src/com/cloud/agent/api/routing/LoadBalancerConfigCommand.java
index ee29290..3a51e8a 100644
--- a/core/src/com/cloud/agent/api/routing/LoadBalancerConfigCommand.java
+++ b/core/src/com/cloud/agent/api/routing/LoadBalancerConfigCommand.java
@@ -33,6 +33,7 @@ public class LoadBalancerConfigCommand extends NetworkElementCommand {
     public String lbStatsAuth = "admin1:AdMiN123";
     public String lbStatsUri = "/admin?stats";
     public String maxconn ="";
+    public boolean keepAliveEnabled = false;
     NicTO nic;
     Long vpcId;
 
@@ -44,7 +45,7 @@ public class LoadBalancerConfigCommand extends NetworkElementCommand {
     	this.vpcId = vpcId;
     }
 
-    public LoadBalancerConfigCommand(LoadBalancerTO[] loadBalancers,String PublicIp,String
GuestIp,String PrivateIp, NicTO nic, Long vpcId, String maxconn) {
+    public LoadBalancerConfigCommand(LoadBalancerTO[] loadBalancers,String PublicIp,String
GuestIp,String PrivateIp, NicTO nic, Long vpcId, String maxconn, boolean keepAliveEnabled)
{
     	this.loadBalancers = loadBalancers;
     	this.lbStatsPublicIP = PublicIp;
     	this.lbStatsPrivateIP = PrivateIp;
@@ -52,6 +53,7 @@ public class LoadBalancerConfigCommand extends NetworkElementCommand {
     	this.nic = nic;
     	this.vpcId = vpcId;
         this.maxconn=maxconn;
+        this.keepAliveEnabled = keepAliveEnabled;
     }
 
     public NicTO getNic() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/core/src/com/cloud/network/HAProxyConfigurator.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/network/HAProxyConfigurator.java b/core/src/com/cloud/network/HAProxyConfigurator.java
index 2309125..ae49a2e 100644
--- a/core/src/com/cloud/network/HAProxyConfigurator.java
+++ b/core/src/com/cloud/network/HAProxyConfigurator.java
@@ -44,6 +44,7 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator {
     private static String[] globalSection = { "global",
             "\tlog 127.0.0.1:3914   local0 warning", 
             "\tmaxconn 4096",
+            "\tmaxpipes 1024",
             "\tchroot /var/lib/haproxy", 
             "\tuser haproxy",
             "\tgroup haproxy",
@@ -122,7 +123,9 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator {
         sb = new StringBuilder();
         // FIXME sb.append("\t").append("balance ").append(algorithm);
         result.add(sb.toString());
-        if (publicPort.equals(NetUtils.HTTP_PORT)) {
+        if (publicPort.equals(NetUtils.HTTP_PORT)
+                // && global option httpclose set (or maybe not in this spot???)
+                ) {
             sb = new StringBuilder();
             sb.append("\t").append("mode http");
             result.add(sb.toString());
@@ -434,7 +437,7 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator {
         return sb.toString();
     }
 
-    private List<String> getRulesForPool(LoadBalancerTO lbTO)  {
+    private List<String> getRulesForPool(LoadBalancerTO lbTO, boolean keepAliveEnabled)
 {
         StringBuilder sb = new StringBuilder();
         String poolName = sb.append(lbTO.getSrcIp().replace(".", "_"))
                 .append('-').append(lbTO.getSrcPort()).toString();
@@ -498,7 +501,9 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator {
         if ((stickinessSubRule != null) && !destsAvailable) {
             s_logger.warn("Haproxy stickiness policy for lb rule: " + lbTO.getSrcIp() + ":"
+ lbTO.getSrcPort() +": Not Applied, cause:  backends are unavailable");
         }
-        if ((publicPort.equals(NetUtils.HTTP_PORT)) || (httpbasedStickiness) ) {
+        if ((publicPort.equals(NetUtils.HTTP_PORT)
+              && !keepAliveEnabled
+                ) || (httpbasedStickiness) ) {
             sb = new StringBuilder();
             sb.append("\t").append("mode http");
             result.add(sb.toString());
@@ -516,23 +521,58 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator
{
         StringBuilder rule = new StringBuilder("\nlisten ").append(ruleName)
                 .append(" ").append(statsIp).append(":")
                 .append(lbCmd.lbStatsPort);
+        // TODO DH: write test for this in both cases
+        if(!lbCmd.keepAliveEnabled) {
+            s_logger.info("Haproxy mode http enabled");
+            rule.append("\n\tmode http\n\toption httpclose");
+        }
         rule.append(
-                "\n\tmode http\n\toption httpclose\n\tstats enable\n\tstats uri     ")
+                "\n\tstats enable\n\tstats uri     ")
                 .append(lbCmd.lbStatsUri)
                 .append("\n\tstats realm   Haproxy\\ Statistics\n\tstats auth    ")
                 .append(lbCmd.lbStatsAuth);
         rule.append("\n");
-        return rule.toString();
+        String result = rule.toString();
+        if(s_logger.isDebugEnabled()) {
+            s_logger.debug("Haproxystats rule: " + result);
+        }
+        return result;
     }
 
     @Override
     public String[] generateConfiguration(LoadBalancerConfigCommand lbCmd)   {
         List<String> result = new ArrayList<String>();
         List <String> gSection =  Arrays.asList(globalSection);
+//        note that this is overwritten on the String in the static ArrayList<String>

         gSection.set(2,"\tmaxconn " + lbCmd.maxconn);
+        // TODO DH: write test for this function
+        String pipesLine = "\tmaxpipes " + Long.toString(Long.parseLong(lbCmd.maxconn)/4);
+        gSection.set(3,pipesLine);
+        if(s_logger.isDebugEnabled()) {
+            for(String s : gSection) {
+                s_logger.debug("global section: " + s);
+            }
+        }
         result.addAll(gSection);
+        // TODO decide under what circumstances these options are needed
+//        result.add("\tnokqueue");
+//        result.add("\tnopoll");
+
         result.add(blankLine);
-        result.addAll(Arrays.asList(defaultsSection));
+        List <String> dSection =  Arrays.asList(defaultsSection);
+        if(lbCmd.keepAliveEnabled) {
+            dSection.set(6, "\t#no option set here :<"); 
+            dSection.set(7, "\tno option forceclose");
+        } else {
+            dSection.set(6, "\toption forwardfor"); 
+            dSection.set(7, "\toption forceclose");
+        }
+        if(s_logger.isDebugEnabled()) {
+            for(String s : dSection) {
+                s_logger.debug("default section: " + s);
+            }
+        }
+        result.addAll(dSection);
         if (!lbCmd.lbStatsVisibility.equals("disabled")) {
             /* new rule : listen admin_page guestip/link-local:8081 */
             if (lbCmd.lbStatsVisibility.equals("global")) {
@@ -571,7 +611,7 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator {
             if ( lbTO.isRevoked() ) {
                 continue;
             }
-            List<String> poolRules = getRulesForPool(lbTO);
+            List<String> poolRules = getRulesForPool(lbTO, lbCmd.keepAliveEnabled);
             result.addAll(poolRules);
             has_listener = true;
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/core/test/com/cloud/network/HAProxyConfiguratorTest.java
----------------------------------------------------------------------
diff --git a/core/test/com/cloud/network/HAProxyConfiguratorTest.java b/core/test/com/cloud/network/HAProxyConfiguratorTest.java
new file mode 100644
index 0000000..d854231
--- /dev/null
+++ b/core/test/com/cloud/network/HAProxyConfiguratorTest.java
@@ -0,0 +1,97 @@
+// 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.
+package com.cloud.network;
+
+import static org.junit.Assert.*;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
+import com.cloud.agent.api.to.LoadBalancerTO;
+
+/**
+ * @author dhoogland
+ *
+ */
+public class HAProxyConfiguratorTest {
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @BeforeClass
+    public static void setUpBeforeClass() throws Exception {
+    }
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @AfterClass
+    public static void tearDownAfterClass() throws Exception {
+    }
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    /**
+     * Test method for {@link com.cloud.network.HAProxyConfigurator#generateConfiguration(com.cloud.agent.api.routing.LoadBalancerConfigCommand)}.
+     */
+    @Test
+    public void testGenerateConfigurationLoadBalancerConfigCommand() {
+        LoadBalancerTO lb = new LoadBalancerTO("1", "10.2.0.1", 80, "http", "bla", false,
false, false, null);
+        LoadBalancerTO[] lba = new LoadBalancerTO[1];
+        lba[0] = lb;
+        HAProxyConfigurator hpg = new HAProxyConfigurator();
+        LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1",
"10.1.1.1", null, 1L, "12", false);
+        String result = genConfig(hpg, cmd);
+        assertTrue("keepalive disabled should result in 'mode http' in the resulting haproxy
config", result.contains("mode http"));
+
+        cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1", "10.1.1.1", null,
1L, "4", true);
+        result = genConfig(hpg, cmd);
+        assertTrue("keepalive enabled should not result in 'mode http' in the resulting haproxy
config",! result.contains("mode http"));
+        // TODO
+        // create lb command
+        // setup tests for
+        // maxconn (test for maxpipes as well)
+        // httpmode
+    }
+
+    private String genConfig(HAProxyConfigurator hpg, LoadBalancerConfigCommand cmd) {
+        String [] sa = hpg.generateConfiguration(cmd);
+        StringBuilder sb = new StringBuilder();
+        for(String s: sa) {
+            sb.append(s).append('\n');
+        }
+        return sb.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java
----------------------------------------------------------------------
diff --git a/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java b/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java
index 5e1b9b5..03a549f 100755
--- a/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java
+++ b/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java
@@ -210,7 +210,7 @@ public interface ConfigurationManager {
 
     NetworkOfferingVO createNetworkOffering(String name, String displayText, TrafficType
trafficType, String tags, boolean specifyVlan, Availability availability, Integer networkRate,
Map<Service, Set<Provider>> serviceProviderMap,
             boolean isDefault, Network.GuestType type, boolean systemOnly, Long serviceOfferingId,
boolean conserveMode, Map<Service, Map<Capability, String>> serviceCapabilityMap,
-            boolean specifyIpRanges, boolean isPersistent, Map<NetworkOffering.Detail,String>
details, boolean egressDefaultPolicy, Integer maxconn);
+            boolean specifyIpRanges, boolean isPersistent, Map<NetworkOffering.Detail,String>
details, boolean egressDefaultPolicy, Integer maxconn, boolean enableKeepAlive);
 
     Vlan createVlanAndPublicIpRange(long zoneId, long networkId, long physicalNetworkId,
boolean forVirtualNetwork, Long podId, String startIP, String endIP, String vlanGateway, String
vlanNetmask, String vlanId, Account vlanOwner, String startIPv6, String endIPv6, String vlanIp6Gateway,
String vlanIp6Cidr) throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException;
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
index 3c4b1ed..8ba3fdf 100755
--- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
+++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
@@ -409,7 +409,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
         if (_networkOfferingDao.findByUniqueName(NetworkOffering.QuickCloudNoServices) ==
null) {
             offering = _configMgr.createNetworkOffering(NetworkOffering.QuickCloudNoServices,
"Offering for QuickCloud with no services", TrafficType.Guest, null, true,
                 Availability.Optional, null, new HashMap<Network.Service, Set<Network.Provider>>(),
true, Network.GuestType.Shared, false, null, true, null, true, false, null,
-                false, null);
+                false, null, true);
             offering.setState(NetworkOffering.State.Enabled);
             _networkOfferingDao.update(offering.getId(), offering);
         }
@@ -418,7 +418,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
         if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultSharedNetworkOfferingWithSGService)
== null) {
             offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultSharedNetworkOfferingWithSGService,
"Offering for Shared Security group enabled networks",
                 TrafficType.Guest, null, true, Availability.Optional, null, defaultSharedNetworkOfferingProviders,
true, Network.GuestType.Shared, false, null, true, null, true,
-                false, null, false, null);
+                false, null, false, null, true);
             offering.setState(NetworkOffering.State.Enabled);
             _networkOfferingDao.update(offering.getId(), offering);
         }
@@ -426,7 +426,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
         //#3 - shared network offering with no SG service
         if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultSharedNetworkOffering)
== null) {
             offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultSharedNetworkOffering,
"Offering for Shared networks", TrafficType.Guest, null, true,
-                Availability.Optional, null, defaultSharedNetworkOfferingProviders, true,
Network.GuestType.Shared, false, null, true, null, true, false, null, false, null);
+                Availability.Optional, null, defaultSharedNetworkOfferingProviders, true,
Network.GuestType.Shared, false, null, true, null, true, false, null, false, null, true);
             offering.setState(NetworkOffering.State.Enabled);
             _networkOfferingDao.update(offering.getId(), offering);
         }
@@ -435,7 +435,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
         if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingWithSourceNatService)
== null) {
             offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingWithSourceNatService,
                 "Offering for Isolated networks with Source Nat service enabled", TrafficType.Guest,
null, false, Availability.Required, null,
-                defaultIsolatedSourceNatEnabledNetworkOfferingProviders, true, Network.GuestType.Isolated,
false, null, true, null, false, false, null, false, null);
+                defaultIsolatedSourceNatEnabledNetworkOfferingProviders, true, Network.GuestType.Isolated,
false, null, true, null, false, false, null, false, null, true);
 
             offering.setState(NetworkOffering.State.Enabled);
             _networkOfferingDao.update(offering.getId(), offering);
@@ -445,7 +445,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
         if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks)
== null) {
             offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks,
                 "Offering for Isolated VPC networks with Source Nat service enabled", TrafficType.Guest,
null, false, Availability.Optional, null, defaultVPCOffProviders, true,
-                Network.GuestType.Isolated, false, null, false, null, false, false, null,
false, null);
+                Network.GuestType.Isolated, false, null, false, null, false, false, null,
false, null, true);
             offering.setState(NetworkOffering.State.Enabled);
             _networkOfferingDao.update(offering.getId(), offering);
         }
@@ -456,7 +456,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
             defaultVPCOffProviders.remove(Service.Lb);
             offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksNoLB,
                 "Offering for Isolated VPC networks with Source Nat service enabled and LB
service disabled", TrafficType.Guest, null, false, Availability.Optional, null,
-                defaultVPCOffProviders, true, Network.GuestType.Isolated, false, null, false,
null, false, false, null, false, null);
+                defaultVPCOffProviders, true, Network.GuestType.Isolated, false, null, false,
null, false, false, null, false, null, true);
             offering.setState(NetworkOffering.State.Enabled);
             _networkOfferingDao.update(offering.getId(), offering);
         }
@@ -465,7 +465,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
         if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOffering)
== null) {
             offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOffering,
"Offering for Isolated networks with no Source Nat service",
                 TrafficType.Guest, null, true, Availability.Optional, null, defaultIsolatedNetworkOfferingProviders,
true, Network.GuestType.Isolated, false, null, true, null,
-                true, false, null, false, null);
+                true, false, null, false, null, true);
             offering.setState(NetworkOffering.State.Enabled);
             _networkOfferingDao.update(offering.getId(), offering);
         }
@@ -489,7 +489,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
         if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB)
== null) {
             offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB,
                 "Offering for Isolated VPC networks with Internal Lb support", TrafficType.Guest,
null, false, Availability.Optional, null, internalLbOffProviders, true,
-                Network.GuestType.Isolated, false, null, false, null, false, false, null,
false, null);
+                Network.GuestType.Isolated, false, null, false, null, false, false, null,
false, null, true);
             offering.setState(NetworkOffering.State.Enabled);
             offering.setInternalLb(true);
             offering.setPublicLb(false);
@@ -521,7 +521,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
         if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultSharedEIPandELBNetworkOffering)
== null) {
             offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultSharedEIPandELBNetworkOffering,
                 "Offering for Shared networks with Elastic IP and Elastic LB capabilities",
TrafficType.Guest, null, true, Availability.Optional, null, netscalerServiceProviders,
-                true, Network.GuestType.Shared, false, null, true, serviceCapabilityMap,
true, false, null, false, null);
+                true, Network.GuestType.Shared, false, null, true, serviceCapabilityMap,
true, false, null, false, null, true);
             offering.setState(NetworkOffering.State.Enabled);
             offering.setDedicatedLB(false);
             _networkOfferingDao.update(offering.getId(), offering);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
index eefdc94..d9fb543 100755
--- a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
+++ b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
@@ -136,6 +136,8 @@ public class NetworkOfferingVO implements NetworkOffering {
     @Column(name = "concurrent_connections")
     Integer concurrentConnections;
 
+    @Column(name = "keep_alive_enabled")
+    boolean keepAliveEnabled = false;
 
     @Override
     public String getDisplayText() {
@@ -149,6 +151,15 @@ public class NetworkOfferingVO implements NetworkOffering {
     boolean publicLb;
 
     @Override
+    public boolean isKeepAliveEnabled() {
+        return keepAliveEnabled;
+    }
+
+    public void setKeepAliveEnabled(boolean keepAliveEnabled) {
+        this.keepAliveEnabled = keepAliveEnabled;
+    }
+
+    @Override
     public long getId() {
         return id;
     }
@@ -430,6 +441,7 @@ public class NetworkOfferingVO implements NetworkOffering {
         this.internalLb = internalLb;
     }
 
+    @Override
     public Integer getConcurrentConnections() {
         return  this.concurrentConnections;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java
b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java
index 3f8fc5c..ab414de 100644
--- a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java
+++ b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java
@@ -311,7 +311,7 @@ public class ElasticLoadBalancerManagerImpl extends ManagerBase implements
Elast
             maxconn = offering.getConcurrentConnections().toString();
         }
         LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lbs,elbVm.getPublicIpAddress(),
-                _nicDao.getIpAddress(guestNetworkId, elbVm.getId()),elbVm.getPrivateIpAddress(),
null, null, maxconn);
+                _nicDao.getIpAddress(guestNetworkId, elbVm.getId()),elbVm.getPrivateIpAddress(),
null, null, maxconn, offering.isKeepAliveEnabled());
         cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP,
                 elbVm.getPrivateIpAddress());
         cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME,

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java
b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java
index 5da6e02..b6269eb 100644
--- a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java
+++ b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java
@@ -461,7 +461,7 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements
In
         }
         LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lbs, guestNic.getIp4Address(),
                 guestNic.getIp4Address(), internalLbVm.getPrivateIpAddress(),
-                _itMgr.toNicTO(guestNicProfile, internalLbVm.getHypervisorType()), internalLbVm.getVpcId(),
maxconn);
+                _itMgr.toNicTO(guestNicProfile, internalLbVm.getHypervisorType()), internalLbVm.getVpcId(),
maxconn, offering.isKeepAliveEnabled());
 
         cmd.lbStatsVisibility = _configDao.getValue(Config.NetworkLBHaproxyStatsVisbility.key());
         cmd.lbStatsUri = _configDao.getValue(Config.NetworkLBHaproxyStatsUri.key());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index 349bd54..6460276 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -3646,6 +3646,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements
Configurati
         Map<String, String> detailsStr = cmd.getDetails();
         Boolean egressDefaultPolicy = cmd.getEgressDefaultPolicy();
         Integer maxconn = null;
+        boolean enableKeepAlive = false;
 
         // Verify traffic type
         for (TrafficType tType : TrafficType.values()) {
@@ -3807,6 +3808,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements
Configurati
                 maxconn=Integer.parseInt(_configDao.getValue(Config.NetworkLBHaproxyMaxConn.key()));
             }
         }
+        if(cmd.getKeepAliveEnabled() != null && cmd.getKeepAliveEnabled()) {
+            enableKeepAlive = true;
+        }
         
         // validate the Source NAT service capabilities specified in the network
         // offering
@@ -3865,7 +3869,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements
Configurati
 
         NetworkOffering offering = createNetworkOffering(name, displayText, trafficType,
tags, specifyVlan, availability, networkRate,
                 serviceProviderMap, false, guestType, false, serviceOfferingId, conserveMode,
serviceCapabilityMap,
-                specifyIpRanges, isPersistent, details, egressDefaultPolicy, maxconn);
+                specifyIpRanges, isPersistent, details, egressDefaultPolicy, maxconn, enableKeepAlive);
         CallContext.current().setEventDetails(" Id: " + offering.getId() + " Name: " + name);
         return offering;
     }
@@ -3987,7 +3991,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements
Configurati
             Map<Service, Set<Provider>> serviceProviderMap, boolean isDefault,
Network.GuestType type,
             boolean systemOnly, Long serviceOfferingId, boolean conserveMode,
             Map<Service, Map<Capability, String>> serviceCapabilityMap, boolean
specifyIpRanges, boolean isPersistent,
-            Map<NetworkOffering.Detail, String> details, boolean egressDefaultPolicy,
Integer maxconn) {
+            Map<NetworkOffering.Detail, String> details, boolean egressDefaultPolicy,
Integer maxconn, boolean enableKeepAlive) {
 
         String multicastRateStr = _configDao.getValue("multicast.throttling.rate");
         int multicastRate = ((multicastRateStr == null) ? 10 : Integer.parseInt(multicastRateStr));
@@ -4146,6 +4150,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements
Configurati
         // 1) create network offering object
         s_logger.debug("Adding network offering " + offering);
         offering.setConcurrentConnections(maxconn);
+        offering.setKeepAliveEnabled(enableKeepAlive);
         offering = _networkOfferingDao.persist(offering, details);
         // 2) populate services and providers
         if (serviceProviderMap != null) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index 1958d1e..3dfcad5 100755
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -3328,9 +3328,10 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase
implements V
         else {
             maxconn = offering.getConcurrentConnections().toString();
         }
+
         LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lbs, routerPublicIp,
                 getRouterIpInNetwork(guestNetworkId, router.getId()), router.getPrivateIpAddress(),
-                _itMgr.toNicTO(nicProfile, router.getHypervisorType()), router.getVpcId(),
maxconn);
+                _itMgr.toNicTO(nicProfile, router.getHypervisorType()), router.getVpcId(),
maxconn, offering.isKeepAliveEnabled());
 
         cmd.lbStatsVisibility = _configDao.getValue(Config.NetworkLBHaproxyStatsVisbility.key());
         cmd.lbStatsUri = _configDao.getValue(Config.NetworkLBHaproxyStatsUri.key());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
index c9a0480..3147f1f 100755
--- a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
+++ b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
@@ -432,7 +432,7 @@ public class MockConfigurationManagerImpl extends ManagerBase implements
Configu
     @Override
     public NetworkOfferingVO createNetworkOffering(String name, String displayText, TrafficType
trafficType, String tags, boolean specifyVlan, Availability availability, Integer networkRate,
             Map<Service, Set<Provider>> serviceProviderMap, boolean isDefault,
GuestType type, boolean systemOnly, Long serviceOfferingId, boolean conserveMode,
-            Map<Service, Map<Capability, String>> serviceCapabilityMap, boolean
specifyIpRanges, boolean isPersistent, Map<NetworkOffering.Detail,String> details, boolean
egressDefaultPolicy, Integer maxconn) {
+            Map<Service, Map<Capability, String>> serviceCapabilityMap, boolean
specifyIpRanges, boolean isPersistent, Map<NetworkOffering.Detail,String> details, boolean
egressDefaultPolicy, Integer maxconn, boolean enableKeepAlive) {
         // TODO Auto-generated method stub
         return null;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java
----------------------------------------------------------------------
diff --git a/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java
b/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java
index 1f1fb75..f2ebf67 100644
--- a/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java
+++ b/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java
@@ -106,7 +106,7 @@ public class CreateNetworkOfferingTest extends TestCase{
     public void createSharedNtwkOffWithVlan() {
         NetworkOfferingVO off = configMgr.createNetworkOffering("shared", "shared", TrafficType.Guest,
null, true,
                 Availability.Optional, 200, null, false, Network.GuestType.Shared, false,
-                null, false, null, true, false, null, false, null);
+                null, false, null, true, false, null, false, null, true);
         assertNotNull("Shared network offering with specifyVlan=true failed to create ",
off);
     }
     
@@ -115,7 +115,7 @@ public class CreateNetworkOfferingTest extends TestCase{
         try {
             NetworkOfferingVO off = configMgr.createNetworkOffering("shared", "shared", TrafficType.Guest,
null, false,
                     Availability.Optional, 200, null, false, Network.GuestType.Shared, false,
-                    null, false, null, true, false, null, false, null);
+                    null, false, null, true, false, null, false, null, true);
             assertNull("Shared network offering with specifyVlan=false was created", off);
         } catch (InvalidParameterValueException ex) {
         }
@@ -125,7 +125,7 @@ public class CreateNetworkOfferingTest extends TestCase{
     public void createSharedNtwkOffWithSpecifyIpRanges() {
         NetworkOfferingVO off = configMgr.createNetworkOffering("shared", "shared", TrafficType.Guest,
null, true,
                 Availability.Optional, 200, null, false, Network.GuestType.Shared, false,
-                null, false, null, true, false, null, false, null);
+                null, false, null, true, false, null, false, null, true);
         
         assertNotNull("Shared network offering with specifyIpRanges=true failed to create
", off);
     }
@@ -135,7 +135,7 @@ public class CreateNetworkOfferingTest extends TestCase{
         try {
             NetworkOfferingVO off = configMgr.createNetworkOffering("shared", "shared", TrafficType.Guest,
null, true,
                     Availability.Optional, 200, null, false, Network.GuestType.Shared, false,
-                    null, false, null, false, false, null, false, null);
+                    null, false, null, false, false, null, false, null, true);
             assertNull("Shared network offering with specifyIpRanges=false was created",
off);
         } catch (InvalidParameterValueException ex) {
         }
@@ -150,7 +150,7 @@ public class CreateNetworkOfferingTest extends TestCase{
         serviceProviderMap.put(Network.Service.SourceNat, vrProvider);
         NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest,
null, false,
                 Availability.Optional, 200, serviceProviderMap, false, Network.GuestType.Isolated,
false,
-                null, false, null, false, false, null, false, null);
+                null, false, null, false, false, null, false, null, true);
         
         assertNotNull("Isolated network offering with specifyIpRanges=false failed to create
", off);
     }
@@ -163,7 +163,7 @@ public class CreateNetworkOfferingTest extends TestCase{
         serviceProviderMap.put(Network.Service.SourceNat, vrProvider);
         NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest,
null, true,
                 Availability.Optional, 200, serviceProviderMap, false, Network.GuestType.Isolated,
false,
-                null, false, null, false, false, null, false, null);
+                null, false, null, false, false, null, false, null, true);
         assertNotNull("Isolated network offering with specifyVlan=true wasn't created", off);
        
     }
@@ -177,7 +177,7 @@ public class CreateNetworkOfferingTest extends TestCase{
             serviceProviderMap.put(Network.Service.SourceNat, vrProvider);
             NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated",
TrafficType.Guest, null, false,
                     Availability.Optional, 200, serviceProviderMap, false, Network.GuestType.Isolated,
false,
-                    null, false, null, true, false, null, false, null);
+                    null, false, null, true, false, null, false, null, true);
             assertNull("Isolated network offering with specifyIpRanges=true and source nat
service enabled, was created", off);
         } catch (InvalidParameterValueException ex) {
         }
@@ -190,7 +190,7 @@ public class CreateNetworkOfferingTest extends TestCase{
         Set<Network.Provider> vrProvider = new HashSet<Network.Provider>();
         NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest,
null, false,
                 Availability.Optional, 200, serviceProviderMap, false, Network.GuestType.Isolated,
false,
-                null, false, null, true, false, null, false, null);
+                null, false, null, true, false, null, false, null, true);
         assertNotNull("Isolated network offering with specifyIpRanges=true and with no sourceNatService,
failed to create", off);
         
     }
@@ -208,7 +208,7 @@ public class CreateNetworkOfferingTest extends TestCase{
         serviceProviderMap.put(Network.Service.Lb , vrProvider);
         NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest,
null, true,
                 Availability.Optional, 200, serviceProviderMap, false, Network.GuestType.Isolated,
false,
-                null, false, null, false, false, null, false, null);
+                null, false, null, false, false, null, false, null, true);
         // System.out.println("Creating Vpc Network Offering");
         assertNotNull("Vpc Isolated network offering with Vpc provider ", off);
     }
@@ -228,7 +228,7 @@ public class CreateNetworkOfferingTest extends TestCase{
         serviceProviderMap.put(Network.Service.Lb, lbProvider);
         NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest,
null, true,
                 Availability.Optional, 200, serviceProviderMap, false, Network.GuestType.Isolated,
false, null, false,
-                null, false, false, null, false, null);
+                null, false, false, null, false, null, true);
         // System.out.println("Creating Vpc Network Offering");
         assertNotNull("Vpc Isolated network offering with Vpc and Netscaler provider ", off);
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c0c46268/setup/db/db/schema-421to430.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-421to430.sql b/setup/db/db/schema-421to430.sql
index 8e4aa93..aaebf96 100644
--- a/setup/db/db/schema-421to430.sql
+++ b/setup/db/db/schema-421to430.sql
@@ -33,6 +33,8 @@ ALTER TABLE `cloud`.`async_job` ADD COLUMN `job_dispatcher` VARCHAR(64);
 ALTER TABLE `cloud`.`async_job` ADD COLUMN `job_executing_msid` bigint;
 ALTER TABLE `cloud`.`async_job` ADD COLUMN `job_pending_signals` int(10) NOT NULL DEFAULT
0;
 
+ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `keep_alive_enabled` int(1) unsigned NOT
NULL DEFAULT 1 COMMENT 'true if connection should be reset after requests.';
+
 ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `power_state` VARCHAR(74) DEFAULT 'PowerUnknown';
 ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `power_state_update_time` DATETIME;
 ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `power_state_update_count` INT DEFAULT 0;


Mime
View raw message