You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bh...@apache.org on 2015/01/23 15:09:22 UTC

[1/2] git commit: updated refs/heads/master to f9a8111

Repository: cloudstack
Updated Branches:
  refs/heads/master 35ede0418 -> f9a8111e1


hyperv: fix maven warning, add version to exec plugin

Signed-off-by: Rohit Yadav <ro...@shapeblue.com>


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

Branch: refs/heads/master
Commit: 9635e177018002d87c8a90a56b6d4ae173f03cfd
Parents: 35ede04
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Fri Jan 23 18:41:09 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Jan 23 18:41:09 2015 +0530

----------------------------------------------------------------------
 plugins/hypervisors/hyperv/pom.xml | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9635e177/plugins/hypervisors/hyperv/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/pom.xml b/plugins/hypervisors/hyperv/pom.xml
index e09fb43..7ab9f09 100644
--- a/plugins/hypervisors/hyperv/pom.xml
+++ b/plugins/hypervisors/hyperv/pom.xml
@@ -70,6 +70,7 @@
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>exec-maven-plugin</artifactId>
+        <version>1.2.1</version>
         <configuration>
           <executable>java</executable>
           <mainClass>com.cloud.agent.AgentShell</mainClass>


[2/2] git commit: updated refs/heads/master to f9a8111

Posted by bh...@apache.org.
CLOUDSTACK-8151: Add removeRawUsageRecords API to cleanup old cloud_usage data

Call removeRawUsageRecords with interval (> 0) and it will clean up cloud_usage
table by removing records older than interval no. of days from today (current date)
and in case it runs when the job exec time is near, it will fail alerting
user to try again after a 15 min window.

There is an issue with async job scheduler, if this API were async it tries
to search and remove job from cloud_usage.async_job table and fails which is
why this API is sync and extends BaseCmd.

Signed-off-by: Rohit Yadav <ro...@shapeblue.com>


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

Branch: refs/heads/master
Commit: f9a8111e17cdd561203d7098667488ad64888d86
Parents: 9635e17
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Fri Jan 23 19:17:39 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Jan 23 19:38:32 2015 +0530

----------------------------------------------------------------------
 api/src/com/cloud/event/EventTypes.java         |  44 ++++----
 .../admin/usage/RemoveRawUsageRecordsCmd.java   |  78 ++++++++++++++
 .../apache/cloudstack/usage/UsageService.java   |  11 +-
 client/tomcatconf/commands.properties.in        |   1 +
 .../src/com/cloud/usage/dao/UsageDao.java       |   6 +-
 .../src/com/cloud/usage/dao/UsageDaoImpl.java   |  44 +++++---
 .../com/cloud/server/ManagementServerImpl.java  |   2 +
 .../src/com/cloud/usage/UsageServiceImpl.java   | 101 ++++++++++++-------
 8 files changed, 213 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f9a8111e/api/src/com/cloud/event/EventTypes.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java
index 2e8c8ae..20f287a 100644
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -16,26 +16,6 @@
 // under the License.
 package com.cloud.event;
 
-import java.util.HashMap;
-import java.util.Map;
-
-import com.cloud.network.IpAddress;
-import com.cloud.network.Site2SiteCustomerGateway;
-import com.cloud.network.Site2SiteVpnGateway;
-import com.cloud.network.rules.FirewallRule;
-import com.cloud.network.rules.HealthCheckPolicy;
-import com.cloud.network.rules.StickinessPolicy;
-import com.cloud.network.vpc.NetworkACL;
-import com.cloud.network.vpc.NetworkACLItem;
-import com.cloud.network.Site2SiteVpnConnection;
-import com.cloud.server.ResourceTag;
-import com.cloud.storage.snapshot.SnapshotPolicy;
-import com.cloud.vm.ConsoleProxy;
-import com.cloud.vm.Nic;
-import com.cloud.vm.NicSecondaryIp;
-import com.cloud.vm.SecondaryStorageVm;
-import org.apache.cloudstack.config.Configuration;
-
 import com.cloud.dc.DataCenter;
 import com.cloud.dc.Pod;
 import com.cloud.dc.StorageNetworkIpRange;
@@ -43,20 +23,29 @@ import com.cloud.dc.Vlan;
 import com.cloud.domain.Domain;
 import com.cloud.host.Host;
 import com.cloud.network.GuestVlan;
