incubator-cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From muralire...@apache.org
Subject [37/50] [abbrv] git commit: refs/heads/gslb-wip - CLOUDSTACK-874 Ability to delete Events and Alerts
Date Mon, 18 Mar 2013 10:14:48 GMT
CLOUDSTACK-874 Ability to delete Events and Alerts

Signed-off-by: Min Chen <min.chen@citrix.com>


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

Branch: refs/heads/gslb-wip
Commit: 5e4c2c8a9eb339fb467aea15582a79cd2feef4bf
Parents: ae3eeca
Author: Sanjay Tripathi <sanjay.tripathi@citrix.com>
Authored: Fri Mar 8 10:52:40 2013 -0800
Committer: Min Chen <min.chen@citrix.com>
Committed: Fri Mar 8 10:52:40 2013 -0800

----------------------------------------------------------------------
 api/src/com/cloud/alert/Alert.java                 |    1 +
 api/src/com/cloud/event/Event.java                 |    1 +
 api/src/com/cloud/server/ManagementService.java    |   38 +++-
 .../org/apache/cloudstack/api/ApiConstants.java    |    1 +
 client/tomcatconf/commands.properties.in           |    4 +
 core/src/com/cloud/alert/AlertVO.java              |   38 ++--
 core/src/com/cloud/event/EventVO.java              |  167 ++++++++-------
 core/src/com/cloud/event/dao/EventDao.java         |    5 +
 core/src/com/cloud/event/dao/EventDaoImpl.java     |   71 +++++--
 server/src/com/cloud/alert/dao/AlertDao.java       |    7 +
 server/src/com/cloud/alert/dao/AlertDaoImpl.java   |   85 ++++++++
 server/src/com/cloud/api/ApiDispatcher.java        |    6 +-
 .../src/com/cloud/api/query/QueryManagerImpl.java  |    3 +
 server/src/com/cloud/api/query/vo/EventJoinVO.java |    9 +
 server/src/com/cloud/configuration/Config.java     |    5 +-
 .../src/com/cloud/server/ManagementServerImpl.java |  109 +++++++++-
 setup/db/db/schema-410to420.sql                    |   45 ++++
 17 files changed, 475 insertions(+), 120 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/api/src/com/cloud/alert/Alert.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/alert/Alert.java b/api/src/com/cloud/alert/Alert.java
