// Copyright 2012 Citrix Systems, Inc. Licensed under the // Apache License, Version 2.0 (the "License"); you may not use this // file except in compliance with the License. Citrix Systems, Inc. // reserves all rights not expressly granted by 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. // // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.server; 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 com.cloud.api.commands.GenerateUsageRecordsCmd; import com.cloud.api.commands.GetUsageRecordsCmd; import com.cloud.domain.dao.DomainDao; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.projects.Project; import com.cloud.server.api.response.UsageTypeResponse; import com.cloud.usage.UsageJobVO; import com.cloud.usage.UsageTypes; import com.cloud.usage.UsageVO; import com.cloud.usage.dao.UsageDao; import com.cloud.usage.dao.UsageJobDao; import com.cloud.user.Account; import com.cloud.user.AccountVO; import com.cloud.user.UserContext; import com.cloud.user.dao.AccountDao; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.db.Filter; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; public class ManagementServerExtImpl extends ManagementServerImpl implements ManagementServerExt { private final AccountDao _accountDao; private final DomainDao _domainDao; private final UsageDao _usageDao; private final UsageJobDao _usageJobDao; private final TimeZone _usageTimezone; protected ManagementServerExtImpl() { super(); ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name); _accountDao = locator.getDao(AccountDao.class); _domainDao = locator.getDao(DomainDao.class); _usageDao = locator.getDao(UsageDao.class); _usageJobDao = locator.getDao(UsageJobDao.class); Map<String, String> configs = getConfigs(); String timeZoneStr = configs.get("usage.aggregation.timezone"); if (timeZoneStr == null) { timeZoneStr = "GMT"; } _usageTimezone = TimeZone.getTimeZone(timeZoneStr); } @Override public boolean generateUsageRecords(GenerateUsageRecordsCmd cmd) { Transaction txn = Transaction.open(Transaction.USAGE_DB); try { UsageJobVO immediateJob = _usageJobDao.getNextImmediateJob(); if (immediateJob == null) { UsageJobVO job = _usageJobDao.getLastJob(); String host = null; int pid = 0; if (job != null) { host = job.getHost(); pid = ((job.getPid() == null) ? 0 : job.getPid().intValue()); } _usageJobDao.createNewJob(host, pid, UsageJobVO.JOB_TYPE_SINGLE); } } finally { txn.close(); // switch back to VMOPS_DB Transaction swap = Transaction.open(Transaction.CLOUD_DB); swap.close(); } return true; } @Override public List<UsageVO> getUsageRecords(GetUsageRecordsCmd cmd) { Long accountId = cmd.getAccountId(); Long domainId = cmd.getDomainId(); String accountName = cmd.getAccountName(); Account userAccount = null; Account caller = (Account)UserContext.current().getCaller(); Long usageType = cmd.getUsageType(); Long projectId = cmd.getProjectId(); if (projectId != null) { if (accountId != null) { throw new InvalidParameterValueException("Projectid and accountId can't be specified together"); } Project project = _projectMgr.getProject(projectId); if (project == null) { throw new InvalidParameterValueException("Unable to find project by id " + projectId); } accountId = project.getProjectAccountId(); } //if accountId is not specified, use accountName and domainId if ((accountId == null) && (accountName != null) && (domainId != null)) { if (_domainDao.isChildDomain(caller.getDomainId(), domainId)) { Filter filter = new Filter(AccountVO.class, "id", Boolean.FALSE, null, null); List<AccountVO> accounts = _accountDao.listAccounts(accountName, domainId, filter); if(accounts.size() > 0){ userAccount = accounts.get(0); } if (userAccount != null) { accountId = userAccount.getId(); } else { throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId); } } else { throw new PermissionDeniedException("Invalid Domain Id or Account"); } } boolean isAdmin = false; //If accountId couldn't be found using accountName and domainId, get it from userContext if(accountId == null){ accountId = caller.getId(); //List records for all the accounts if the caller account is of type admin. //If account_id or account_name is explicitly mentioned, list records for the specified account only even if the caller is of type admin if(caller.getType() == Account.ACCOUNT_TYPE_ADMIN){ isAdmin = true; } s_logger.debug("Account details not available. Using userContext accountId: " + accountId); } Date startDate = cmd.getStartDate(); Date endDate = cmd.getEndDate(); if(startDate.after(endDate)){ throw new InvalidParameterValueException("Incorrect Date Range. Start date: "+startDate+" is after end date:"+endDate); } TimeZone usageTZ = getUsageTimezone(); Date adjustedStartDate = computeAdjustedTime(startDate, usageTZ, true); Date adjustedEndDate = computeAdjustedTime(endDate, usageTZ, false); if (s_logger.isDebugEnabled()) { s_logger.debug("getting usage records for account: " + accountId + ", domainId: " + domainId + ", between " + startDate + " and " + endDate + ", using pageSize: " + cmd.getPageSizeVal() + " and startIndex: " + cmd.getStartIndex()); } Filter usageFilter = new Filter(UsageVO.class, "startDate", false, cmd.getStartIndex(), cmd.getPageSizeVal()); SearchCriteria<UsageVO> sc = _usageDao.createSearchCriteria(); if (accountId != -1 && accountId != Account.ACCOUNT_ID_SYSTEM && !isAdmin) { sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId); } if (domainId != null) { sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); } if (usageType != null) { sc.addAnd("usageType", SearchCriteria.Op.EQ, usageType); } if ((adjustedStartDate != null) && (adjustedEndDate != null) && adjustedStartDate.before(adjustedEndDate)) { sc.addAnd("startDate", SearchCriteria.Op.BETWEEN, adjustedStartDate, adjustedEndDate); sc.addAnd("endDate", SearchCriteria.Op.BETWEEN, adjustedStartDate, adjustedEndDate); } else { return new ArrayList<UsageVO>(); // return an empty list if we fail to validate the dates } List<UsageVO> usageRecords = null; Transaction txn = Transaction.open(Transaction.USAGE_DB); try { usageRecords = _usageDao.searchAllRecords(sc, usageFilter); } finally { txn.close(); // switch back to VMOPS_DB Transaction swap = Transaction.open(Transaction.CLOUD_DB); swap.close(); } // now that we are done with the records, update the command with the correct timezone so it can write the proper response cmd.setUsageTimezone(getUsageTimezone()); return usageRecords; } @Override public TimeZone getUsageTimezone() { return _usageTimezone; } @Override public String[] getApiConfig() { return new String[] { "commands.properties", "commands-ext.properties" }; } private Date computeAdjustedTime(Date initialDate, TimeZone targetTZ, boolean adjustToDayStart) { Calendar cal = Calendar.getInstance(); cal.setTime(initialDate); TimeZone localTZ = cal.getTimeZone(); int timezoneOffset = cal.get(Calendar.ZONE_OFFSET); if (localTZ.inDaylightTime(initialDate)) { timezoneOffset += (60 * 60 * 1000); } cal.add(Calendar.MILLISECOND, timezoneOffset); Date newTime = cal.getTime(); Calendar calTS = Calendar.getInstance(targetTZ); calTS.setTime(newTime); timezoneOffset = calTS.get(Calendar.ZONE_OFFSET); if (targetTZ.inDaylightTime(initialDate)) { timezoneOffset += (60 * 60 * 1000); } calTS.add(Calendar.MILLISECOND, -1*timezoneOffset); if (adjustToDayStart) { calTS.set(Calendar.HOUR_OF_DAY, 0); calTS.set(Calendar.MINUTE, 0); calTS.set(Calendar.SECOND, 0); calTS.set(Calendar.MILLISECOND, 0); } else { calTS.set(Calendar.HOUR_OF_DAY, 23); calTS.set(Calendar.MINUTE, 59); calTS.set(Calendar.SECOND, 59); calTS.set(Calendar.MILLISECOND, 999); } return calTS.getTime(); } @Override public List<UsageTypeResponse> listUsageTypes() { return UsageTypes.listUsageTypes(); } }