+import com.cloud.network.IpAddress;
 import com.cloud.network.Network;
 import com.cloud.network.PhysicalNetwork;
 import com.cloud.network.PhysicalNetworkServiceProvider;
 import com.cloud.network.PhysicalNetworkTrafficType;
 import com.cloud.network.RemoteAccessVpn;
+import com.cloud.network.Site2SiteCustomerGateway;
+import com.cloud.network.Site2SiteVpnConnection;
+import com.cloud.network.Site2SiteVpnGateway;
 import com.cloud.network.as.AutoScaleCounter;
 import com.cloud.network.as.AutoScalePolicy;
 import com.cloud.network.as.AutoScaleVmGroup;
 import com.cloud.network.as.AutoScaleVmProfile;
 import com.cloud.network.as.Condition;
 import com.cloud.network.router.VirtualRouter;
+import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.HealthCheckPolicy;
 import com.cloud.network.rules.LoadBalancer;
 import com.cloud.network.rules.StaticNat;
+import com.cloud.network.rules.StickinessPolicy;
 import com.cloud.network.security.SecurityGroup;
+import com.cloud.network.vpc.NetworkACL;
+import com.cloud.network.vpc.NetworkACLItem;
 import com.cloud.network.vpc.PrivateGateway;
 import com.cloud.network.vpc.StaticRoute;
 import com.cloud.network.vpc.Vpc;
@@ -64,14 +53,25 @@ import com.cloud.offering.DiskOffering;
 import com.cloud.offering.NetworkOffering;
 import com.cloud.offering.ServiceOffering;
 import com.cloud.projects.Project;
+import com.cloud.server.ResourceTag;
 import com.cloud.storage.GuestOS;
 import com.cloud.storage.GuestOSHypervisor;
 import com.cloud.storage.Snapshot;
 import com.cloud.storage.Volume;
+import com.cloud.storage.snapshot.SnapshotPolicy;
 import com.cloud.template.VirtualMachineTemplate;
 import com.cloud.user.Account;
 import com.cloud.user.User;
+import com.cloud.vm.ConsoleProxy;
+import com.cloud.vm.Nic;
+import com.cloud.vm.NicSecondaryIp;
+import com.cloud.vm.SecondaryStorageVm;
 import com.cloud.vm.VirtualMachine;