index 050f97f..31768cf 100644
--- a/api/src/com/cloud/alert/Alert.java
+++ b/api/src/com/cloud/alert/Alert.java
@@ -30,4 +30,5 @@ public interface Alert extends Identity, InternalIdentity {
     Date getCreatedDate();
     Date getLastSent();
     Date getResolved();
+    boolean getArchived();
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/api/src/com/cloud/event/Event.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/event/Event.java b/api/src/com/cloud/event/Event.java
index 1a61636..b8def4c 100644
--- a/api/src/com/cloud/event/Event.java
+++ b/api/src/com/cloud/event/Event.java
@@ -40,4 +40,5 @@ public interface Event extends ControlledEntity, Identity, InternalIdentity
{
     String getLevel();
     long getStartId();
     String getParameters();
+    boolean getArchived();
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/api/src/com/cloud/server/ManagementService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/server/ManagementService.java b/api/src/com/cloud/server/ManagementService.java
index 1736da3..1e6ca8d 100755
--- a/api/src/com/cloud/server/ManagementService.java
+++ b/api/src/com/cloud/server/ManagementService.java
@@ -29,6 +29,8 @@ import org.apache.cloudstack.api.command.admin.domain.UpdateDomainCmd;
 import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
 import org.apache.cloudstack.api.command.admin.host.UpdateHostPasswordCmd;
 import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd;
+import org.apache.cloudstack.api.command.admin.resource.ArchiveAlertsCmd;
+import org.apache.cloudstack.api.command.admin.resource.DeleteAlertsCmd;
 import org.apache.cloudstack.api.command.admin.resource.ListAlertsCmd;
 import org.apache.cloudstack.api.command.admin.resource.ListCapacityCmd;
 import org.apache.cloudstack.api.command.admin.resource.UploadCustomCertificateCmd;
@@ -40,12 +42,12 @@ import org.apache.cloudstack.api.command.admin.systemvm.UpgradeSystemVMCmd;
 import org.apache.cloudstack.api.command.admin.vlan.ListVlanIpRangesCmd;
 import org.apache.cloudstack.api.command.user.address.ListPublicIpAddressesCmd;
 import org.apache.cloudstack.api.command.user.config.ListCapabilitiesCmd;
+import org.apache.cloudstack.api.command.user.event.ArchiveEventsCmd;
+import org.apache.cloudstack.api.command.user.event.DeleteEventsCmd;
 import org.apache.cloudstack.api.command.user.guest.ListGuestOsCategoriesCmd;
 import org.apache.cloudstack.api.command.user.guest.ListGuestOsCmd;
 import org.apache.cloudstack.api.command.user.iso.ListIsosCmd;
 import org.apache.cloudstack.api.command.user.iso.UpdateIsoCmd;
-import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd;
-import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd;
 import org.apache.cloudstack.api.command.user.ssh.CreateSSHKeyPairCmd;
 import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd;
 import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd;
@@ -55,12 +57,10 @@ import org.apache.cloudstack.api.command.user.template.UpdateTemplateCmd;
 import org.apache.cloudstack.api.command.user.vm.GetVMPasswordCmd;
 import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd;
 import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd;
-import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd;
 
 import com.cloud.alert.Alert;
 import com.cloud.capacity.Capacity;
 import com.cloud.configuration.Configuration;
-import com.cloud.dc.DataCenter;
 import com.cloud.dc.Pod;
 import com.cloud.dc.Vlan;
 import com.cloud.domain.Domain;
@@ -72,8 +72,6 @@ import com.cloud.host.Host;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.hypervisor.HypervisorCapabilities;
 import com.cloud.network.IpAddress;
-import com.cloud.offering.DiskOffering;
-import com.cloud.offering.ServiceOffering;
 import com.cloud.org.Cluster;
 import com.cloud.storage.GuestOS;
 import com.cloud.storage.GuestOsCategory;
@@ -195,6 +193,34 @@ public interface ManagementService {
     Pair<List<? extends Alert>, Integer> searchForAlerts(ListAlertsCmd cmd);
 
     /**
+     * Archive alerts
+     * @param cmd
+     * @return True on success. False otherwise.
+     */
+    boolean archiveAlerts(ArchiveAlertsCmd cmd);
+
+    /**
+     * Delete alerts
+     * @param cmd
+     * @return True on success. False otherwise.
+     */
+    boolean deleteAlerts(DeleteAlertsCmd cmd);
+
+    /**
+     * Archive events
+     * @param cmd
+     * @return True on success. False otherwise.
+     */
+    boolean archiveEvents(ArchiveEventsCmd cmd);
+
+    /**
+     * Delete events
+     * @param cmd
+     * @return True on success. False otherwise.
+     */
+    boolean deleteEvents(DeleteEventsCmd cmd);
+
+    /**
      * list all the capacity rows in capacity operations table
      *
      * @param cmd

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/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 1b544fd..b40b26c 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -459,6 +459,7 @@ public class ApiConstants {
     public static final String UCS_BLADE_DN = "bladedn";
     public static final String UCS_BLADE_ID = "bladeid";
     public static final String VM_GUEST_IP = "vmguestip";
+    public static final String OLDER_THAN = "olderthan";
 
     public enum HostDetails {
         all, capacity, events, stats, min;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index dd0c3f8..5018236 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -218,9 +218,13 @@ listZones=15
 #### events commands
 listEvents=15
 listEventTypes=15
+archiveEvents=15
+deleteEvents=15
 
 #### alerts commands
 listAlerts=3
+archiveAlerts=1
+deleteAlerts=1
 
 #### system capacity commands
 listCapacity=3

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/core/src/com/cloud/alert/AlertVO.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/alert/AlertVO.java b/core/src/com/cloud/alert/AlertVO.java
index f6089d6..3f014aa 100755
--- a/core/src/com/cloud/alert/AlertVO.java
+++ b/core/src/com/cloud/alert/AlertVO.java
@@ -28,9 +28,7 @@ import javax.persistence.Table;
 import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
 
-import org.apache.cloudstack.api.Identity;
 import com.cloud.utils.db.GenericDao;
-import org.apache.cloudstack.api.InternalIdentity;
 
 @Entity
 @Table(name="alert")
@@ -68,16 +66,19 @@ public class AlertVO implements Alert {
     @Temporal(TemporalType.TIMESTAMP)
     @Column(name="resolved", updatable=true, nullable=true)
     private Date resolved;
-    
+
     @Column(name="uuid")
     private String uuid;
 
+    @Column(name="archived")
+    private boolean archived;
+
     public AlertVO() {
-    	this.uuid = UUID.randomUUID().toString();
+        this.uuid = UUID.randomUUID().toString();
     }
     public AlertVO(Long id) {
         this.id = id;
-    	this.uuid = UUID.randomUUID().toString();
+        this.uuid = UUID.randomUUID().toString();
     }
 
     @Override
@@ -103,12 +104,12 @@ public class AlertVO implements Alert {
     }
 
     public Long getClusterId() {
-		return clusterId;
-	}
-	public void setClusterId(Long clusterId) {
-		this.clusterId = clusterId;
-	}
-	@Override
+        return clusterId;
+    }
+    public void setClusterId(Long clusterId) {
+        this.clusterId = clusterId;
+    }
+    @Override
     public Long getPodId() {
         return podId;
     }
@@ -164,10 +165,19 @@ public class AlertVO implements Alert {
     
     @Override
     public String getUuid() {
-    	return this.uuid;
+        return this.uuid;
     }
-    
+
     public void setUuid(String uuid) {
-    	this.uuid = uuid;
+        this.uuid = uuid;
+    }
+
+    @Override
+    public boolean getArchived() {
+        return archived;
+    }
+
+    public void setArchived(Boolean archived) {
+        this.archived = archived;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/core/src/com/cloud/event/EventVO.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/event/EventVO.java b/core/src/com/cloud/event/EventVO.java
index ac46f24..2c30ead 100644
--- a/core/src/com/cloud/event/EventVO.java
+++ b/core/src/com/cloud/event/EventVO.java
@@ -29,74 +29,75 @@ import javax.persistence.Id;
 import javax.persistence.Table;
 import javax.persistence.Transient;
 
-import org.apache.cloudstack.api.Identity;
 import com.cloud.utils.db.GenericDao;
-import org.apache.cloudstack.api.InternalIdentity;
 
 @Entity
 @Table(name="event")
 public class EventVO implements Event {
-	@Id
+    @Id
     @GeneratedValue(strategy=GenerationType.IDENTITY)
     @Column(name="id")
-	private long id = -1;
+    private long id = -1;
 
-	@Column(name="type")
-	private String type;
-	
-	@Enumerated(value=EnumType.STRING)
-	@Column(name="state")
+    @Column(name="type")
+    private String type;
+
+    @Enumerated(value=EnumType.STRING)
+    @Column(name="state")
     private State state = State.Completed;
 
-	@Column(name="description", length=1024)
-	private String description;
+    @Column(name="description", length=1024)
+    private String description;
 
-	@Column(name=GenericDao.CREATED_COLUMN)
-	private Date createDate;
+    @Column(name=GenericDao.CREATED_COLUMN)
+    private Date createDate;
 
     @Column(name="user_id")
     private long userId;
 
-	@Column(name="account_id")
-	private long accountId;
+    @Column(name="account_id")
+    private long accountId;
 
     @Column(name="domain_id")
     private long domainId;
 
-	@Column(name="level")
-	private String level = LEVEL_INFO;
-	
-	@Column(name="start_id")
+    @Column(name="level")
+    private String level = LEVEL_INFO;
+
+    @Column(name="start_id")
     private long startId;
 
-	@Column(name="parameters", length=1024)
-	private String parameters;
-	
-	@Column(name="uuid")
-	private String uuid;
-
-	@Transient
-	private int totalSize;
-
-	public static final String LEVEL_INFO = "INFO";
-	public static final String LEVEL_WARN = "WARN";
-	public static final String LEVEL_ERROR = "ERROR";
-	
-	public EventVO() {
-		this.uuid = UUID.randomUUID().toString();
-	}
-	
-	public long getId() {
-		return id;
-	}
-	@Override
+    @Column(name="parameters", length=1024)
+    private String parameters;
+
+    @Column(name="uuid")
+    private String uuid;
+
+    @Column(name="archived")
+    private boolean archived;
+
+    @Transient
+    private int totalSize;
+
+    public static final String LEVEL_INFO = "INFO";
+    public static final String LEVEL_WARN = "WARN";
+    public static final String LEVEL_ERROR = "ERROR";
+
+    public EventVO() {
+        this.uuid = UUID.randomUUID().toString();
+    }
+
+    public long getId() {
+        return id;
+    }
+    @Override
     public String getType() {
-		return type;
-	}
-	public void setType(String type) {
-		this.type = type;
-	}
-	@Override
+        return type;
+    }
+    public void setType(String type) {
+        this.type = type;
+    }
+    @Override
     public State getState() {
         return state;
     }
@@ -105,27 +106,27 @@ public class EventVO implements Event {
         this.state = state;
     }
 
-	@Override
+    @Override
     public String getDescription() {
-		return description;
-	}
-	public void setDescription(String description) {
-		this.description = description;
-	}
-	@Override
+        return description;
+    }
+    public void setDescription(String description) {
+        this.description = description;
+    }
+    @Override
     public Date getCreateDate() {
-		return createDate;
-	}
-	public void setCreatedDate(Date createdDate) {
-	    createDate = createdDate;
-	}
-	@Override
+        return createDate;
+    }
+    public void setCreatedDate(Date createdDate) {
+        createDate = createdDate;
+    }
+    @Override
     public long getUserId() {
-		return userId;
-	}
-	public void setUserId(long userId) {
-		this.userId = userId;
-	}
+        return userId;
+    }
+    public void setUserId(long userId) {
+        this.userId = userId;
+    }
     @Override
     public long getAccountId() {
         return accountId;
@@ -165,21 +166,29 @@ public class EventVO implements Event {
         this.startId = startId;
     }
 
-	@Override
+    @Override
     public String getParameters() {
-		return parameters;
-	}
-	public void setParameters(String parameters) {
-		this.parameters = parameters;
-	}
-	
-	@Override
-	public String getUuid() {
-		return this.uuid;
-	}
-	
-	public void setUuid(String uuid) {
-		this.uuid = uuid;
-	}
+        return parameters;
+    }
+    public void setParameters(String parameters) {
+        this.parameters = parameters;
+    }
+
+    @Override
+    public String getUuid() {
+        return this.uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
 
+    @Override
+    public boolean getArchived() {
+        return archived;
+    }
+
+    public void setArchived(Boolean archived) {
+        this.archived = archived;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/core/src/com/cloud/event/dao/EventDao.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/event/dao/EventDao.java b/core/src/com/cloud/event/dao/EventDao.java
index bfcb818..da5f47a 100644
--- a/core/src/com/cloud/event/dao/EventDao.java
+++ b/core/src/com/cloud/event/dao/EventDao.java
@@ -30,4 +30,9 @@ public interface EventDao extends GenericDao<EventVO, Long> {
     public List<EventVO> listOlderEvents(Date oldTime);
 
     EventVO findCompletedEvent(long startId);
+
+    public List<EventVO> listToArchiveOrDeleteEvents(List<Long> ids, String type,
Date olderThan, Long accountId);
+
+    public void archiveEvents(List<EventVO> events);
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/core/src/com/cloud/event/dao/EventDaoImpl.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/event/dao/EventDaoImpl.java b/core/src/com/cloud/event/dao/EventDaoImpl.java
index 44fbb03..6ba59c5 100644
--- a/core/src/com/cloud/event/dao/EventDaoImpl.java
+++ b/core/src/com/cloud/event/dao/EventDaoImpl.java
@@ -30,24 +30,34 @@ import com.cloud.utils.db.Filter;
 import com.cloud.utils.db.GenericDaoBase;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.SearchCriteria.Op;
 
 @Component
 @Local(value={EventDao.class})
 public class EventDaoImpl extends GenericDaoBase<EventVO, Long> implements EventDao
{
-	public static final Logger s_logger = Logger.getLogger(EventDaoImpl.class.getName());
-	protected final SearchBuilder<EventVO> CompletedEventSearch;
-	
-	public EventDaoImpl () {
-	    CompletedEventSearch = createSearchBuilder();
-	    CompletedEventSearch.and("state",CompletedEventSearch.entity().getState(),SearchCriteria.Op.EQ);
-	    CompletedEventSearch.and("startId", CompletedEventSearch.entity().getStartId(), SearchCriteria.Op.EQ);
-	    CompletedEventSearch.done();
-	}
+    public static final Logger s_logger = Logger.getLogger(EventDaoImpl.class.getName());
+    protected final SearchBuilder<EventVO> CompletedEventSearch;
+    protected final SearchBuilder<EventVO> ToArchiveOrDeleteEventSearch;
 
-	@Override
-	public List<EventVO> searchAllEvents(SearchCriteria<EventVO> sc, Filter filter)
{
-	    return listIncludingRemovedBy(sc, filter);
-	}
+    public EventDaoImpl () {
+        CompletedEventSearch = createSearchBuilder();
+        CompletedEventSearch.and("state",CompletedEventSearch.entity().getState(),SearchCriteria.Op.EQ);
+        CompletedEventSearch.and("startId", CompletedEventSearch.entity().getStartId(), SearchCriteria.Op.EQ);
+        CompletedEventSearch.done();
+
+        ToArchiveOrDeleteEventSearch = createSearchBuilder();
+        ToArchiveOrDeleteEventSearch.and("id", ToArchiveOrDeleteEventSearch.entity().getId(),
Op.IN);
+        ToArchiveOrDeleteEventSearch.and("type", ToArchiveOrDeleteEventSearch.entity().getType(),
Op.EQ);
+        ToArchiveOrDeleteEventSearch.and("accountId", ToArchiveOrDeleteEventSearch.entity().getAccountId(),
Op.EQ);
+        ToArchiveOrDeleteEventSearch.and("createDateL", ToArchiveOrDeleteEventSearch.entity().getCreateDate(),
Op.LT);
+        ToArchiveOrDeleteEventSearch.done();
+    }
+
+    @Override
+    public List<EventVO> searchAllEvents(SearchCriteria<EventVO> sc, Filter filter)
{
+        return listIncludingRemovedBy(sc, filter);
+    }
 
     @Override
     public List<EventVO> listOlderEvents(Date oldTime) {
@@ -55,9 +65,8 @@ public class EventDaoImpl extends GenericDaoBase<EventVO, Long> implements
Event
         SearchCriteria<EventVO> sc = createSearchCriteria();
         sc.addAnd("createDate", SearchCriteria.Op.LT, oldTime);
         return listIncludingRemovedBy(sc, null);
-        
     }
-    
+
     @Override
     public EventVO findCompletedEvent(long startId) {
         SearchCriteria<EventVO> sc = CompletedEventSearch.create();
@@ -65,4 +74,36 @@ public class EventDaoImpl extends GenericDaoBase<EventVO, Long> implements
Event
         sc.setParameters("startId", startId);
         return findOneIncludingRemovedBy(sc);
     }
+
+    @Override
+    public List<EventVO> listToArchiveOrDeleteEvents(List<Long> ids, String type,
Date olderThan, Long accountId) {
+        SearchCriteria<EventVO> sc = ToArchiveOrDeleteEventSearch.create();
+        if (ids != null) {
+            sc.setParameters("id", ids.toArray(new Object[ids.size()]));
+        }
+        if (type != null) {
+            sc.setParameters("type", type);
+        }
+        if (olderThan != null) {
+            sc.setParameters("createDateL", olderThan);
+        }
+        if (accountId != null) {
+            sc.setParameters("accountId", accountId);
+        }
+        return search(sc, null);
+    }
+
+    @Override
+    public void archiveEvents(List<EventVO> events) {
+
+        Transaction txn = Transaction.currentTxn();
+        txn.start();
+        for (EventVO event : events) {
+            event = lockRow(event.getId(), true);
+            event.setArchived(true);
+            update(event.getId(), event);
+            txn.commit();
+        }
+        txn.close();
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/server/src/com/cloud/alert/dao/AlertDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/alert/dao/AlertDao.java b/server/src/com/cloud/alert/dao/AlertDao.java
index eb1faa5..fda814d 100755
--- a/server/src/com/cloud/alert/dao/AlertDao.java
+++ b/server/src/com/cloud/alert/dao/AlertDao.java
@@ -16,6 +16,9 @@
 // under the License.
 package com.cloud.alert.dao;
 
+import java.util.Date;
+import java.util.List;
+
 import com.cloud.alert.AlertVO;
 import com.cloud.utils.db.GenericDao;
 
@@ -23,4 +26,8 @@ public interface AlertDao extends GenericDao<AlertVO, Long> {
     AlertVO getLastAlert(short type, long dataCenterId, Long podId, Long clusterId);
     // This is for backward compatibility
     AlertVO getLastAlert(short type, long dataCenterId, Long podId);
+
+    public boolean deleteAlert(List<Long> Ids, String type, Date olderThan, Long zoneId);
+    public boolean archiveAlert(List<Long> Ids, String type, Date olderThan, Long zoneId);
+    public List<AlertVO> listOlderAlerts(Date oldTime);
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/server/src/com/cloud/alert/dao/AlertDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/alert/dao/AlertDaoImpl.java b/server/src/com/cloud/alert/dao/AlertDaoImpl.java
index 2f3be88..4b9bc6a 100755
--- a/server/src/com/cloud/alert/dao/AlertDaoImpl.java
+++ b/server/src/com/cloud/alert/dao/AlertDaoImpl.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.alert.dao;
 
+import java.util.Date;
 import java.util.List;
 
 import javax.ejb.Local;
@@ -25,11 +26,26 @@ import org.springframework.stereotype.Component;
 import com.cloud.alert.AlertVO;
 import com.cloud.utils.db.Filter;
 import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.utils.db.Transaction;
 
 @Component
 @Local(value = { AlertDao.class })
 public class AlertDaoImpl extends GenericDaoBase<AlertVO, Long> implements AlertDao
{
+
+    protected final SearchBuilder<AlertVO> AlertSearchByIdsAndType;
+
+    public AlertDaoImpl() {
+        AlertSearchByIdsAndType = createSearchBuilder();
+        AlertSearchByIdsAndType.and("id", AlertSearchByIdsAndType.entity().getId(), Op.IN);
+        AlertSearchByIdsAndType.and("type", AlertSearchByIdsAndType.entity().getType(), Op.EQ);
+        AlertSearchByIdsAndType.and("createdDateL", AlertSearchByIdsAndType.entity().getCreatedDate(),
Op.LT);
+        AlertSearchByIdsAndType.and("data_center_id", AlertSearchByIdsAndType.entity().getDataCenterId(),
Op.EQ);
+        AlertSearchByIdsAndType.done();
+    }
+
     @Override
     public AlertVO getLastAlert(short type, long dataCenterId, Long podId, Long clusterId)
{
         Filter searchFilter = new Filter(AlertVO.class, "createdDate", Boolean.FALSE, Long.valueOf(0),
Long.valueOf(1));
@@ -68,4 +84,73 @@ public class AlertDaoImpl extends GenericDaoBase<AlertVO, Long> implements
Alert
         }
         return null;
     }
+
+    @Override
+    public boolean archiveAlert(List<Long> Ids, String type, Date olderThan, Long zoneId)
{
+        SearchCriteria<AlertVO> sc = AlertSearchByIdsAndType.create();
+
+        if (Ids != null) {
+            sc.setParameters("id", Ids.toArray(new Object[Ids.size()]));
+        }
+        if(type != null) {
+            sc.setParameters("type", type);
+        }
+        if(zoneId != null) {
+            sc.setParameters("data_center_id", zoneId);
+        }
+        if(olderThan != null) {
+            sc.setParameters("createdDateL", olderThan);
+        }
+        boolean result = true;;
+        List<AlertVO> alerts = listBy(sc);
+        if (Ids != null && alerts.size() < Ids.size()) {
+            result = false;
+            return result;
+        }
+        Transaction txn = Transaction.currentTxn();
+        txn.start();
+        for (AlertVO alert : alerts) {
+            alert = lockRow(alert.getId(), true);
+            alert.setArchived(true);
+            update(alert.getId(), alert);
+            txn.commit();
+        }
+        txn.close();
+        return result;
+    }
+
+    @Override
+    public boolean deleteAlert(List<Long> ids, String type, Date olderThan, Long zoneId)
{
+        SearchCriteria<AlertVO> sc = AlertSearchByIdsAndType.create();
+
+        if (ids != null) {
+            sc.setParameters("id", ids.toArray(new Object[ids.size()]));
+        }
+        if(type != null) {
+            sc.setParameters("type", type);
+        }
+        if(zoneId != null) {
+            sc.setParameters("data_center_id", zoneId);
+        }
+        if(olderThan != null) {
+            sc.setParameters("createdDateL", olderThan);
+        }
+        boolean result = true;
+        List<AlertVO> alerts = listBy(sc);
+        if (ids != null && alerts.size() < ids.size()) {
+            result = false;
+            return result;
+        }
+        remove(sc);
+        return result;
+    }
+
+    @Override
+    public List<AlertVO> listOlderAlerts(Date oldTime) {
+        if (oldTime == null) return null;
+        SearchCriteria<AlertVO> sc = createSearchCriteria();
+        sc.addAnd("createDate", SearchCriteria.Op.LT, oldTime);
+        return listIncludingRemovedBy(sc, null);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/server/src/com/cloud/api/ApiDispatcher.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiDispatcher.java b/server/src/com/cloud/api/ApiDispatcher.java
index 764b3ae..f7a3236 100755
--- a/server/src/com/cloud/api/ApiDispatcher.java
+++ b/server/src/com/cloud/api/ApiDispatcher.java
@@ -50,6 +50,8 @@ import org.apache.cloudstack.api.InternalIdentity;
 import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.ServerApiException;
 import org.apache.cloudstack.api.Validate;
+import org.apache.cloudstack.api.command.user.event.ArchiveEventsCmd;
+import org.apache.cloudstack.api.command.user.event.DeleteEventsCmd;
 import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
@@ -391,7 +393,7 @@ public class ApiDispatcher {
                 // This piece of code is for maintaining backward compatibility
                 // and support both the date formats(Bug 9724)
                 // Do the date messaging for ListEventsCmd only
-                if (cmdObj instanceof ListEventsCmd) {
+                if (cmdObj instanceof ListEventsCmd || cmdObj instanceof DeleteEventsCmd
|| cmdObj instanceof ArchiveEventsCmd) {
                     boolean isObjInNewDateFormat = isObjInNewDateFormat(paramObj.toString());
                     if (isObjInNewDateFormat) {
                         DateFormat newFormat = BaseCmd.NEW_INPUT_FORMAT;
@@ -406,6 +408,8 @@ public class ApiDispatcher {
                                 date = messageDate(date, 0, 0, 0);
                             } else if (field.getName().equals("endDate")) {
                                 date = messageDate(date, 23, 59, 59);
+                            } else if (field.getName().equals("olderThan")) {
+                                date = messageDate(date, 0, 0, 0);
                             }
                             field.set(cmdObj, date);
                         }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/server/src/com/cloud/api/query/QueryManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java
index 8d8663a..35fe2f3 100644
--- a/server/src/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/com/cloud/api/query/QueryManagerImpl.java
@@ -397,6 +397,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService
{
         sb.and("state", sb.entity().getState(), SearchCriteria.Op.NEQ);
         sb.and("startId", sb.entity().getStartId(), SearchCriteria.Op.EQ);
         sb.and("createDate", sb.entity().getCreateDate(), SearchCriteria.Op.BETWEEN);
+        sb.and("archived", sb.entity().getArchived(), SearchCriteria.Op.EQ);
 
         SearchCriteria<EventJoinVO> sc = sb.create();
         // building ACL condition
@@ -430,6 +431,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService
{
             sc.setParameters("createDateL", endDate);
         }
 
+        sc.setParameters("archived", false);
+
         Pair<List<EventJoinVO>, Integer> eventPair = null;
         // event_view will not have duplicate rows for each event, so searchAndCount should
be good enough.
         if ((entryTime != null) && (duration != null)) {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/server/src/com/cloud/api/query/vo/EventJoinVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/vo/EventJoinVO.java b/server/src/com/cloud/api/query/vo/EventJoinVO.java
index f29a942..12d7e5a 100644
--- a/server/src/com/cloud/api/query/vo/EventJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/EventJoinVO.java
@@ -104,6 +104,8 @@ public class EventJoinVO extends BaseViewVO implements ControlledViewEntity
{
     @Column(name="project_name")
     private String projectName;
 
+    @Column(name="archived")
+    private boolean archived;
 
 
     public EventJoinVO() {
@@ -313,5 +315,12 @@ public class EventJoinVO extends BaseViewVO implements ControlledViewEntity
{
         this.parameters = parameters;
     }
 
+    public boolean getArchived() {
+        return archived;
+    }
+
+    public void setArchived(Boolean archived) {
+        this.archived = archived;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/server/src/com/cloud/configuration/Config.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index 418f97d..64465a2 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -204,9 +204,10 @@ public enum Config {
 	SecStorageSessionMax("Advanced", AgentManager.class, Integer.class, "secstorage.session.max",
"50", "The max number of command execution sessions that a SSVM can handle", null),
 	SecStorageCmdExecutionTimeMax("Advanced", AgentManager.class, Integer.class, "secstorage.cmd.execution.time.max",
"30", "The max command execution time in minute", null),
 	SecStorageProxy("Advanced", AgentManager.class, String.class, "secstorage.proxy", null,
"http proxy used by ssvm, in http://username:password@proxyserver:port format", null),
+    AlertPurgeInterval("Advanced", ManagementServer.class, Integer.class, "alert.purge.interval",
"86400", "The interval (in seconds) to wait before running the alert purge thread", null),
+    AlertPurgeDelay("Advanced", ManagementServer.class, Integer.class, "alert.purge.delay",
"0", "Alerts older than specified number days will be purged. Set this value to 0 to never
delete alerts", null),
 
-
-	DirectAttachNetworkEnabled("Advanced", ManagementServer.class, Boolean.class, "direct.attach.network.externalIpAllocator.enabled",
"false", "Direct-attach VMs using external DHCP server", "true,false"),
+    DirectAttachNetworkEnabled("Advanced", ManagementServer.class, Boolean.class, "direct.attach.network.externalIpAllocator.enabled",
"false", "Direct-attach VMs using external DHCP server", "true,false"),
 	DirectAttachNetworkExternalAPIURL("Advanced", ManagementServer.class, String.class, "direct.attach.network.externalIpAllocator.url",
null, "Direct-attach VMs using external DHCP server (API url)", null),
 	CheckPodCIDRs("Advanced", ManagementServer.class, String.class, "check.pod.cidrs", "true",
"If true, different pods must belong to different CIDR subnets.", "true,false"),
 	NetworkGcWait("Advanced", ManagementServer.class, Integer.class, "network.gc.wait", "600",
"Time (in seconds) to wait before shutting down a network that's not in used", null),

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index 11400de..d70c45f 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -47,6 +47,7 @@ import javax.management.MalformedObjectNameException;
 import javax.management.NotCompliantMBeanException;
 import javax.naming.ConfigurationException;
 
+import org.apache.cloudstack.acl.ControlledEntity;
 import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 import org.apache.cloudstack.api.ApiConstants;
 
@@ -125,6 +126,7 @@ import com.cloud.alert.AlertManager;
 import com.cloud.alert.AlertVO;
 import com.cloud.alert.dao.AlertDao;
 import com.cloud.api.ApiDBUtils;
+import com.cloud.api.query.vo.EventJoinVO;
 import com.cloud.async.AsyncJobExecutor;
 import com.cloud.async.AsyncJobManager;
 import com.cloud.async.AsyncJobResult;
@@ -188,6 +190,7 @@ import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
 import com.cloud.info.ConsoleProxyInfo;
 import com.cloud.keystore.KeystoreManager;
 import com.cloud.network.IpAddress;
+import com.cloud.network.as.ConditionVO;
 import com.cloud.network.dao.IPAddressDao;
 import com.cloud.network.dao.IPAddressVO;
 import com.cloud.network.dao.LoadBalancerDao;
@@ -262,6 +265,7 @@ import com.cloud.utils.db.GenericDaoBase;
 import com.cloud.utils.db.GlobalLock;
 import com.cloud.utils.db.JoinBuilder;
 import com.cloud.utils.db.JoinBuilder.JoinType;
+import com.cloud.utils.db.SearchCriteria.Op;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.Transaction;
@@ -295,7 +299,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName());
 
     @Inject
-    private AccountManager _accountMgr;
+    public AccountManager _accountMgr;
     @Inject
     private AgentManager _agentMgr;
     @Inject
@@ -311,7 +315,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     @Inject
     private SecondaryStorageVmDao _secStorageVmDao;
     @Inject
-    private EventDao _eventDao;
+    public EventDao _eventDao;
     @Inject
     private DataCenterDao _dcDao;
     @Inject
@@ -347,7 +351,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     @Inject
     private AccountDao _accountDao;
     @Inject
-    private AlertDao _alertDao;
+    public AlertDao _alertDao;
     @Inject
     private CapacityDao _capacityDao;
     @Inject
@@ -371,6 +375,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     @Inject
     private AsyncJobManager _asyncMgr;
     private int _purgeDelay;
+    private int _alertPurgeDelay;
     @Inject
     private InstanceGroupDao _vmGroupDao;
     @Inject
@@ -417,6 +422,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     EventUtils	_forceEventUtilsRef;
 */
     private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1,
new NamedThreadFactory("EventChecker"));
+    private final ScheduledExecutorService _alertExecutor = Executors.newScheduledThreadPool(1,
new NamedThreadFactory("AlertChecker"));
     private KeystoreManager _ksMgr;
 
     private Map<String, String> _configs;
@@ -446,6 +452,15 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
             _eventExecutor.scheduleAtFixedRate(new EventPurgeTask(), cleanup, cleanup, TimeUnit.SECONDS);
         }
 
+        //Alerts purge configurations
+        int alertPurgeInterval = NumbersUtil.parseInt(_configDao.getValue(Config.AlertPurgeInterval.key()),
+                60 * 60 * 24); // 1 day.
+        _alertPurgeDelay = NumbersUtil.parseInt(_configDao.getValue(Config.AlertPurgeDelay.key()),
0);
+        if (_alertPurgeDelay != 0) {
+            _alertExecutor.scheduleAtFixedRate(new AlertPurgeTask(), alertPurgeInterval,
alertPurgeInterval,
+                    TimeUnit.SECONDS);
+        }
+
         String[] availableIds = TimeZone.getAvailableIDs();
         _availableIdsMap = new HashMap<String, Boolean>(availableIds.length);
         for (String id : availableIds) {
@@ -538,6 +553,42 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         return _eventDao.search(sc, null);
     }
 
+    @Override
+    public boolean archiveEvents(ArchiveEventsCmd cmd) {
+        List<Long> ids = cmd.getIds();
+        boolean result =true;
+
+        List<EventVO> events = _eventDao.listToArchiveOrDeleteEvents(ids, cmd.getType(),
cmd.getOlderThan(), cmd.getEntityOwnerId());
+        ControlledEntity[] sameOwnerEvents = events.toArray(new ControlledEntity[events.size()]);
+        _accountMgr.checkAccess(UserContext.current().getCaller(), null, true, sameOwnerEvents);
+
+        if (ids != null && events.size() < ids.size()) {
+            result = false;
+            return result;
+        }
+        _eventDao.archiveEvents(events);
+        return result;
+    }
+
+    @Override
+    public boolean deleteEvents(DeleteEventsCmd cmd) {
+        List<Long> ids = cmd.getIds();
+        boolean result =true;
+
+        List<EventVO> events = _eventDao.listToArchiveOrDeleteEvents(ids, cmd.getType(),
cmd.getOlderThan(), cmd.getEntityOwnerId());
+        ControlledEntity[] sameOwnerEvents = events.toArray(new ControlledEntity[events.size()]);
+        _accountMgr.checkAccess(UserContext.current().getCaller(), null, true, sameOwnerEvents);
+
+        if (ids != null && events.size() < ids.size()) {
+            result = false;
+            return result;
+        }
+        for (EventVO event : events) {
+        _eventDao.remove(event.getId());
+        }
+        return result;
+    }
+
     private Date massageDate(Date date, int hourOfDay, int minute, int second) {
         Calendar cal = Calendar.getInstance();
         cal.setTime(date);
@@ -1663,11 +1714,26 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
             sc.addAnd("type", SearchCriteria.Op.EQ, type);
         }
 
+        sc.addAnd("archived", SearchCriteria.Op.EQ, false);
         Pair<List<AlertVO>, Integer> result = _alertDao.searchAndCount(sc, searchFilter);
         return new Pair<List<? extends Alert>, Integer>(result.first(), result.second());
     }
 
     @Override
