You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by hu...@apache.org on 2014/03/14 14:58:27 UTC

[30/50] [abbrv] git commit: updated refs/heads/4.4 to 48f8a95

CLOUDSTACK-6090: Virtual Router Service Failure Alerting

Signed-off-by: Koushik Das <ko...@apache.org>


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

Branch: refs/heads/4.4
Commit: f7337527cf9dbb35ec4c60621d4b37173635660c
Parents: 6a5d3e9
Author: Harikrishna Patnala <ha...@citrix.com>
Authored: Fri Mar 14 15:00:38 2014 +0530
Committer: Koushik Das <ko...@apache.org>
Committed: Fri Mar 14 15:14:15 2014 +0530

----------------------------------------------------------------------
 .../cloud/agent/api/GetRouterAlertsAnswer.java  |  62 +++++
 .../api/routing/GetRouterAlertsCommand.java     |  46 ++++
 .../virtualnetwork/VirtualRoutingResource.java  |  45 +++-
 .../spring-engine-schema-core-daos-context.xml  |   1 +
 .../network/dao/OpRouterMonitorServiceDao.java  |  25 ++
 .../dao/OpRouterMonitorServiceDaoImpl.java      |  28 +++
 .../network/dao/OpRouterMonitorServiceVO.java   |  52 ++++
 .../VirtualNetworkApplianceManagerImpl.java     |  67 +++++
 setup/db/db/schema-430to440.sql                 |   8 +
 .../config/opt/cloud/bin/getRouterAlerts.sh     |  70 ++++++
 .../debian/config/root/monitorServices.py       |   3 +
 .../smoke/test_VirtualRouter_alerts.py          | 244 +++++++++++++++++++
 12 files changed, 650 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f7337527/core/src/com/cloud/agent/api/GetRouterAlertsAnswer.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/GetRouterAlertsAnswer.java b/core/src/com/cloud/agent/api/GetRouterAlertsAnswer.java
