From c3ed426837c17eeba31c27dbbad59889b61bab5e Mon Sep 17 00:00:00 2001 From: kishan Date: Thu, 15 Dec 2011 16:44:17 +0530 Subject: [PATCH] bug 12206: Added op_user_stats_log table to store historic user stats. Network stats update thread will update aggregate bytes and log the entry in this table. Mgmt server with min id will run this job. status 12206: resolved fixed reviewed-by: Nitin --- core/src/com/cloud/user/UserStatsLogVO.java | 134 ++++++++++++++++++ .../cluster/dao/ManagementServerHostDao.java | 3 + .../dao/ManagementServerHostDaoImpl.java | 15 ++ .../DefaultComponentLibrary.java | 2 + .../VirtualNetworkApplianceManagerImpl.java | 121 +++++++++++----- .../com/cloud/user/dao/UserStatisticsDao.java | 2 +- .../cloud/user/dao/UserStatisticsDaoImpl.java | 29 ++-- .../com/cloud/user/dao/UserStatsLogDao.java | 25 ++++ .../cloud/user/dao/UserStatsLogDaoImpl.java | 30 ++++ setup/db/create-schema.sql | 13 ++ setup/db/db/schema-2214to30.sql | 11 ++ 11 files changed, 335 insertions(+), 50 deletions(-) create mode 100644 core/src/com/cloud/user/UserStatsLogVO.java create mode 100644 server/src/com/cloud/user/dao/UserStatsLogDao.java create mode 100644 server/src/com/cloud/user/dao/UserStatsLogDaoImpl.java diff --git a/core/src/com/cloud/user/UserStatsLogVO.java b/core/src/com/cloud/user/UserStatsLogVO.java new file mode 100644 index 00000000000..2112c7fa1b8 --- /dev/null +++ b/core/src/com/cloud/user/UserStatsLogVO.java @@ -0,0 +1,134 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.user; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +@Entity +@Table(name="op_user_stats_log") +public class UserStatsLogVO { + @Id + @Column(name="user_stats_id") + private long userStatsId; + + @Column(name="net_bytes_received") + private long netBytesReceived; + + @Column(name="net_bytes_sent") + private long netBytesSent; + + @Column(name="current_bytes_received") + private long currentBytesReceived; + + @Column(name="current_bytes_sent") + private long currentBytesSent; + + @Column(name="agg_bytes_received") + private long aggBytesReceived; + + @Column(name="agg_bytes_sent") + private long aggBytesSent; + + @Column(name="updated") + @Temporal(value=TemporalType.TIMESTAMP) + private Date updatedTime; + + public UserStatsLogVO(){ + } + + public UserStatsLogVO(long userStatsId, long netBytesReceived, long netBytesSent, long currentBytesReceived, long currentBytesSent, + long aggBytesReceived, long aggBytesSent, Date updatedTime) { + this.userStatsId = userStatsId; + this.netBytesReceived = netBytesReceived; + this.netBytesSent = netBytesSent; + this.currentBytesReceived = currentBytesReceived; + this.currentBytesSent = currentBytesSent; + this.aggBytesReceived = aggBytesReceived; + this.aggBytesSent = aggBytesSent; + this.updatedTime = updatedTime; + } + + public Long getUserStatsId() { + return userStatsId; + } + + public long getCurrentBytesReceived() { + return currentBytesReceived; + } + + public void setCurrentBytesReceived(long currentBytesReceived) { + this.currentBytesReceived = currentBytesReceived; + } + + public long getCurrentBytesSent() { + return currentBytesSent; + } + + public void setCurrentBytesSent(long currentBytesSent) { + this.currentBytesSent = currentBytesSent; + } + + public long getNetBytesReceived() { + return netBytesReceived; + } + + public long getNetBytesSent() { + return netBytesSent; + } + + public void setNetBytesReceived(long netBytesReceived) { + this.netBytesReceived = netBytesReceived; + } + + public void setNetBytesSent(long netBytesSent) { + this.netBytesSent = netBytesSent; + } + + public long getAggBytesReceived() { + return aggBytesReceived; + } + + public void setAggBytesReceived(long aggBytesReceived) { + this.aggBytesReceived = aggBytesReceived; + } + + public long getAggBytesSent() { + return aggBytesSent; + } + + public void setAggBytesSent(long aggBytesSent) { + this.aggBytesSent = aggBytesSent; + } + + public Date getUpdatedTime() { + return updatedTime; + } + + public void setUpdatedTime(Date updatedTime) { + this.updatedTime = updatedTime; + } + +} diff --git a/server/src/com/cloud/cluster/dao/ManagementServerHostDao.java b/server/src/com/cloud/cluster/dao/ManagementServerHostDao.java index 8b5ac4f949c..c14c385ee57 100644 --- a/server/src/com/cloud/cluster/dao/ManagementServerHostDao.java +++ b/server/src/com/cloud/cluster/dao/ManagementServerHostDao.java @@ -24,6 +24,7 @@ import java.util.List; import com.cloud.cluster.ManagementServerHost; import com.cloud.cluster.ManagementServerHost.State; import com.cloud.cluster.ManagementServerHostVO; +import com.cloud.utils.db.Filter; import com.cloud.utils.db.GenericDao; public interface ManagementServerHostDao extends GenericDao { @@ -44,4 +45,6 @@ public interface ManagementServerHostDao extends GenericDao listBy(ManagementServerHost.State...states); public List listOrphanMsids(); + + ManagementServerHostVO findOneInUpState(Filter filter); } diff --git a/server/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java b/server/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java index abc7c0687f9..4add7166f88 100644 --- a/server/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java +++ b/server/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java @@ -36,6 +36,7 @@ import com.cloud.cluster.ManagementServerHost.State; import com.cloud.cluster.ManagementServerHostVO; import com.cloud.utils.DateUtil; import com.cloud.utils.db.DB; +import com.cloud.utils.db.Filter; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @@ -258,4 +259,18 @@ public class ManagementServerHostDaoImpl extends GenericDaoBase sc = StateSearch.create(); + + sc.setParameters("state", ManagementServerHost.State.Up); + + List mshosts = listBy(sc, filter); + if(mshosts != null && mshosts.size() > 0){ + return mshosts.get(0); + } + return null; + } + } diff --git a/server/src/com/cloud/configuration/DefaultComponentLibrary.java b/server/src/com/cloud/configuration/DefaultComponentLibrary.java index 223153eed9b..32f1bd5998f 100755 --- a/server/src/com/cloud/configuration/DefaultComponentLibrary.java +++ b/server/src/com/cloud/configuration/DefaultComponentLibrary.java @@ -173,6 +173,7 @@ import com.cloud.user.dao.SSHKeyPairDaoImpl; import com.cloud.user.dao.UserAccountDaoImpl; import com.cloud.user.dao.UserDaoImpl; import com.cloud.user.dao.UserStatisticsDaoImpl; +import com.cloud.user.dao.UserStatsLogDaoImpl; import com.cloud.utils.component.Adapter; import com.cloud.utils.component.ComponentLibrary; import com.cloud.utils.component.ComponentLibraryBase; @@ -226,6 +227,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com info.addParameter("cache.size", "5000"); info.addParameter("cache.time.to.live", "300"); addDao("UserStatisticsDao", UserStatisticsDaoImpl.class); + addDao("UserStatsLogDao", UserStatsLogDaoImpl.class); addDao("FirewallRulesDao", FirewallRulesDaoImpl.class); addDao("LoadBalancerDao", LoadBalancerDaoImpl.class); addDao("NetworkRuleConfigDao", NetworkRuleConfigDaoImpl.class); diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index e1ca0873862..f862798f435 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -78,7 +78,9 @@ import com.cloud.alert.AlertManager; import com.cloud.api.commands.UpgradeRouterCmd; import com.cloud.async.AsyncJobManager; import com.cloud.capacity.dao.CapacityDao; +import com.cloud.cluster.ManagementServerHostVO; import com.cloud.cluster.ManagementServerNode; +import com.cloud.cluster.dao.ManagementServerHostDao; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.ZoneConfig; @@ -183,10 +185,12 @@ import com.cloud.user.AccountService; import com.cloud.user.User; import com.cloud.user.UserContext; import com.cloud.user.UserStatisticsVO; +import com.cloud.user.UserStatsLogVO; import com.cloud.user.UserVO; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; import com.cloud.user.dao.UserStatisticsDao; +import com.cloud.user.dao.UserStatsLogDao; import com.cloud.uservm.UserVm; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; @@ -196,6 +200,8 @@ import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.Inject; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GlobalLock; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.MacAddress; @@ -269,6 +275,8 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian @Inject CapacityDao _capacityDao = null; @Inject + UserStatsLogDao _userStatsLogDao = null; + @Inject AgentManager _agentMgr; @Inject StorageManager _storageMgr; @@ -332,7 +340,9 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian PhysicalNetworkServiceProviderDao _physicalProviderDao; @Inject VirtualRouterProviderDao _vrProviderDao; - + @Inject + ManagementServerHostDao _msHostDao; + int _routerRamSize; int _routerCpuMHz; int _retry = 2; @@ -350,7 +360,8 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian private int _usageAggregationRange = 1440; private String _usageTimeZone = "GMT"; private final long mgmtSrvrId = MacAddress.getMacAddress().toLong(); - + private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 5; // 5 seconds + ScheduledExecutorService _executor; ScheduledExecutorService _checkExecutor; ScheduledExecutorService _networkStatsUpdateExecutor; @@ -689,39 +700,39 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian public boolean start() { if (_routerStatsInterval > 0){ _executor.scheduleAtFixedRate(new NetworkUsageTask(), _routerStatsInterval, _routerStatsInterval, TimeUnit.SECONDS); - - //Schedule Network stats update task - TimeZone usageTimezone = TimeZone.getTimeZone(_usageTimeZone); - Calendar cal = Calendar.getInstance(usageTimezone); - cal.setTime(new Date()); - long endDate = 0; - int HOURLY_TIME = 60; - final int DAILY_TIME = 60 * 24; - if (_usageAggregationRange == DAILY_TIME) { - cal.roll(Calendar.DAY_OF_YEAR, false); - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - cal.roll(Calendar.DAY_OF_YEAR, true); - cal.add(Calendar.MILLISECOND, -1); - endDate = cal.getTime().getTime(); - } else if (_usageAggregationRange == HOURLY_TIME) { - cal.roll(Calendar.HOUR_OF_DAY, false); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - cal.roll(Calendar.HOUR_OF_DAY, true); - cal.add(Calendar.MILLISECOND, -1); - endDate = cal.getTime().getTime(); - } else { - endDate = cal.getTime().getTime(); - } - - _networkStatsUpdateExecutor.scheduleAtFixedRate(new NetworkStatsUpdateTask(), (endDate - System.currentTimeMillis()), (_usageAggregationRange * 60 * 1000), TimeUnit.MILLISECONDS); }else{ s_logger.debug("router.stats.interval - " + _routerStatsInterval+ " so not scheduling the router stats thread"); } + + //Schedule Network stats update task + TimeZone usageTimezone = TimeZone.getTimeZone(_usageTimeZone); + Calendar cal = Calendar.getInstance(usageTimezone); + cal.setTime(new Date()); + long endDate = 0; + int HOURLY_TIME = 60; + final int DAILY_TIME = 60 * 24; + if (_usageAggregationRange == DAILY_TIME) { + cal.roll(Calendar.DAY_OF_YEAR, false); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + cal.roll(Calendar.DAY_OF_YEAR, true); + cal.add(Calendar.MILLISECOND, -1); + endDate = cal.getTime().getTime(); + } else if (_usageAggregationRange == HOURLY_TIME) { + cal.roll(Calendar.HOUR_OF_DAY, false); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + cal.roll(Calendar.HOUR_OF_DAY, true); + cal.add(Calendar.MILLISECOND, -1); + endDate = cal.getTime().getTime(); + } else { + endDate = cal.getTime().getTime(); + } + + _networkStatsUpdateExecutor.scheduleAtFixedRate(new NetworkStatsUpdateTask(), (endDate - System.currentTimeMillis()), (_usageAggregationRange * 60 * 1000), TimeUnit.MILLISECONDS); if (_routerCheckInterval > 0) { _checkExecutor.scheduleAtFixedRate(new CheckRouterTask(), _routerCheckInterval, _routerCheckInterval, TimeUnit.SECONDS); @@ -875,15 +886,49 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian @Override public void run() { - try{ - if(_statsDao.updateAggStats()){ - s_logger.debug("Succussfully updated aggregate network stats"); - } else { - s_logger.debug("Failed to update aggregate network stats"); + GlobalLock scanLock = GlobalLock.getInternLock("network.stats"); + try { + if(scanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) { + //Check for ownership + //msHost in UP state with min id should run the job + ManagementServerHostVO msHost = _msHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L)); + if(msHost == null || (msHost.getMsid() != mgmtSrvrId)){ + s_logger.debug("Skipping aggregate network stats update"); + scanLock.unlock(); + return; + } + Transaction txn = Transaction.open(Transaction.CLOUD_DB); + try { + txn.start(); + //get all stats with delta > 0 + List updatedStats = _statsDao.listUpdatedStats(); + Date updatedTime = new Date(); + for(UserStatisticsVO stat : updatedStats){ + //update agg bytes + stat.setAggBytesReceived(stat.getCurrentBytesReceived() + stat.getNetBytesReceived()); + stat.setAggBytesSent(stat.getCurrentBytesSent() + stat.getNetBytesSent()); + _userStatsDao.update(stat.getId(), stat); + //insert into op_user_stats_log + UserStatsLogVO statsLog = new UserStatsLogVO(stat.getId(), stat.getNetBytesReceived(), stat.getNetBytesSent(), stat.getCurrentBytesReceived(), + stat.getCurrentBytesSent(), stat.getAggBytesReceived(), stat.getAggBytesSent(), updatedTime); + _userStatsLogDao.persist(statsLog); + } + s_logger.debug("Successfully updated aggregate network stats"); + txn.commit(); + } catch (Exception e){ + txn.rollback(); + s_logger.debug("Failed to update aggregate network stats", e); + } finally { + scanLock.unlock(); + txn.close(); + } } } catch (Exception e){ - s_logger.debug("Failed to update aggregate network stats", e); + s_logger.debug("Exception while trying to acquire network stats lock", e); + } finally { + scanLock.releaseRef(); } + } } diff --git a/server/src/com/cloud/user/dao/UserStatisticsDao.java b/server/src/com/cloud/user/dao/UserStatisticsDao.java index a400f736fd3..c01109c1350 100644 --- a/server/src/com/cloud/user/dao/UserStatisticsDao.java +++ b/server/src/com/cloud/user/dao/UserStatisticsDao.java @@ -33,5 +33,5 @@ public interface UserStatisticsDao extends GenericDao { List listActiveAndRecentlyDeleted(Date minRemovedDate, int startIndex, int limit); - boolean updateAggStats(); + List listUpdatedStats(); } diff --git a/server/src/com/cloud/user/dao/UserStatisticsDaoImpl.java b/server/src/com/cloud/user/dao/UserStatisticsDaoImpl.java index 298be81468e..83a4dfa199c 100644 --- a/server/src/com/cloud/user/dao/UserStatisticsDaoImpl.java +++ b/server/src/com/cloud/user/dao/UserStatisticsDaoImpl.java @@ -43,9 +43,11 @@ public class UserStatisticsDaoImpl extends GenericDaoBase= ?) " + "ORDER BY us.id"; - private static final String UPDATE_AGG_STATS = "UPDATE user_statistics set agg_bytes_received = net_bytes_received + current_bytes_received , agg_bytes_sent = net_bytes_sent + current_bytes_sent"; + private static final String UPDATED_STATS_SEARCH = "SELECT id, current_bytes_received, current_bytes_sent, net_bytes_received, net_bytes_sent, agg_bytes_received, agg_bytes_sent from user_statistics " + + "where (agg_bytes_received < net_bytes_received + current_bytes_received) OR (agg_bytes_sent < net_bytes_sent + current_bytes_sent)"; private final SearchBuilder AllFieldsSearch; - private final SearchBuilder AccountSearch; + private final SearchBuilder AccountSearch; + public UserStatisticsDaoImpl() { AccountSearch = createSearchBuilder(); @@ -113,18 +115,23 @@ public class UserStatisticsDaoImpl extends GenericDaoBase listUpdatedStats() { + List userStats = new ArrayList(); + + Transaction txn = Transaction.currentTxn(); try { - String sql = UPDATE_AGG_STATS; PreparedStatement pstmt = null; - pstmt = txn.prepareAutoCloseStatement(sql); - return pstmt.executeUpdate() > 0; + pstmt = txn.prepareAutoCloseStatement(UPDATED_STATS_SEARCH); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + userStats.add(toEntityBean(rs, false)); + } } catch (Exception ex) { - s_logger.error("error updating agg user stats", ex); + s_logger.error("error lisitng updated user stats", ex); } - return false; - } + return userStats; + } + } diff --git a/server/src/com/cloud/user/dao/UserStatsLogDao.java b/server/src/com/cloud/user/dao/UserStatsLogDao.java new file mode 100644 index 00000000000..f728e2c911c --- /dev/null +++ b/server/src/com/cloud/user/dao/UserStatsLogDao.java @@ -0,0 +1,25 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.user.dao; + +import com.cloud.user.UserStatsLogVO; +import com.cloud.utils.db.GenericDao; + +public interface UserStatsLogDao extends GenericDao { +} diff --git a/server/src/com/cloud/user/dao/UserStatsLogDaoImpl.java b/server/src/com/cloud/user/dao/UserStatsLogDaoImpl.java new file mode 100644 index 00000000000..69b1bcb842c --- /dev/null +++ b/server/src/com/cloud/user/dao/UserStatsLogDaoImpl.java @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.user.dao; + +import javax.ejb.Local; + +import com.cloud.user.UserStatsLogVO; +import com.cloud.utils.db.GenericDaoBase; + +@Local(value={UserStatsLogDao.class}) +public class UserStatsLogDaoImpl extends GenericDaoBase implements UserStatsLogDao { + public UserStatsLogDaoImpl(){ + } +} diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index f0713158e2b..8c2194fefa2 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -2013,4 +2013,17 @@ CREATE TABLE `cloud`.`virtual_router_providers` ( CONSTRAINT `uc_virtual_router_providers__uuid` UNIQUE (`uuid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `cloud`.`op_user_stats_log` ( + `user_stats_id` bigint unsigned NOT NULL, + `net_bytes_received` bigint unsigned NOT NULL default '0', + `net_bytes_sent` bigint unsigned NOT NULL default '0', + `current_bytes_received` bigint unsigned NOT NULL default '0', + `current_bytes_sent` bigint unsigned NOT NULL default '0', + `agg_bytes_received` bigint unsigned NOT NULL default '0', + `agg_bytes_sent` bigint unsigned NOT NULL default '0', + `updated` datetime COMMENT 'stats update timestamp', + UNIQUE KEY (`user_stats_id`, `updated`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + SET foreign_key_checks = 1; diff --git a/setup/db/db/schema-2214to30.sql b/setup/db/db/schema-2214to30.sql index 5c8b22a68ac..6ea206197c5 100755 --- a/setup/db/db/schema-2214to30.sql +++ b/setup/db/db/schema-2214to30.sql @@ -485,3 +485,14 @@ ALTER TABLE `cloud`.`networks` ADD COLUMN `restart_required` int(1) unsigned NOT DELETE FROM `cloud`.`configuration` where name='cmd.wait'; UPDATE `cloud`.`configuration` set value='true' where name='firewall.rule.ui.enabled'; +CREATE TABLE `cloud`.`op_user_stats_log` ( + `user_stats_id` bigint unsigned NOT NULL, + `net_bytes_received` bigint unsigned NOT NULL default '0', + `net_bytes_sent` bigint unsigned NOT NULL default '0', + `current_bytes_received` bigint unsigned NOT NULL default '0', + `current_bytes_sent` bigint unsigned NOT NULL default '0', + `agg_bytes_received` bigint unsigned NOT NULL default '0', + `agg_bytes_sent` bigint unsigned NOT NULL default '0', + `updated` datetime COMMENT 'stats update timestamp', + UNIQUE KEY (`user_stats_id`, `updated`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8;