+    public boolean archiveAlerts(ArchiveAlertsCmd cmd) {
+        Long zoneId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(),
null);
+        boolean result = _alertDao.archiveAlert(cmd.getIds(), cmd.getType(), cmd.getOlderThan(),
zoneId);
+        return result;
+    }
+
+    @Override
+    public boolean deleteAlerts(DeleteAlertsCmd cmd) {
+        Long zoneId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(),
null);
+        boolean result = _alertDao.deleteAlert(cmd.getIds(), cmd.getType(), cmd.getOlderThan(),
zoneId);
+        return result;
+    }
+
+    @Override
     public List<CapacityVO> listTopConsumedResources(ListCapacityCmd cmd) {
 
         Integer capacityType = cmd.getType();
@@ -2168,6 +2234,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         cmdList.add(AddIpToVmNicCmd.class);
         cmdList.add(RemoveIpFromVmNicCmd.class);
         cmdList.add(ListNicsCmd.class);
+        cmdList.add(ArchiveAlertsCmd.class);
+        cmdList.add(DeleteAlertsCmd.class);
+        cmdList.add(ArchiveEventsCmd.class);
+        cmdList.add(DeleteEventsCmd.class);
         return cmdList;
     }
 
@@ -2205,6 +2275,39 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         }
     }
 