new file mode 100644
index 0000000..06a7a7a
--- /dev/null
+++ b/core/src/com/cloud/agent/api/GetRouterAlertsAnswer.java
@@ -0,0 +1,62 @@
+// 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.agent.api;
+
+
+import com.cloud.agent.api.routing.GetRouterAlertsCommand;
+
+public class GetRouterAlertsAnswer extends Answer {
+
+    String routerName;
+    String[] alerts;
+    String timeStamp;
+
+    protected GetRouterAlertsAnswer() {
+    }
+
+    public GetRouterAlertsAnswer(GetRouterAlertsCommand cmd, String alerts[], String timeStamp) {
+        super(cmd, true, null);
+        this.alerts = alerts;
+        this.timeStamp = timeStamp;
+    }
+
+
+    public GetRouterAlertsAnswer(GetRouterAlertsCommand cmd, Exception ex) {
+        super(cmd, ex);
+    }
+
+    public void setAlerts(String[] alerts) {
+        this.alerts = alerts;
+    }
+
+    public String[] getAlerts() {
+        return alerts;
+    }
+
+    public void setTimeStamp(String timeStamp) {
+        this.timeStamp = timeStamp;
+    }
+
+    public String getTimeStamp() {
+        return timeStamp;
+    }
+
+    public String getRouterName() {
+        return routerName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f7337527/core/src/com/cloud/agent/api/routing/GetRouterAlertsCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/routing/GetRouterAlertsCommand.java b/core/src/com/cloud/agent/api/routing/GetRouterAlertsCommand.java
new file mode 100644
index 0000000..a6769ef
--- /dev/null
+++ b/core/src/com/cloud/agent/api/routing/GetRouterAlertsCommand.java
@@ -0,0 +1,46 @@
+// 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.agent.api.routing;
+
+
+public class GetRouterAlertsCommand  extends NetworkElementCommand {
+
+    private String previousAlertTimeStamp;
+
+    protected GetRouterAlertsCommand() {
+
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        return false;
+    }
+
+    public GetRouterAlertsCommand(String timeStamp) {
+        this.previousAlertTimeStamp = timeStamp;
+    }
+
+    public String getPreviousAlertTimeStamp() {
+        return previousAlertTimeStamp;
+    }
+
+    @Override
+    public boolean isQuery() {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f7337527/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
index 3712aba..e13fbf6 100755
--- a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
+++ b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
@@ -32,6 +32,8 @@ import com.cloud.agent.api.routing.DeleteIpAliasCommand;
 import com.cloud.agent.api.routing.DhcpEntryCommand;
 import com.cloud.agent.api.routing.DnsMasqConfigCommand;
 import com.cloud.agent.api.routing.GroupAnswer;
+import com.cloud.agent.api.routing.GetRouterAlertsCommand;
+import com.cloud.agent.api.GetRouterAlertsAnswer;
 import com.cloud.agent.api.routing.IpAliasTO;
 import com.cloud.agent.api.routing.IpAssocCommand;
 import com.cloud.agent.api.routing.IpAssocVpcCommand;
@@ -102,6 +104,7 @@ public class VirtualRoutingResource {
         protected static final String IPASSOC = "ipassoc.sh";
         protected static final String LB = "loadbalancer.sh";
         protected static final String MONITOR_SERVICE = "monitor_service.sh";
+        protected static final String ROUTER_ALERTS = "getRouterAlerts.sh";
         protected static final String PASSWORD = "savepassword.sh";
         protected static final String RVR_CHECK = "checkrouter.sh";
         protected static final String RVR_BUMPUP_PRI = "bumpup_priority.sh";
@@ -275,7 +278,9 @@ public class VirtualRoutingResource {
         } else if (cmd instanceof GetDomRVersionCmd) {
             return execute((GetDomRVersionCmd)cmd);
         } else if (cmd instanceof CheckS2SVpnConnectionsCommand) {
-            return execute((CheckS2SVpnConnectionsCommand)cmd);
+            return execute((CheckS2SVpnConnectionsCommand) cmd);
+        } else if (cmd instanceof GetRouterAlertsCommand) {
+            return execute((GetRouterAlertsCommand)cmd);
         } else {
             s_logger.error("Unknown query command in VirtualRoutingResource!");
             return Answer.createUnsupportedCommandAnswer(cmd);
@@ -642,6 +647,29 @@ public class VirtualRoutingResource {
         return new CheckS2SVpnConnectionsAnswer(cmd, result.isSuccess(), result.getDetails());
     }
 
+    private GetRouterAlertsAnswer execute(GetRouterAlertsCommand cmd) {
+
+        String args = null;
+        String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
+        if (cmd.getPreviousAlertTimeStamp() != null) {
+            args = cmd.getPreviousAlertTimeStamp();
+        }
+
+        ExecutionResult result = _vrDeployer.executeInVR(routerIp, VRScripts.ROUTER_ALERTS, args);
+        String alerts[] = null;
+        String lastAlertTimestamp = null;
+        // CallHostPlugin results "success" when there are no alerts on virtual router
+        if (result.isSuccess()) {
+            if (!result.getDetails().isEmpty() && !result.getDetails().equals("No Alerts")) {
+                alerts = result.getDetails().split("\\\\n");
+                String[] lastAlert = alerts[alerts.length - 1].split(" ");
+                lastAlertTimestamp = lastAlert[0] + " " + lastAlert[1];
+            }
+        }
+
+        return new GetRouterAlertsAnswer(cmd, alerts, lastAlertTimestamp);
+    }
+
     protected Answer execute(CheckRouterCommand cmd) {
         final ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.RVR_CHECK, null);
         if (!result.isSuccess()) {
@@ -732,6 +760,21 @@ public class VirtualRoutingResource {
         return cfg;
     }
 
+    protected List<ConfigItem> generateConfig(GetRouterAlertsCommand cmd) {
+        LinkedList<ConfigItem> cfg = new LinkedList<>();
+
+        String args = null;
+        String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
+        if (cmd.getPreviousAlertTimeStamp() != null) {
+            args = "getRouterAlerts.sh " + routerIp + " " + cmd.getPreviousAlertTimeStamp();
+        } else {
+            args = "getRouterAlerts.sh " + routerIp;
+        }
+
+        cfg.add(new ConfigItem(VRScripts.ROUTER_ALERTS, args));
+        return cfg;
+    }
+
     protected List<ConfigItem> generateConfig(SetupGuestNetworkCommand cmd) {
         LinkedList<ConfigItem> cfg = new LinkedList<>();
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f7337527/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
----------------------------------------------------------------------
diff --git a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
index 765d86c..489b37d 100644
--- a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
+++ b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
@@ -157,6 +157,7 @@
   <bean id="firewallRulesCidrsDaoImpl" class="com.cloud.network.dao.FirewallRulesCidrsDaoImpl" />
   <bean id="firewallRulesDaoImpl" class="com.cloud.network.dao.FirewallRulesDaoImpl" />
   <bean id="MonitoringServiceDaoImpl" class="com.cloud.network.dao.MonitoringServiceDaoImpl" />
+  <bean id="OpRouterMonitorServiceDaoImpl" class="com.cloud.network.dao.OpRouterMonitorServiceDaoImpl" />
   <bean id="globalLoadBalancerDaoImpl" class="org.apache.cloudstack.region.gslb.GlobalLoadBalancerDaoImpl" />
   <bean id="globalLoadBalancerLbRuleMapDaoImpl" class="org.apache.cloudstack.region.gslb.GlobalLoadBalancerLbRuleMapDaoImpl" />
   <bean id="guestOSCategoryDaoImpl" class="com.cloud.storage.dao.GuestOSCategoryDaoImpl" />

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f7337527/engine/schema/src/com/cloud/network/dao/OpRouterMonitorServiceDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/network/dao/OpRouterMonitorServiceDao.java b/engine/schema/src/com/cloud/network/dao/OpRouterMonitorServiceDao.java
new file mode 100644
index 0000000..ebc0f1a
--- /dev/null
+++ b/engine/schema/src/com/cloud/network/dao/OpRouterMonitorServiceDao.java
@@ -0,0 +1,25 @@
+// 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.dao;
+
+
+import com.cloud.utils.db.GenericDao;
+
+public interface OpRouterMonitorServiceDao extends GenericDao<OpRouterMonitorServiceVO, Long> {
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f7337527/engine/schema/src/com/cloud/network/dao/OpRouterMonitorServiceDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/network/dao/OpRouterMonitorServiceDaoImpl.java b/engine/schema/src/com/cloud/network/dao/OpRouterMonitorServiceDaoImpl.java
new file mode 100644
index 0000000..b92512e
--- /dev/null
+++ b/engine/schema/src/com/cloud/network/dao/OpRouterMonitorServiceDaoImpl.java
@@ -0,0 +1,28 @@
+// 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.dao;
+
+import com.cloud.utils.db.GenericDaoBase;
+import org.springframework.stereotype.Component;
+
+import javax.ejb.Local;
+
+@Component
+@Local(value=OpRouterMonitorServiceDao.class)
+public class OpRouterMonitorServiceDaoImpl extends GenericDaoBase<OpRouterMonitorServiceVO, Long> implements OpRouterMonitorServiceDao  {
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f7337527/engine/schema/src/com/cloud/network/dao/OpRouterMonitorServiceVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/network/dao/OpRouterMonitorServiceVO.java b/engine/schema/src/com/cloud/network/dao/OpRouterMonitorServiceVO.java
new file mode 100644
index 0000000..c70bba3
--- /dev/null
+++ b/engine/schema/src/com/cloud/network/dao/OpRouterMonitorServiceVO.java
@@ -0,0 +1,52 @@
+package com.cloud.network.dao;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import javax.persistence.Id;
+import javax.persistence.Column;
+
+
+@Entity
+@Table(name = "op_router_monitoring_services")
+public class OpRouterMonitorServiceVO implements InternalIdentity {
+
+    @Id
+    @Column(name="vm_id")
+    Long id;
+
+    @Column(name="router_name")
+    private String name;
+
+    @Column(name="last_alert_timestamp")
+    private String lastAlertTimestamp;
+
+
+    public OpRouterMonitorServiceVO() {}
+
+    public OpRouterMonitorServiceVO(long vmId, String name, String lastAlertTimestamp) {
+        this.id = vmId;
+        this.name = name;
+        this.lastAlertTimestamp = lastAlertTimestamp;
+    }
+
+
+    @Override
+    public long getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getLastAlertTimestamp() {
+        return lastAlertTimestamp;
+    }
+
+    public void setLastAlertTimestamp (String timestamp) {
+        this.lastAlertTimestamp = timestamp;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f7337527/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 eeab91d..c692491 100755
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -55,6 +55,7 @@ import org.apache.cloudstack.framework.jobs.AsyncJobManager;
 import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
 import org.apache.cloudstack.managed.context.ManagedContextRunnable;
 import org.apache.cloudstack.utils.identity.ManagementServerNode;
+import org.apache.cloudstack.alert.AlertService.AlertType;
 import com.cloud.agent.AgentManager;
 import com.cloud.agent.Listener;
 import com.cloud.agent.api.AgentControlAnswer;
@@ -73,6 +74,8 @@ import com.cloud.agent.api.NetworkUsageAnswer;
 import com.cloud.agent.api.NetworkUsageCommand;
 import com.cloud.agent.api.PvlanSetupCommand;
 import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.routing.GetRouterAlertsCommand;
+import com.cloud.agent.api.GetRouterAlertsAnswer;
 import com.cloud.agent.api.check.CheckSshAnswer;
 import com.cloud.agent.api.check.CheckSshCommand;
 import com.cloud.agent.api.routing.AggregationControlCommand;
@@ -179,6 +182,7 @@ import com.cloud.network.dao.MonitoringServiceDao;
 import com.cloud.network.dao.MonitoringServiceVO;
 import com.cloud.network.dao.NetworkDao;
 import com.cloud.network.dao.NetworkVO;
+import com.cloud.network.dao.OpRouterMonitorServiceDao;
 import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
 import com.cloud.network.dao.RemoteAccessVpnDao;
 import com.cloud.network.dao.Site2SiteCustomerGatewayDao;
@@ -188,6 +192,7 @@ import com.cloud.network.dao.Site2SiteVpnGatewayDao;
 import com.cloud.network.dao.UserIpv6AddressDao;
 import com.cloud.network.dao.VirtualRouterProviderDao;
 import com.cloud.network.dao.VpnUserDao;
+import com.cloud.network.dao.OpRouterMonitorServiceVO;
 import com.cloud.network.lb.LoadBalancingRule;
 import com.cloud.network.lb.LoadBalancingRule.LbDestination;
 import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy;
@@ -394,6 +399,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     AsyncJobManager _asyncMgr;
     @Inject
     protected ApiAsyncJobDispatcher _asyncDispatcher;
+    @Inject
+    OpRouterMonitorServiceDao _opRouterMonitorServiceDao;
 
     int _routerRamSize;
     int _routerCpuMHz;
@@ -1348,6 +1355,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
                 updateSite2SiteVpnConnectionState(routers);
 
+                getRouterAlerts();
+
                 final List<NetworkVO> networks = _networkDao.listRedundantNetworks();
                 s_logger.debug("Found " + networks.size() + " networks to update RvR status. ");
                 for (final NetworkVO network : networks) {
@@ -1362,6 +1371,64 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         }
     }
 
+    private void getRouterAlerts() {
+        try{
+            List<DomainRouterVO> routersInIsolatedNetwork = _routerDao.listByStateAndNetworkType(State.Running, GuestType.Isolated, mgmtSrvrId);
+            List<DomainRouterVO> routersInSharedNetwork = _routerDao.listByStateAndNetworkType(State.Running, GuestType.Shared, mgmtSrvrId);
+
+            List<DomainRouterVO> routers = new ArrayList<DomainRouterVO>();
+            routers.addAll(routersInIsolatedNetwork);
+            routers.addAll(routersInSharedNetwork);
+            s_logger.debug("Found " + routers.size() + " running routers. ");
+
+            for (final DomainRouterVO router : routers) {
+                if (router.getVpcId() != null) {
+                    continue;
+                }
+                String privateIP = router.getPrivateIpAddress();
+
+                if (privateIP != null) {
+                    OpRouterMonitorServiceVO opRouterMonitorServiceVO = _opRouterMonitorServiceDao.findById(router.getId());
+
+                    GetRouterAlertsCommand command = null;
+                    if (opRouterMonitorServiceVO == null) {
+                        command = new GetRouterAlertsCommand(null);
+                    } else {
+                        command = new GetRouterAlertsCommand(opRouterMonitorServiceVO.getLastAlertTimestamp());
+                    }
+
+                    command.setAccessDetail(NetworkElementCommand.ROUTER_IP, router.getPrivateIpAddress());
+                    command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName());
+
+                    GetRouterAlertsAnswer answer = null;
+                    try {
+                        answer = (GetRouterAlertsAnswer) _agentMgr.easySend(router.getHostId(), command);
+                        String alerts[] = answer.getAlerts();
+                        if (alerts != null ) {
+                            for (String alert: alerts) {
+                                _alertMgr.sendAlert(AlertType.ALERT_TYPE_DOMAIN_ROUTER, router.getDataCenterId(), router.getPodIdToDeployIn(), "Monitoring Service on VR " + router.getInstanceName(), alert);
+                            }
+                            String lastAlertTimeStamp = answer.getTimeStamp();
+                            if (opRouterMonitorServiceVO == null) {
+                                opRouterMonitorServiceVO = new OpRouterMonitorServiceVO(router.getId(), router.getHostName(), lastAlertTimeStamp);
+                                _opRouterMonitorServiceDao.persist(opRouterMonitorServiceVO);
+                            } else {
+                                opRouterMonitorServiceVO.setLastAlertTimestamp(lastAlertTimeStamp);
+                                _opRouterMonitorServiceDao.update(opRouterMonitorServiceVO.getId(), opRouterMonitorServiceVO);
+                            }
+                        }
+                    } catch (Exception e) {
+                        s_logger.warn("Error while collecting alerts from router: " + router.getInstanceName() + " from host: " + router.getHostId(), e);
+                        continue;
+                    }
+                }
+            }
+        } catch (Exception e) {
+            s_logger.warn("Error while collecting alerts from router", e);
+        }
+    }
+
+
     private final static int DEFAULT_PRIORITY = 100;
     private final static int DEFAULT_DELTA = 2;
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f7337527/setup/db/db/schema-430to440.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-430to440.sql b/setup/db/db/schema-430to440.sql
index 056c5f8..9d41fe9 100644
--- a/setup/db/db/schema-430to440.sql
+++ b/setup/db/db/schema-430to440.sql
@@ -657,6 +657,14 @@ ALTER TABLE `cloud`.`s2s_vpn_gateway` ADD COLUMN `display` tinyint(1) NOT NULL D
 INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (225, UUID(), 9, 'FreeBSD 10 (32-bit)');
 INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (226, UUID(), 9, 'FreeBSD 10 (64-bit)');
 
+CREATE TABLE `cloud`.`op_router_monitoring_services` (
+  `vm_id` bigint unsigned UNIQUE NOT NULL COMMENT 'Primary Key',
+  `router_name` varchar(255) NOT NULL COMMENT 'Name of the Virtual Router',
+  `last_alert_timestamp` varchar(255) NOT NULL COMMENT 'Timestamp of the last alert received from Virtual Router',
+   PRIMARY KEY (`vm_id`),
+   CONSTRAINT `fk_virtual_router__id` FOREIGN KEY `fk_virtual_router__id` (`vm_id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE
+) ENGINE = InnoDB DEFAULT CHARSET=utf8
+
 ALTER TABLE `cloud`.`event` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'True if the detail can be displayed to the end user';
 
 DROP VIEW IF EXISTS `cloud`.`event_view`;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f7337527/systemvm/patches/debian/config/opt/cloud/bin/getRouterAlerts.sh
----------------------------------------------------------------------
diff --git a/systemvm/patches/debian/config/opt/cloud/bin/getRouterAlerts.sh b/systemvm/patches/debian/config/opt/cloud/bin/getRouterAlerts.sh
new file mode 100644
index 0000000..e5e8abe
--- /dev/null
+++ b/systemvm/patches/debian/config/opt/cloud/bin/getRouterAlerts.sh
@@ -0,0 +1,70 @@
+#!/usr/bin/env bash
+# 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.
+
+# getRouterAlerts.sh  --- Send the alerts from routerServiceMonitor.log to Management Server
+
+source /root/func.sh
+
+lock="biglock"
+locked=$(getLockFile $lock)
+if [ "$locked" != "1" ]
+then
+    exit 1
+fi
+
+#set -x
+
+filename=/var/log/routerServiceMonitor.log #Monitor service log file
+if [ -n "$1" -a -n "$2" ]
+then
+        reqdateval=$(date -d $1 +"%Y%m%d");
+        reqtimeval=$(date -d $2 +"%H%M%S");
+else
+        reqdateval=0
+        reqtimeval=0
+fi
+if [ -f $filename ]
+then
+        while read line
+        do
+        if [ -n "$line" ]; then
+            dateval=`echo $line |awk '{print $1}'`
+            timeval=`echo $line |awk '{print $2}'`
+
+            todate=$(date -d "$dateval" +"%Y%m%d") > /dev/null
+            totime=$(date -d "$timeval" +"%H%M%S") > /dev/null
+            if [ "$todate" -gt "$reqdateval" ] > /dev/null
+            then
+                if [ -n "$alerts" ]; then  alerts="$alerts\n$line"; else alerts="$line"; fi #>> $outputfile
+                elif [ "$todate" -eq "$reqdateval" ] > /dev/null
+                then
+                    if [ "$totime" -gt "$reqtimeval" ] > /dev/null
+                    then
+                        if [ -n "$alerts" ]; then  alerts="$alerts\n$line"; else alerts="$line"; fi #>> $outputfile
+                    fi
+                fi
+            fi
+        done < $filename
+fi
+if [ -n "$alerts" ]; then
+       echo $alerts
+else
+       echo "No Alerts"
+fi
+
+unlock_exit 0 $lock $locked
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f7337527/systemvm/patches/debian/config/root/monitorServices.py
----------------------------------------------------------------------
diff --git a/systemvm/patches/debian/config/root/monitorServices.py b/systemvm/patches/debian/config/root/monitorServices.py
index 0319ece..c1dfba2 100755
--- a/systemvm/patches/debian/config/root/monitorServices.py
+++ b/systemvm/patches/debian/config/root/monitorServices.py
@@ -25,6 +25,7 @@ from subprocess import *
 from os import path
 import time
 import os
+import logging
 
 class StatusCodes:
     SUCCESS      = 0
@@ -92,6 +93,8 @@ def raisealert(severity, msg, process_name=None):
     else:
         log = '['+severity+']' + " " + msg +"\n"
 
+    logging.basicConfig(level=logging.INFO,filename='/var/log/routerServiceMonitor.log',format='%(asctime)s %(message)s')
+    logging.info(log)
     msg = 'logger -t monit '+ log
     pout = Popen(msg, shell=True, stdout=PIPE)
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f7337527/test/integration/smoke/test_VirtualRouter_alerts.py
----------------------------------------------------------------------
diff --git a/test/integration/smoke/test_VirtualRouter_alerts.py b/test/integration/smoke/test_VirtualRouter_alerts.py
new file mode 100644
index 0000000..2333d84
--- /dev/null
+++ b/test/integration/smoke/test_VirtualRouter_alerts.py
@@ -0,0 +1,244 @@
+# 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.
+""" P1 tests for alert receiving from VR on service failure in VR
+"""
+#Import Local Modules
+import marvin
+from marvin.cloudstackTestCase import *
+from marvin.cloudstackAPI import *
+from marvin.integration.lib.utils import *
+from marvin.integration.lib.base import *
+from marvin.integration.lib.common import *
+from nose.plugins.attrib import attr
+import time
+
+
+_multiprocess_shared_ = True
+
+class Services:
+    """Test VM Life Cycle Services
+    """
+
+    def __init__(self):
+        self.services = {
+
+            "account": {
+                "email": "test@test.com",
+                "firstname": "Test",
+                "lastname": "User",
+                "username": "test",
+                # Random characters are appended in create account to
+                # ensure unique username generated each time
+                "password": "password",
+                },
+            "small":
+            # Create a small virtual machine instance with disk offering
+                {
+                    "displayname": "testserver",
+                    "username": "root", # VM creds for SSH
+                    "password": "password",
+                    "ssh_port": 22,
+                    "hypervisor": 'XenServer',
+                    "privateport": 22,
+                    "publicport": 22,
+                    "protocol": 'TCP',
+                    },
+            "service_offerings":
+                {
+                    "small":
+                        {
+                            # Small service offering ID to for change VM
+                            # service offering from medium to small
+                            "name": "SmallInstance",
+                            "displaytext": "SmallInstance",
+                            "cpunumber": 1,
+                            "cpuspeed": 100,
+                            "memory": 256,
+                            },
+                    "big":
+                        {
+                            # Big service offering ID to for change VM
+                            "name": "BigInstance",
+                            "displaytext": "BigInstance",
+                            "cpunumber": 1,
+                            "cpuspeed": 100,
+                            "memory": 512,
+                            }
+                },
+            #Change this
+            "template": {
+                "displaytext": "xs",
+                "name": "xs",
+                "passwordenabled": False,
+                },
+            "sleep": 60,
+            "timeout": 10,
+            #Migrate VM to hostid
+            "ostype": 'CentOS 5.3 (64-bit)',
+            # CentOS 5.3 (64-bit)
+        }
+
+
+class TestVRServiceFailureAlerting(cloudstackTestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls.api_client = super(TestVRServiceFailureAlerting, cls).getClsTestClient().getApiClient()
+        cls.services = Services().services
+
+        # Get Zone, Domain and templates
+        domain = get_domain(cls.api_client, cls.services)
+        cls.zone = get_zone(cls.api_client, cls.services)
+        cls.services['mode'] = cls.zone.networktype
+
+        template = get_template(
+            cls.api_client,
+            cls.zone.id,
+            cls.services["ostype"]
+        )
+        # Set Zones and disk offerings ??
+        cls.services["small"]["zoneid"] = cls.zone.id
+        cls.services["small"]["template"] = template.id
+
+        # Create account, service offerings, vm.
+        cls.account = Account.create(
+            cls.api_client,
+            cls.services["account"],
+            domainid=domain.id
+        )
+
+        cls.small_offering = ServiceOffering.create(
+            cls.api_client,
+            cls.services["service_offerings"]["small"]
+        )
+
+        #create a virtual machine
+        cls.virtual_machine = VirtualMachine.create(
+            cls.api_client,
+            cls.services["small"],
+            accountid=cls.account.name,
+            domainid=cls.account.domainid,
+            serviceofferingid=cls.small_offering.id,
+            mode=cls.services["mode"]
+        )
+        cls._cleanup = [
+            cls.small_offering,
+            cls.account
+        ]
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.api_client = super(TestVRServiceFailureAlerting, cls).getClsTestClient().getApiClient()
+        cleanup_resources(cls.api_client, cls._cleanup)
+        return
+
+    def setUp(self):
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+        self.cleanup = []
+
+    def tearDown(self):
+        #Clean up, terminate the created ISOs
+        cleanup_resources(self.apiclient, self.cleanup)
+        return
+
+    @attr(hypervisor="xenserver")
+    @attr(tags=["advanced", "basic"])
+    def test_01_VRServiceFailureAlerting(self):
+
+
+        if self.zone.networktype == "Basic":
+            list_router_response = list_routers(
+                self.apiclient,
+                listall="true"
+            )
+        else:
+            list_router_response = list_routers(
+                self.apiclient,
+                account=self.account.name,
+                domainid=self.account.domainid
+            )
+        self.assertEqual(
+            isinstance(list_router_response, list),
+            True,
+            "Check list response returns a valid list"
+        )
+        router = list_router_response[0]
+
+        hosts = list_hosts(
+            self.apiclient,
+            zoneid=router.zoneid,
+            type='Routing',
+            state='Up',
+            id=router.hostid
+        )
+        self.assertEqual(
+            isinstance(hosts, list),
+            True,
+            "Check list host returns a valid list"
+        )
+        host = hosts[0]
+
+        self.debug("Router ID: %s, state: %s" % (router.id, router.state))
+
+        self.assertEqual(
+        router.state,
+        'Running',
+        "Check list router response for router state"
+        )
+
+        alertSubject = "Monitoring Service on VR " + router.name
+
+        if self.apiclient.hypervisor.lower() == 'vmware':
+            result = get_process_status(
+                        self.apiclient.connection.mgtSvr,
+                        22,
+                        self.apiclient.connection.user,
+                        self.apiclient.connection.passwd,
+                        router.linklocalip,
+                        "service dnsmasq status",
+                        hypervisor=self.apiclient.hypervisor
+                        )
+        else:
+            try:
+                host.user, host.passwd = get_host_credentials(self.config, host.ipaddress)
+                result = get_process_status(
+                            host.ipaddress,
+                            22,
+                            host.user,
+                            host.passwd,
+                            router.linklocalip,
+                            "service apache2 stop"
+                            )
+            except KeyError:
+                self.skipTest("Marvin configuration has no host credentials to check router services")
+
+        res = str(result)
+        self.debug("apache process status: %s" % res)
+
+        time.sleep(300) #wait for 5 minutes meanwhile monitor service on VR starts the apache service
+
+        qresultset = self.dbclient.execute(
+            "select id from alert where subject = '%s' ORDER BY id DESC LIMIT 1;" \
+            % str(alertSubject)
+        )
+        self.assertNotEqual(
+            len(qresultset),
+            0,
+            "Check DB Query result set"
+        )
+
+        return