+import org.apache.cloudstack.config.Configuration;
+import org.apache.cloudstack.usage.Usage;
+
+import java.util.HashMap;
+import java.util.Map;
 
 public class EventTypes {
 
@@ -519,6 +519,8 @@ public class EventTypes {
     public static final String EVENT_NIC_SECONDARY_IP_UNASSIGN = "NIC.SECONDARY.IP.UNASSIGN";
     public static final String EVENT_NIC_SECONDARY_IP_CONFIGURE = "NIC.SECONDARY.IP.CONFIGURE";
 
+    //Usage related events
+    public static final String EVENT_USAGE_REMOVE_USAGE_RECORDS = "USAGE.REMOVE.USAGE.RECORDS";
 
     static {
 
@@ -871,6 +873,8 @@ public class EventTypes {
         entityEventDetails.put(EVENT_NIC_SECONDARY_IP_UNASSIGN, NicSecondaryIp.class);
         entityEventDetails.put(EVENT_NIC_SECONDARY_IP_CONFIGURE, NicSecondaryIp.class);
 
+        //Usage
+        entityEventDetails.put(EVENT_USAGE_REMOVE_USAGE_RECORDS, Usage.class);
     }
 
     public static String getEntityForEvent(String eventName) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f9a8111e/api/src/org/apache/cloudstack/api/command/admin/usage/RemoveRawUsageRecordsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/usage/RemoveRawUsageRecordsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/usage/RemoveRawUsageRecordsCmd.java
new file mode 100644
index 0000000..da7871c
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/usage/RemoveRawUsageRecordsCmd.java
@@ -0,0 +1,78 @@
+// 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 org.apache.cloudstack.api.command.admin.usage;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.log4j.Logger;
+
+@APICommand(name = "removeRawUsageRecords", description = "Safely removes raw records from cloud_usage table", responseObject = SuccessResponse.class, since = "4.6.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class RemoveRawUsageRecordsCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(RemoveRawUsageRecordsCmd.class.getName());
+
+    private static final String s_name = "removerawusagerecordsresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+    @Parameter(name = ApiConstants.INTERVAL, type = CommandType.INTEGER, required = true,
+            description = "Specify the number of days (greater than zero) to remove records that are older than those number of days from today. For example, specifying 10 would result in removing all the records created before 10 days from today")
+    private Integer interval;
+
+    public Integer getInterval() {
+        return interval;
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+
+        boolean result = _usageService.removeRawUsageRecords(this);
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
+                    "Failed to remove old raw usage records from cloud_usage table, a job is likely running at this time. Please try again after 15 mins.");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f9a8111e/api/src/org/apache/cloudstack/usage/UsageService.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/usage/UsageService.java b/api/src/org/apache/cloudstack/usage/UsageService.java
index cae37bd..2345e59 100644
--- a/api/src/org/apache/cloudstack/usage/UsageService.java
+++ b/api/src/org/apache/cloudstack/usage/UsageService.java
@@ -16,14 +16,14 @@
 // under the License.
 package org.apache.cloudstack.usage;
 
-import java.util.List;
-import java.util.TimeZone;
-
+import com.cloud.utils.Pair;
 import org.apache.cloudstack.api.command.admin.usage.GenerateUsageRecordsCmd;
 import org.apache.cloudstack.api.command.admin.usage.GetUsageRecordsCmd;
+import org.apache.cloudstack.api.command.admin.usage.RemoveRawUsageRecordsCmd;
 import org.apache.cloudstack.api.response.UsageTypeResponse;
 
-import com.cloud.utils.Pair;
+import java.util.List;
+import java.util.TimeZone;
 
 public interface UsageService {
     /**
@@ -61,6 +61,7 @@ public interface UsageService {
      */
     TimeZone getUsageTimezone();
 
-    List<UsageTypeResponse> listUsageTypes();
+    boolean removeRawUsageRecords(RemoveRawUsageRecordsCmd cmd);
 
+    List<UsageTypeResponse> listUsageTypes();
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f9a8111e/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index 36d735d..f932904 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -544,6 +544,7 @@ listOvsElements=7
 generateUsageRecords=1
 listUsageRecords=7
 listUsageTypes=1
+removeRawUsageRecords=1
 
 #### traffic monitor commands
 addTrafficMonitor=1

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f9a8111e/engine/schema/src/com/cloud/usage/dao/UsageDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/usage/dao/UsageDao.java b/engine/schema/src/com/cloud/usage/dao/UsageDao.java
index 334c9d0..f9e9d23 100644
--- a/engine/schema/src/com/cloud/usage/dao/UsageDao.java
+++ b/engine/schema/src/com/cloud/usage/dao/UsageDao.java
@@ -16,8 +16,6 @@
 // under the License.
 package com.cloud.usage.dao;
 
-import java.util.List;
-
 import com.cloud.usage.UsageVO;
 import com.cloud.user.AccountVO;
 import com.cloud.user.UserStatisticsVO;
@@ -27,6 +25,8 @@ import com.cloud.utils.db.Filter;
 import com.cloud.utils.db.GenericDao;
 import com.cloud.utils.db.SearchCriteria;
 
+import java.util.List;
+
 public interface UsageDao extends GenericDao<UsageVO, Long> {
     void deleteRecordsForAccount(Long accountId);
 
@@ -53,4 +53,6 @@ public interface UsageDao extends GenericDao<UsageVO, Long> {
     void saveVmDiskStats(List<VmDiskStatisticsVO> vmDiskStats);
 
     void saveUsageRecords(List<UsageVO> usageRecords);
+
+    void removeOldUsageRecords(int days);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f9a8111e/engine/schema/src/com/cloud/usage/dao/UsageDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/usage/dao/UsageDaoImpl.java b/engine/schema/src/com/cloud/usage/dao/UsageDaoImpl.java
index a2d38e2..93ddf9b 100644
--- a/engine/schema/src/com/cloud/usage/dao/UsageDaoImpl.java
+++ b/engine/schema/src/com/cloud/usage/dao/UsageDaoImpl.java
@@ -16,19 +16,6 @@
 // under the License.
 package com.cloud.usage.dao;
 
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.Types;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.TimeZone;
-
-import javax.ejb.Local;
-
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
 import com.cloud.usage.UsageVO;
 import com.cloud.user.AccountVO;
 import com.cloud.user.UserStatisticsVO;
@@ -40,6 +27,17 @@ import com.cloud.utils.db.GenericDaoBase;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.TransactionLegacy;
 import com.cloud.utils.exception.CloudRuntimeException;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import javax.ejb.Local;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
 
 @Component
 @Local(value = {UsageDao.class})
@@ -47,6 +45,7 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
     public static final Logger s_logger = Logger.getLogger(UsageDaoImpl.class.getName());
     private static final String DELETE_ALL = "DELETE FROM cloud_usage";
     private static final String DELETE_ALL_BY_ACCOUNTID = "DELETE FROM cloud_usage WHERE account_id = ?";
+    private static final String DELETE_ALL_BY_INTERVAL = "DELETE FROM cloud_usage WHERE end_date < DATE_SUB(CURRENT_DATE(), INTERVAL ? DAY)";
     private static final String INSERT_ACCOUNT = "INSERT INTO cloud_usage.account (id, account_name, type, domain_id, removed, cleanup_needed) VALUES (?,?,?,?,?,?)";
     private static final String INSERT_USER_STATS =
             "INSERT INTO cloud_usage.user_statistics (id, data_center_id, account_id, public_ip_address, device_id, device_type, network_id, net_bytes_received,"
@@ -451,4 +450,23 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
             throw new CloudRuntimeException(ex.getMessage());
         }
     }
+
+    @Override
+    public void removeOldUsageRecords(int days) {
+        String sql = DELETE_ALL_BY_INTERVAL;
+        TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
+        PreparedStatement pstmt = null;
+        try {
+            txn.start();
+            pstmt = txn.prepareAutoCloseStatement(sql);
+            pstmt.setLong(1, days);
+            pstmt.executeUpdate();
+            txn.commit();
+        } catch (Exception ex) {
+            txn.rollback();
+            s_logger.error("error removing old cloud_usage records for interval: " + days);
+        } finally {
+            txn.close();
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f9a8111e/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 e61a9f4..9de7f1d 100644
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -39,6 +39,7 @@ import javax.crypto.spec.SecretKeySpec;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import org.apache.cloudstack.api.command.admin.usage.RemoveRawUsageRecordsCmd;
 import org.apache.cloudstack.api.command.user.snapshot.UpdateSnapshotPolicyCmd;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.log4j.Logger;
@@ -2658,6 +2659,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         cmdList.add(DeleteTrafficTypeCmd.class);
         cmdList.add(GenerateUsageRecordsCmd.class);
         cmdList.add(GetUsageRecordsCmd.class);
+        cmdList.add(RemoveRawUsageRecordsCmd.class);
         cmdList.add(ListTrafficMonitorsCmd.class);
         cmdList.add(ListTrafficTypeImplementorsCmd.class);
         cmdList.add(ListTrafficTypesCmd.class);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f9a8111e/server/src/com/cloud/usage/UsageServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/usage/UsageServiceImpl.java b/server/src/com/cloud/usage/UsageServiceImpl.java
index f81415b..8cc40ca 100644
--- a/server/src/com/cloud/usage/UsageServiceImpl.java
+++ b/server/src/com/cloud/usage/UsageServiceImpl.java
@@ -16,56 +16,31 @@
 // under the License.
 package com.cloud.usage;
 
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.TimeZone;
-
-import javax.ejb.Local;
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-
+import com.cloud.configuration.Config;
+import com.cloud.domain.DomainVO;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.PermissionDeniedException;
 import com.cloud.host.HostVO;
 import com.cloud.host.dao.HostDao;
 import com.cloud.network.VpnUserVO;
-import com.cloud.network.dao.LoadBalancerVO;
-import com.cloud.network.dao.IPAddressVO;
 import com.cloud.network.dao.IPAddressDao;
+import com.cloud.network.dao.IPAddressVO;
 import com.cloud.network.dao.LoadBalancerDao;
+import com.cloud.network.dao.LoadBalancerVO;
 import com.cloud.network.dao.VpnUserDao;
 import com.cloud.network.rules.PortForwardingRuleVO;
 import com.cloud.network.rules.dao.PortForwardingRulesDao;
 import com.cloud.network.security.SecurityGroupVO;
 import com.cloud.network.security.dao.SecurityGroupDao;
+import com.cloud.projects.Project;
+import com.cloud.projects.ProjectManager;
 import com.cloud.storage.SnapshotVO;
 import com.cloud.storage.VMTemplateVO;
 import com.cloud.storage.VolumeVO;
 import com.cloud.storage.dao.SnapshotDao;
 import com.cloud.storage.dao.VMTemplateDao;
 import com.cloud.storage.dao.VolumeDao;
-import com.cloud.vm.VMInstanceVO;
-import com.cloud.vm.dao.VMInstanceDao;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import org.apache.cloudstack.api.command.admin.usage.GenerateUsageRecordsCmd;
-import org.apache.cloudstack.api.command.admin.usage.GetUsageRecordsCmd;
-import org.apache.cloudstack.api.response.UsageTypeResponse;
-import org.apache.cloudstack.context.CallContext;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-import org.apache.cloudstack.usage.Usage;
-import org.apache.cloudstack.usage.UsageService;
-import org.apache.cloudstack.usage.UsageTypes;
-
-import com.cloud.configuration.Config;
-import com.cloud.domain.DomainVO;
-import com.cloud.domain.dao.DomainDao;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.exception.PermissionDeniedException;
-import com.cloud.projects.Project;
-import com.cloud.projects.ProjectManager;
 import com.cloud.usage.dao.UsageDao;
 import com.cloud.usage.dao.UsageJobDao;
 import com.cloud.user.Account;
@@ -78,6 +53,29 @@ import com.cloud.utils.component.ManagerBase;
 import com.cloud.utils.db.Filter;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.TransactionLegacy;
+import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.dao.VMInstanceDao;
+import org.apache.cloudstack.api.command.admin.usage.GenerateUsageRecordsCmd;
+import org.apache.cloudstack.api.command.admin.usage.GetUsageRecordsCmd;
+import org.apache.cloudstack.api.command.admin.usage.RemoveRawUsageRecordsCmd;
+import org.apache.cloudstack.api.response.UsageTypeResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.usage.Usage;
+import org.apache.cloudstack.usage.UsageService;
+import org.apache.cloudstack.usage.UsageTypes;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
 
 @Component
 @Local(value = {UsageService.class})
@@ -375,6 +373,41 @@ public class UsageServiceImpl extends ManagerBase implements UsageService, Manag
         return _usageTimezone;
     }
 
+    @Override
+    public boolean removeRawUsageRecords(RemoveRawUsageRecordsCmd cmd) throws InvalidParameterValueException {
+        Integer interval = cmd.getInterval();
+        if (interval != null && interval > 0 ) {
+            String jobExecTime = _configDao.getValue(Config.UsageStatsJobExecTime.toString());
+            if (jobExecTime != null ) {
+                String[] segments = jobExecTime.split(":");
+                if (segments.length == 2) {
+                    String timeZoneStr = _configDao.getValue(Config.UsageExecutionTimezone.toString());
+                    if (timeZoneStr == null) {
+                        timeZoneStr = "GMT";
+                    }
+                    TimeZone tz = TimeZone.getTimeZone(timeZoneStr);
+                    Calendar cal = Calendar.getInstance(tz);
+                    cal.setTime(new Date());
+                    long curTS = cal.getTimeInMillis();
+                    cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(segments[0]));
+                    cal.set(Calendar.MINUTE, Integer.parseInt(segments[1]));
+                    cal.set(Calendar.SECOND, 0);
+                    cal.set(Calendar.MILLISECOND, 0);
+                    long execTS = cal.getTimeInMillis();
+                    s_logger.debug("Trying to remove old raw cloud_usage records older than " + interval + " day(s), current time=" + curTS + " next job execution time=" + execTS);
+                    // Let's avoid cleanup when job runs and around a 15 min interval
+                    if (Math.abs(curTS - execTS) < 15 * 60 * 1000) {
+                        return false;
+                    }
+                }
+            }
+            _usageDao.removeOldUsageRecords(interval);
+        } else {
+            throw new InvalidParameterValueException("Invalid interval value. Interval to remove cloud_usage records should be greater than 0");
+        }
+        return true;
+    }
+
     private Date computeAdjustedTime(Date initialDate, TimeZone targetTZ, boolean adjustToDayStart) {
         Calendar cal = Calendar.getInstance();
         cal.setTime(initialDate);