+    protected class AlertPurgeTask implements Runnable {
+        @Override
+        public void run() {
+            try {
+                GlobalLock lock = GlobalLock.getInternLock("AlertPurge");
+                if (lock == null) {
+                    s_logger.debug("Couldn't get the global lock");
+                    return;
+                }
+                if (!lock.lock(30)) {
+                    s_logger.debug("Couldn't lock the db");
+                    return;
+                }
+                try {
+                    final Calendar purgeCal = Calendar.getInstance();
+                    purgeCal.add(Calendar.DAY_OF_YEAR, - _alertPurgeDelay);
+                    Date purgeTime = purgeCal.getTime();
+                    s_logger.debug("Deleting alerts older than: " + purgeTime.toString());
+                    List<AlertVO> oldAlerts = _alertDao.listOlderAlerts(purgeTime);
+                    s_logger.debug("Found " + oldAlerts.size() + " events to be purged");
+                    for (AlertVO alert : oldAlerts) {
+                        _alertDao.expunge(alert.getId());
+                    }
+                } catch (Exception e) {
+                    s_logger.error("Exception ", e);
+                } finally {
+                    lock.unlock();
+                }
+            } catch (Exception e) {
+                s_logger.error("Exception ", e);
+            }
+        }
+    }
 
     @Override
     public Pair<List<StoragePoolVO>, Integer> searchForStoragePools(Criteria
c) {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5e4c2c8a/setup/db/db/schema-410to420.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql
index f3112a1..ca15bda 100644
--- a/setup/db/db/schema-410to420.sql
+++ b/setup/db/db/schema-410to420.sql
@@ -140,3 +140,48 @@ CREATE TABLE nic_secondary_ips (
 
 ALTER TABLE `cloud`.`nics` ADD COLUMN secondary_ip SMALLINT DEFAULT '0' COMMENT 'secondary
ips configured for the nic';
 ALTER TABLE `cloud`.`user_ip_address` ADD COLUMN dnat_vmip VARCHAR(40);
+
+ALTER TABLE `cloud`.`alert` ADD COLUMN `archived` tinyint(1) unsigned NOT NULL DEFAULT 0;
+ALTER TABLE `cloud`.`event` ADD COLUMN `archived` tinyint(1) unsigned NOT NULL DEFAULT 0;
+INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server',
'alert.purge.interval', '86400', 'The interval (in seconds) to wait before running the alert
purge thread');
+INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server',
'alert.purge.delay', '0', 'Alerts older than specified number days will be purged. Set this
value to 0 to never delete alerts');
+
+DROP VIEW IF EXISTS `cloud`.`event_view`;
+CREATE VIEW `cloud`.`event_view` AS
+    select
+        event.id,
+        event.uuid,
+        event.type,
+        event.state,
+        event.description,
+        event.created,
+        event.level,
+        event.parameters,
+        event.start_id,
+        eve.uuid start_uuid,
+        event.user_id,
+        event.archived,
+        user.username user_name,
+        account.id account_id,
+        account.uuid account_uuid,
+        account.account_name account_name,
+        account.type account_type,
+        domain.id domain_id,
+        domain.uuid domain_uuid,
+        domain.name domain_name,
+        domain.path domain_path,
+        projects.id project_id,
+        projects.uuid project_uuid,
+        projects.name project_name
+    from
+        `cloud`.`event`
+            inner join
+        `cloud`.`account` ON event.account_id = account.id
+            inner join
+        `cloud`.`domain` ON event.domain_id = domain.id
+            inner join
+        `cloud`.`user` ON event.user_id = user.id
+            left join
+        `cloud`.`projects` ON projects.project_account_id = event.account_id
+            left join
+        `cloud`.`event` eve ON event.start_id = eve.id;


Mime
View raw message