cloudstack/server/src/com/cloud/server/ManagementServerImpl.java

5652 lines
240 KiB
Java
Executable File

/**
* 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 <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.server;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
import com.cloud.agent.api.proxy.UpdateCertificateCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.alert.Alert;
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.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.CreateDomainCmd;
import com.cloud.api.commands.DeleteDomainCmd;
import com.cloud.api.commands.DeletePreallocatedLunCmd;
import com.cloud.api.commands.DeployVMCmd;
import com.cloud.api.commands.DeployVm2Cmd;
import com.cloud.api.commands.ExtractVolumeCmd;
import com.cloud.api.commands.GetCloudIdentifierCmd;
import com.cloud.api.commands.ListAccountsCmd;
import com.cloud.api.commands.ListAlertsCmd;
import com.cloud.api.commands.ListAsyncJobsCmd;
import com.cloud.api.commands.ListCapabilitiesCmd;
import com.cloud.api.commands.ListCapacityCmd;
import com.cloud.api.commands.ListCfgsByCmd;
import com.cloud.api.commands.ListClustersCmd;
import com.cloud.api.commands.ListDiskOfferingsCmd;
import com.cloud.api.commands.ListDomainChildrenCmd;
import com.cloud.api.commands.ListDomainsCmd;
import com.cloud.api.commands.ListEventsCmd;
import com.cloud.api.commands.ListGuestOsCategoriesCmd;
import com.cloud.api.commands.ListGuestOsCmd;
import com.cloud.api.commands.ListHostsCmd;
import com.cloud.api.commands.ListHypervisorsCmd;
import com.cloud.api.commands.ListIsosCmd;
import com.cloud.api.commands.ListPodsByCmd;
import com.cloud.api.commands.ListPreallocatedLunsCmd;
import com.cloud.api.commands.ListPublicIpAddressesCmd;
import com.cloud.api.commands.ListRemoteAccessVpnsCmd;
import com.cloud.api.commands.ListRoutersCmd;
import com.cloud.api.commands.ListServiceOfferingsCmd;
import com.cloud.api.commands.ListStoragePoolsCmd;
import com.cloud.api.commands.ListSystemVMsCmd;
import com.cloud.api.commands.ListTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.ListTemplatesCmd;
import com.cloud.api.commands.ListUsersCmd;
import com.cloud.api.commands.ListVMGroupsCmd;
import com.cloud.api.commands.ListVMsCmd;
import com.cloud.api.commands.ListVlanIpRangesCmd;
import com.cloud.api.commands.ListVolumesCmd;
import com.cloud.api.commands.ListVpnUsersCmd;
import com.cloud.api.commands.ListZonesByCmd;
import com.cloud.api.commands.RebootSystemVmCmd;
import com.cloud.api.commands.RegisterCmd;
import com.cloud.api.commands.RegisterPreallocatedLunCmd;
import com.cloud.api.commands.StartSystemVMCmd;
import com.cloud.api.commands.StopSystemVmCmd;
import com.cloud.api.commands.UpdateDomainCmd;
import com.cloud.api.commands.UpdateIsoCmd;
import com.cloud.api.commands.UpdateIsoPermissionsCmd;
import com.cloud.api.commands.UpdateTemplateCmd;
import com.cloud.api.commands.UpdateTemplateOrIsoCmd;
import com.cloud.api.commands.UpdateTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.UpdateTemplatePermissionsCmd;
import com.cloud.api.commands.UpdateVMGroupCmd;
import com.cloud.api.commands.UploadCustomCertificateCmd;
import com.cloud.api.response.ExtractResponse;
import com.cloud.async.AsyncJobExecutor;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobResult;
import com.cloud.async.AsyncJobVO;
import com.cloud.async.BaseAsyncJobExecutor;
import com.cloud.async.dao.AsyncJobDao;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.certificate.CertificateVO;
import com.cloud.certificate.dao.CertificateDao;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.ConfigurationVO;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.configuration.dao.ResourceLimitDao;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.AccountVlanMapVO;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterIpAddressVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DataCenterIpAddressDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.Event;
import com.cloud.event.EventTypes;
import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.CloudAuthenticationException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientStorageCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ManagementServerException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.info.ConsoleProxyInfo;
import com.cloud.network.IPAddressVO;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
import com.cloud.network.RemoteAccessVpnVO;
import com.cloud.network.VpnUserVO;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.RemoteAccessVpnDao;
import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.security.NetworkGroupManager;
import com.cloud.network.security.NetworkGroupVO;
import com.cloud.network.security.dao.NetworkGroupDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
import com.cloud.server.auth.UserAuthenticator;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.GuestOSCategoryVO;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.LaunchPermissionVO;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.Upload;
import com.cloud.storage.Upload.Mode;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeStats;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.LaunchPermissionDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.UploadDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.preallocatedlun.PreallocatedLunVO;
import com.cloud.storage.preallocatedlun.dao.PreallocatedLunDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.upload.UploadMonitor;
import com.cloud.template.TemplateManager;
import com.cloud.template.VirtualMachineTemplate.TemplateFilter;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.UserAccountVO;
import com.cloud.user.UserContext;
import com.cloud.user.UserStatisticsVO;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserAccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.EnumUtils;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.PasswordGenerator;
import com.cloud.utils.component.Adapters;
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.JoinBuilder;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.net.MacAddress;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.InstanceGroupVMMapVO;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.NicVO;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.State;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmService;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.InstanceGroupDao;
import com.cloud.vm.dao.InstanceGroupVMMapDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
public class ManagementServerImpl implements ManagementServer {
public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName());
private final AccountManager _accountMgr;
private final AgentManager _agentMgr;
private final ConfigurationManager _configMgr;
private final NetworkGroupDao _networkSecurityGroupDao;
private final IPAddressDao _publicIpAddressDao;
private final DataCenterIpAddressDao _privateIpAddressDao;
private final DomainRouterDao _routerDao;
private final ConsoleProxyDao _consoleProxyDao;
private final ClusterDao _clusterDao;
private final SecondaryStorageVmDao _secStorageVmDao;
private final EventDao _eventDao;
private final DataCenterDao _dcDao;
private final VlanDao _vlanDao;
private final AccountVlanMapDao _accountVlanMapDao;
private final PodVlanMapDao _podVlanMapDao;
private final HostDao _hostDao;
private final UserDao _userDao;
private final UserVmDao _userVmDao;
private final ConfigurationDao _configDao;
private final NetworkManager _networkMgr;
private final UserVmManager _vmMgr;
private final ConsoleProxyManager _consoleProxyMgr;
private final SecondaryStorageVmManager _secStorageVmMgr;
private final ServiceOfferingDao _offeringsDao;
private final DiskOfferingDao _diskOfferingDao;
private final VMTemplateDao _templateDao;
private final LaunchPermissionDao _launchPermissionDao;
private final DomainDao _domainDao;
private final AccountDao _accountDao;
private final ResourceLimitDao _resourceLimitDao;
private final UserAccountDao _userAccountDao;
private final AlertDao _alertDao;
private final CapacityDao _capacityDao;
private final GuestOSDao _guestOSDao;
private final GuestOSCategoryDao _guestOSCategoryDao;
private final StoragePoolDao _poolDao;
private final StoragePoolHostDao _poolHostDao;
private final StorageManager _storageMgr;
private final UserVmDao _vmDao;
private final NetworkDao _networkDao;
private final NicDao _nicDao;
private final Adapters<UserAuthenticator> _userAuthenticators;
private final HostPodDao _hostPodDao;
private final UserStatisticsDao _userStatsDao;
private final VMInstanceDao _vmInstanceDao;
private final VolumeDao _volumeDao;
private final AlertManager _alertMgr;
private final AsyncJobDao _jobDao;
private final AsyncJobManager _asyncMgr;
private final TemplateManager _tmpltMgr;
private final NetworkGroupManager _networkGroupMgr;
private final int _purgeDelay;
private final boolean _directAttachNetworkExternalIpAllocator;
private final PreallocatedLunDao _lunDao;
private final InstanceGroupDao _vmGroupDao;
private final InstanceGroupVMMapDao _groupVMMapDao;
private final UploadMonitor _uploadMonitor;
private final UploadDao _uploadDao;
private final CertificateDao _certDao;
private final RemoteAccessVpnDao _remoteAccessVpnDao;
private final VpnUserDao _vpnUsersDao;
@Inject private UserVmService _userVmService;
private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AccountChecker"));
private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker"));
private final StatsCollector _statsCollector;
private final Map<String, String> _configs;
private String _domain;
private final int _routerRamSize;
private final int _proxyRamSize;
private final int _ssRamSize;
private int _maxVolumeSizeInGb;
private boolean _useNewNetworking = false;
private final Map<String, Boolean> _availableIdsMap;
private boolean _networkGroupsEnabled = false;
private boolean _isHypervisorSnapshotCapable = false;
private String _hashKey = null;
protected ManagementServerImpl() {
ComponentLocator locator = ComponentLocator.getLocator(Name);
_lunDao = locator.getDao(PreallocatedLunDao.class);
_configDao = locator.getDao(ConfigurationDao.class);
_routerDao = locator.getDao(DomainRouterDao.class);
_eventDao = locator.getDao(EventDao.class);
_dcDao = locator.getDao(DataCenterDao.class);
_vlanDao = locator.getDao(VlanDao.class);
_accountVlanMapDao = locator.getDao(AccountVlanMapDao.class);
_podVlanMapDao = locator.getDao(PodVlanMapDao.class);
_hostDao = locator.getDao(HostDao.class);
_hostPodDao = locator.getDao(HostPodDao.class);
_jobDao = locator.getDao(AsyncJobDao.class);
_clusterDao = locator.getDao(ClusterDao.class);
_networkDao = locator.getDao(NetworkDao.class);
_nicDao = locator.getDao(NicDao.class);
_accountMgr = locator.getManager(AccountManager.class);
_agentMgr = locator.getManager(AgentManager.class);
_configMgr = locator.getManager(ConfigurationManager.class);
_networkMgr = locator.getManager(NetworkManager.class);
_vmMgr = locator.getManager(UserVmManager.class);
_consoleProxyMgr = locator.getManager(ConsoleProxyManager.class);
_secStorageVmMgr = locator.getManager(SecondaryStorageVmManager.class);
_storageMgr = locator.getManager(StorageManager.class);
_networkSecurityGroupDao = locator.getDao(NetworkGroupDao.class);
_publicIpAddressDao = locator.getDao(IPAddressDao.class);
_privateIpAddressDao = locator.getDao(DataCenterIpAddressDao.class);
_consoleProxyDao = locator.getDao(ConsoleProxyDao.class);
_secStorageVmDao = locator.getDao(SecondaryStorageVmDao.class);
_userDao = locator.getDao(UserDao.class);
_userVmDao = locator.getDao(UserVmDao.class);
_offeringsDao = locator.getDao(ServiceOfferingDao.class);
_diskOfferingDao = locator.getDao(DiskOfferingDao.class);
_templateDao = locator.getDao(VMTemplateDao.class);
_launchPermissionDao = locator.getDao(LaunchPermissionDao.class);
_domainDao = locator.getDao(DomainDao.class);
_accountDao = locator.getDao(AccountDao.class);
_resourceLimitDao = locator.getDao(ResourceLimitDao.class);
_userAccountDao = locator.getDao(UserAccountDao.class);
_alertDao = locator.getDao(AlertDao.class);
_capacityDao = locator.getDao(CapacityDao.class);
_guestOSDao = locator.getDao(GuestOSDao.class);
_guestOSCategoryDao = locator.getDao(GuestOSCategoryDao.class);
_poolDao = locator.getDao(StoragePoolDao.class);
_poolHostDao = locator.getDao(StoragePoolHostDao.class);
_vmDao = locator.getDao(UserVmDao.class);
_vmGroupDao = locator.getDao(InstanceGroupDao.class);
_groupVMMapDao = locator.getDao(InstanceGroupVMMapDao.class);
_uploadDao = locator.getDao(UploadDao.class);
_certDao = locator.getDao(CertificateDao.class);
_remoteAccessVpnDao = locator.getDao(RemoteAccessVpnDao.class);
_vpnUsersDao = locator.getDao(VpnUserDao.class);
_configs = _configDao.getConfiguration();
_userStatsDao = locator.getDao(UserStatisticsDao.class);
_vmInstanceDao = locator.getDao(VMInstanceDao.class);
_volumeDao = locator.getDao(VolumeDao.class);
_alertMgr = locator.getManager(AlertManager.class);
_asyncMgr = locator.getManager(AsyncJobManager.class);
_tmpltMgr = locator.getManager(TemplateManager.class);
_networkGroupMgr = locator.getManager(NetworkGroupManager.class);
_uploadMonitor = locator.getManager(UploadMonitor.class);
_userAuthenticators = locator.getAdapters(UserAuthenticator.class);
if (_userAuthenticators == null || !_userAuthenticators.isSet()) {
s_logger.error("Unable to find an user authenticator.");
}
_domain = _configs.get("domain");
if (_domain == null) {
_domain = ".myvm.com";
}
if (!_domain.startsWith(".")) {
_domain = "." + _domain;
}
String value = _configs.get("account.cleanup.interval");
int cleanup = NumbersUtil.parseInt(value, 60 * 60 * 24); // 1 hour.
// Parse the max number of UserVMs and public IPs from server-setup.xml,
// and set them in the right places
_routerRamSize = NumbersUtil.parseInt(_configs.get("router.ram.size"),NetworkManager.DEFAULT_ROUTER_VM_RAMSIZE);
_proxyRamSize = NumbersUtil.parseInt(_configs.get("consoleproxy.ram.size"), ConsoleProxyManager.DEFAULT_PROXY_VM_RAMSIZE);
_ssRamSize = NumbersUtil.parseInt(_configs.get("secstorage.ram.size"), SecondaryStorageVmManager.DEFAULT_SS_VM_RAMSIZE);
_directAttachNetworkExternalIpAllocator =
Boolean.parseBoolean(_configs.get("direct.attach.network.externalIpAllocator.enabled"));
_statsCollector = StatsCollector.getInstance(_configs);
_executor.scheduleAtFixedRate(new AccountCleanupTask(), cleanup, cleanup, TimeUnit.SECONDS);
_purgeDelay = NumbersUtil.parseInt(_configs.get("event.purge.delay"), 0);
if(_purgeDelay != 0){
_eventExecutor.scheduleAtFixedRate(new EventPurgeTask(), cleanup, cleanup, TimeUnit.SECONDS);
}
String[] availableIds = TimeZone.getAvailableIDs();
_availableIdsMap = new HashMap<String, Boolean>(availableIds.length);
for (String id: availableIds) {
_availableIdsMap.put(id, true);
}
String enabled =_configDao.getValue("direct.attach.network.groups.enabled");
if ("true".equalsIgnoreCase(enabled)) {
_networkGroupsEnabled = true;
}
String maxVolumeSizeInGbString = _configDao.getValue("max.volume.size.gb");
int maxVolumeSizeGb = NumbersUtil.parseInt(maxVolumeSizeInGbString, (2000));//2000 gb
_maxVolumeSizeInGb = maxVolumeSizeGb;
_useNewNetworking = Boolean.parseBoolean(_configs.get("use.new.networking"));
}
protected Map<String, String> getConfigs() {
return _configs;
}
@Override
public StorageStats getStorageStatistics(long hostId) {
return _statsCollector.getStorageStats(hostId);
}
@Override
public PreallocatedLunVO registerPreallocatedLun(RegisterPreallocatedLunCmd cmd) {
Long zoneId = cmd.getZoneId();
String portal = cmd.getPortal();
String targetIqn = cmd.getTargetIqn();
Integer lun = cmd.getLun();
Long size = cmd.getDiskSize();
String t = cmd.getTags();
String[] tags = null;
if (t != null) {
tags = t.split(",");
for (int i = 0; i < tags.length; i++) {
tags[i] = tags[i].trim();
}
} else {
tags = new String[0];
}
PreallocatedLunVO vo = new PreallocatedLunVO(zoneId, portal, targetIqn, lun, size);
return _lunDao.persist(vo, tags);
}
@Override
public boolean unregisterPreallocatedLun(DeletePreallocatedLunCmd cmd) throws IllegalArgumentException {
Long id = cmd.getId();
PreallocatedLunVO lun = null;
if ((lun = _lunDao.findById(id)) == null) {
throw new IllegalArgumentException("Unable to find a LUN with ID " + id);
}
if (lun.getTaken() != null) {
throw new IllegalArgumentException("The LUN is currently in use and cannot be deleted.");
}
return _lunDao.delete(id);
}
@Override
public VolumeStats[] getVolumeStatistics(long[] volIds) {
return _statsCollector.getVolumeStats(volIds);
}
@Override
public String updateAdminPassword(long userId, String oldPassword, String newPassword) {
// String old = StringToMD5(oldPassword);
// User user = getUser(userId);
// if (old.equals(user.getPassword())) {
UserVO userVO = _userDao.createForUpdate(userId);
userVO.setPassword(StringToMD5(newPassword));
_userDao.update(userId, userVO);
return newPassword;
// } else {
// return null;
// }
}
private String StringToMD5(String string) {
MessageDigest md5;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new CloudRuntimeException("Error", e);
}
md5.reset();
BigInteger pwInt = new BigInteger(1, md5.digest(string.getBytes()));
// make sure our MD5 hash value is 32 digits long...
StringBuffer sb = new StringBuffer();
String pwStr = pwInt.toString(16);
int padding = 32 - pwStr.length();
for (int i = 0; i < padding; i++) {
sb.append('0');
}
sb.append(pwStr);
return sb.toString();
}
@Override
public User getUser(long userId) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Retrieiving user with id: " + userId);
}
UserVO user = _userDao.getUser(userId);
if (user == null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Unable to find user with id " + userId);
}
return null;
}
return user;
}
@Override
public User getUser(long userId, boolean active) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Retrieiving user with id: " + userId + " and active = " + active);
}
if (active) {
return _userDao.getUser(userId);
} else {
return _userDao.findById(userId);
}
}
@Override
public UserAccount getUserAccount(String username, Long domainId) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Retrieiving user: " + username + " in domain " + domainId);
}
UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
if (userAccount == null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Unable to find user with name " + username + " in domain " + domainId);
}
return null;
}
return userAccount;
}
private UserAccount getUserAccount(String username, String password, Long domainId) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Attempting to log in user: " + username + " in domain " + domainId);
}
UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
if (userAccount == null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Unable to find user with name " + username + " in domain " + domainId);
}
return null;
}
if (!userAccount.getState().equals("enabled") || !userAccount.getAccountState().equals("enabled")) {
if (s_logger.isInfoEnabled()) {
s_logger.info("user " + username + " in domain " + domainId + " is disabled/locked (or account is disabled/locked), returning null");
}
throw new CloudAuthenticationException("user " + username + " in domain " + domainId + " is disabled/locked (or account is disabled/locked)");
//return null;
}
// We only use the first adapter even if multiple have been
// configured
Enumeration<UserAuthenticator> en = _userAuthenticators.enumeration();
UserAuthenticator authenticator = en.nextElement();
boolean authenticated = authenticator.authenticate(username, password, domainId);
if (authenticated) {
return userAccount;
} else {
return null;
}
}
@Override
public Pair<User, Account> findUserByApiKey(String apiKey) {
return _accountDao.findUserAccountByApiKey(apiKey);
}
@Override
public Account getAccount(long accountId) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Retrieiving account with id: " + accountId);
}
AccountVO account = _accountDao.findById(Long.valueOf(accountId));
if (account == null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Unable to find account with id " + accountId);
}
return null;
}
return account;
}
@Override
public String[] createApiKeyAndSecretKey(RegisterCmd cmd) {
Long userId = cmd.getId();
User user = _userDao.findById(userId);
if (user == null) {
throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find user for id : " + userId);
}
// generate both an api key and a secret key, update the user table with the keys, return the keys to the user
String[] keys = new String[2];
keys[0] = createApiKey(userId);
keys[1] = createSecretKey(userId);
return keys;
}
private String createApiKey(Long userId) {
User user = findUserById(userId);
try {
UserVO updatedUser = _userDao.createForUpdate();
String encodedKey = null;
Pair<User, Account> userAcct = null;
int retryLimit = 10;
do {
// FIXME: what algorithm should we use for API keys?
KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
SecretKey key = generator.generateKey();
encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
userAcct = _accountDao.findUserAccountByApiKey(encodedKey);
retryLimit--;
} while ((userAcct != null) && (retryLimit >= 0));
if (userAcct != null) {
return null;
}
updatedUser.setApiKey(encodedKey);
_userDao.update(user.getId(), updatedUser);
return encodedKey;
} catch (NoSuchAlgorithmException ex) {
s_logger.error("error generating secret key for user: " + user.getUsername(), ex);
}
return null;
}
private String createSecretKey(Long userId) {
User user = findUserById(userId);
try {
UserVO updatedUser = _userDao.createForUpdate();
String encodedKey = null;
int retryLimit = 10;
UserVO userBySecretKey = null;
do {
KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
SecretKey key = generator.generateKey();
encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
userBySecretKey = _userDao.findUserBySecretKey(encodedKey);
retryLimit--;
} while ((userBySecretKey != null) && (retryLimit >= 0));
if (userBySecretKey != null) {
return null;
}
updatedUser.setSecretKey(encodedKey);
_userDao.update(user.getId(), updatedUser);
return encodedKey;
} catch (NoSuchAlgorithmException ex) {
s_logger.error("error generating secret key for user: " + user.getUsername(), ex);
}
return null;
}
@Override
public List<IPAddressVO> listPublicIpAddressesBy(Long accountId, boolean allocatedOnly, Long zoneId, Long vlanDbId) {
SearchCriteria<IPAddressVO> sc = _publicIpAddressDao.createSearchCriteria();
if (accountId != null) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
}
if (zoneId != null) {
sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
}
if (vlanDbId != null) {
sc.addAnd("vlanDbId", SearchCriteria.Op.EQ, vlanDbId);
}
if (allocatedOnly) {
sc.addAnd("allocated", SearchCriteria.Op.NNULL);
}
return _publicIpAddressDao.search(sc, null);
}
@Override
public List<DataCenterIpAddressVO> listPrivateIpAddressesBy(Long podId, Long zoneId) {
if (podId != null && zoneId != null) {
return _privateIpAddressDao.listByPodIdDcId(podId.longValue(), zoneId.longValue());
} else {
return new ArrayList<DataCenterIpAddressVO>();
}
}
@Override
public String generateRandomPassword() {
return PasswordGenerator.generateRandomPassword(6);
}
@Override
public boolean attachISOToVM(long vmId, long userId, long isoId, boolean attach, long startEventId) {
UserVmVO vm = _userVmDao.findById(vmId);
VMTemplateVO iso = _templateDao.findById(isoId);
if(attach){
EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_ATTACH, "Attaching ISO: "+isoId+" to Vm: "+vmId, startEventId);
} else {
EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_DETACH, "Detaching ISO: "+isoId+" from Vm: "+vmId, startEventId);
}
boolean success = _vmMgr.attachISOToVM(vmId, isoId, attach);
if (success) {
if (attach) {
vm.setIsoId(iso.getId());
} else {
vm.setIsoId(null);
}
_userVmDao.update(vmId, vm);
if (attach) {
EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_ATTACH, "Successfully attached ISO: " + iso.getName() + " to VM with ID: " + vmId,
null, startEventId);
} else {
EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_DETACH, "Successfully detached ISO from VM with ID: " + vmId, null, startEventId);
}
} else {
if (attach) {
EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_ATTACH, "Failed to attach ISO: " + iso.getName() + " to VM with ID: " + vmId, null, startEventId);
} else {
EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_DETACH, "Failed to detach ISO from VM with ID: " + vmId, null, startEventId);
}
}
return success;
}
private boolean validPassword(String password) {
for (int i = 0; i < password.length(); i++) {
if (password.charAt(i) == ' ') {
return false;
}
}
return true;
}
private UserVm deployVirtualMachineImpl(long userId, long accountId, long dataCenterId, long serviceOfferingId, VMTemplateVO template, Long diskOfferingId,
String domain, String password, String displayName, String group, String userData, String [] networkGroups, long startEventId, long size) throws ResourceAllocationException,
InsufficientStorageCapacityException, ExecutionException, StorageUnavailableException, ConcurrentOperationException {
EventUtils.saveStartedEvent(userId, accountId, EventTypes.EVENT_VM_CREATE, "Deploying Vm", startEventId);
AccountVO account = _accountDao.findById(accountId);
DataCenterVO dc = _dcDao.findById(dataCenterId);
ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
// Make sure a valid template ID was specified
if (template == null) {
throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
}
long templateId = template.getId();
byte [] decodedUserData = null;
if (userData != null) {
if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
throw new InvalidParameterValueException("User data is too long");
}
decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
throw new InvalidParameterValueException("User data is too long");
}
}
boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
// TODO: Checks such as is the user allowed to use the template and purchase the service offering id.
if (domain == null) {
domain = "v" + Long.toHexString(accountId) + _domain;
}
// Check that the password was passed in and is valid
if (!template.getEnablePassword()) {
password = "saved_password";
}
if (password == null || password.equals("") || (!validPassword(password))) {
throw new InvalidParameterValueException("A valid password for this virtual machine was not provided.");
}
List<NetworkGroupVO> networkGroupVOs = new ArrayList<NetworkGroupVO>();
if (networkGroups != null) {
for (String groupName: networkGroups) {
NetworkGroupVO networkGroupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
if (networkGroupVO == null) {
throw new InvalidParameterValueException("Network Group " + groupName + " does not exist");
}
networkGroupVOs.add(networkGroupVO);
}
}
UserStatisticsVO stats = _userStatsDao.findBy(account.getId(), dataCenterId);
if (stats == null) {
stats = new UserStatisticsVO(account.getId(), dataCenterId);
_userStatsDao.persist(stats);
}
Long vmId = _vmDao.getNextInSequence(Long.class, "id");
// check if we are within context of async-execution
AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
if (asyncExecutor != null) {
AsyncJobVO job = asyncExecutor.getJob();
if (s_logger.isInfoEnabled()) {
s_logger.info("DeployVM acquired a new instance " + vmId + ", update async job-" + job.getId() + " progress status");
}
_asyncMgr.updateAsyncJobAttachment(job.getId(), "vm_instance", vmId);
_asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, vmId);
}
HashMap<Long, StoragePoolVO> avoids = new HashMap<Long, StoragePoolVO>();
// Pod allocator now allocate VM based on a reservation style allocation, disable retry here for now
for (int retry = 0; retry < 1; retry++) {
String externalIp = null;
UserVmVO created = null;
ArrayList<StoragePoolVO> a = new ArrayList<StoragePoolVO>(avoids.values());
if (_directAttachNetworkExternalIpAllocator) {
try {
created = _vmMgr.createDirectlyAttachedVMExternal(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
} catch (ResourceAllocationException rae) {
throw rae;
}
} else {
if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtual) {
try {
externalIp = _networkMgr.assignSourceNatIpAddress(account, dc, domain, offering, startEventId, template.getHypervisorType());
} catch (ResourceAllocationException rae) {
throw rae;
}
if (externalIp == null) {
throw new CloudRuntimeException("Unable to allocate a source nat ip address");
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Source Nat acquired: " + externalIp);
}
try {
created = _vmMgr.createVirtualMachine(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, startEventId, size);
} catch (ResourceAllocationException rae) {
throw rae;
}
} else {
try {
created = _vmMgr.createDirectlyAttachedVM(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
} catch (ResourceAllocationException rae) {
throw rae;
}
}
}
//assign vm to the group
try{
if (group != null) {
boolean addToGroup = _vmMgr.addInstanceToGroup(Long.valueOf(vmId), group);
if (!addToGroup) {
throw new CloudRuntimeException("Unable to assing Vm to the group " + group);
}
}
} catch (Exception ex) {
throw new CloudRuntimeException("Unable to assing Vm to the group " + group);
}
if (created == null) {
throw new CloudRuntimeException("Unable to create VM for account (" + accountId + "): " + account.getAccountName());
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("VM created: " + created.getId() + "-" + created.getHostName());
}
boolean executionExceptionFlag = false;
boolean storageUnavailableExceptionFlag = false;
boolean concurrentOperationExceptionFlag = false;
String executionExceptionMsg= "";
String storageUnavailableExceptionMsg = "";
String concurrentOperationExceptionMsg = "";
UserVmVO started = null;
if (isIso)
{
Pair<String, String> isoPath = _storageMgr.getAbsoluteIsoPath(templateId, dataCenterId);
if (isoPath == null) {
s_logger.warn("Unable to get absolute path of the iso");
throw new CloudRuntimeException("Unable to get absolute path of the iso");
}
try
{
started = _vmMgr.startVirtualMachine(userId, created.getId(), password, isoPath.first(), startEventId);
}
catch (ExecutionException e)
{
executionExceptionFlag = true;
executionExceptionMsg = e.getMessage();
}
catch (StorageUnavailableException e)
{
storageUnavailableExceptionFlag = true;
storageUnavailableExceptionMsg = e.getMessage();
}
catch (ConcurrentOperationException e)
{
concurrentOperationExceptionFlag = true;
concurrentOperationExceptionMsg = e.getMessage();
}
}
else
{
try
{
started = _vmMgr.startVirtualMachine(userId, created.getId(), password, null, startEventId);
}
catch (ExecutionException e)
{
executionExceptionFlag = true;
executionExceptionMsg = e.getMessage();
}
catch (StorageUnavailableException e)
{
storageUnavailableExceptionFlag = true;
storageUnavailableExceptionMsg = e.getMessage();
}
catch (ConcurrentOperationException e)
{
concurrentOperationExceptionFlag = true;
concurrentOperationExceptionMsg = e.getMessage();
}
}
if (started == null) {
List<Pair<VolumeVO, StoragePoolVO>> disks = _storageMgr.isStoredOn(created);
// NOTE: We now destroy a VM if the deploy process fails at any step. We now
// have a lazy delete so there is still some time to figure out what's wrong.
_vmMgr.destroyVirtualMachine(userId, created.getId());
boolean retryCreate = true;
for (Pair<VolumeVO, StoragePoolVO> disk : disks) {
if (disk.second().isLocal()) {
avoids.put(disk.second().getId(), disk.second());
} else {
retryCreate = false;
}
}
if (retryCreate) {
continue;
} else if(executionExceptionFlag){
throw new ExecutionException(executionExceptionMsg);
} else if (storageUnavailableExceptionFlag){
throw new StorageUnavailableException(storageUnavailableExceptionMsg);
}else if (concurrentOperationExceptionFlag){
throw new ConcurrentOperationException(concurrentOperationExceptionMsg);
}
else{
throw new CloudRuntimeException("Unable to start the VM " + created.getId() + "-" + created.getHostName());
}
} else {
if (isIso) {
started.setIsoId(templateId);
_userVmDao.update(started.getId(), started);
started = _userVmDao.findById(started.getId());
}
try {
_configMgr.associateIpAddressListToAccount(userId, accountId, dc.getId(),null);
} catch (InsufficientAddressCapacityException e) {
s_logger.debug("Unable to assign public IP address pool: " +e.getMessage());
}
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("VM started: " + started.getId() + "-" + started.getHostName());
}
return started;
}
return null;
}
@Override
public UserVm deployVirtualMachine(DeployVMCmd cmd, String password) throws ResourceAllocationException,
ExecutionException,
ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
if (_useNewNetworking) {
UserVm vm = _userVmService.createVirtualMachine(cmd);
if (vm == null) {
return null;
}
DeployVm2Cmd cmd2 = new DeployVm2Cmd();
cmd2.setEntityId(vm.getId());
vm = _userVmService.startVirtualMachine(cmd2);
return vm;
}
Account ctxAccount = UserContext.current().getAccount();
Long userId = UserContext.current().getUserId();
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
Long accountId = null;
long dataCenterId = cmd.getZoneId();
long serviceOfferingId = cmd.getServiceOfferingId();
long templateId = cmd.getTemplateId();
Long diskOfferingId = cmd.getDiskOfferingId();
String domain = null; // FIXME: this was hardcoded to null in DeployVMCmd in the old framework, do we need it?
String displayName = cmd.getDisplayName();
String group = cmd.getGroup();
String userData = cmd.getUserData();
String[] networkGroups = null;
Long sizeObj = cmd.getSize();
long size = (sizeObj == null) ? 0 : sizeObj;
Account userAccount = null;
DataCenterVO dc = _dcDao.findById(dataCenterId);
if (dc == null) {
throw new InvalidParameterValueException("Unable to find zone: " + dataCenterId);
}
if ((ctxAccount == null) || isAdmin(ctxAccount.getType())) {
if (domainId != null) {
if ((ctxAccount != null) && !_domainDao.isChildDomain(ctxAccount.getDomainId(), domainId)) {
throw new PermissionDeniedException("Failed to deploy VM, invalid domain id (" + domainId + ") given.");
}
if (accountName != null) {
userAccount = _accountDao.findActiveAccount(accountName, domainId);
if (userAccount == null) {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
accountId = userAccount.getId();
}
} else {
accountId = ((ctxAccount != null) ? ctxAccount.getId() : null);
}
} else {
accountId = ctxAccount.getId();
}
if (accountId == null) {
throw new InvalidParameterValueException("No valid account specified for deploying a virtual machine.");
}
if(domainId == null){
domainId = dc.getDomainId(); //get the domain id from zone
}
if(domainId == null){
//do nothing (public zone case)
}
else{
if(userAccount != null){
_configMgr.checkAccess(userAccount, dc);//user deploying his own vm
}else{
_configMgr.checkAccess(ctxAccount, dc);
}
}
List<String> netGrpList = cmd.getNetworkGroupList();
if ((netGrpList != null) && !netGrpList.isEmpty()) {
networkGroups = netGrpList.toArray(new String[netGrpList.size()]);
}
AccountVO account = _accountDao.findById(accountId);
if (account == null) {
throw new InvalidParameterValueException("Unable to find account: " + accountId);
}
ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
if (offering == null) {
throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId);
}
if(offering.getDomainId() == null){
//do nothing as offering is public
}else{
if(userAccount != null){
_configMgr.checkServiceOfferingAccess(userAccount, offering);//user deploying his own vm
}else{
_configMgr.checkServiceOfferingAccess(ctxAccount, offering);
}
}
VMTemplateVO template = _templateDao.findById(templateId);
// Make sure a valid template ID was specified
if (template == null) {
throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
}
boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
if (isIso && !template.isBootable()) {
throw new InvalidParameterValueException("Please specify a bootable ISO.");
}
// If the template represents an ISO, a disk offering must be passed in, and will be used to create the root disk
// Else, a disk offering is optional, and if present will be used to create the data disk
DiskOfferingVO diskOffering = null;
if (diskOfferingId != null) {
diskOffering = _diskOfferingDao.findById(diskOfferingId);
}
if (isIso && diskOffering == null) {
throw new InvalidParameterValueException("Please specify a valid disk offering ID.");
}
if(diskOffering != null){
if(diskOffering.getDomainId() == null){
//do nothing as offering is public
}else{
if(userAccount != null){
_configMgr.checkDiskOfferingAccess(userAccount, diskOffering);//user deploying his own vm
}else{
_configMgr.checkDiskOfferingAccess(ctxAccount, diskOffering);
}
}
}
if (isIso) {
/*iso template doesn;t have hypervisor type, temporarily set it's type as user specified, pass it to storage allocator */
template.setHypervisorType(HypervisorType.getType(cmd.getHypervisor()));
}
//if it is a custom disk offering,AND the size passed in here is <= 0; error out
if(diskOffering != null && diskOffering.isCustomized() && size <= 0){
throw new InvalidParameterValueException("Please specify a valid disk size for VM creation; custom disk offering has no size set");
}
if(diskOffering != null && diskOffering.isCustomized() && size > _maxVolumeSizeInGb){
throw new InvalidParameterValueException("Please specify a valid disk size for VM creation; custom disk offering max size is:"+_maxVolumeSizeInGb);
}
// validate that the template is usable by the account
if (!template.isPublicTemplate()) {
Long templateOwner = template.getAccountId();
if (!BaseCmd.isAdmin(account.getType()) && ((templateOwner == null) || (templateOwner.longValue() != accountId))) {
// since the current account is not the owner of the template, check the launch permissions table to see if the
// account can launch a VM from this template
LaunchPermissionVO permission = _launchPermissionDao.findByTemplateAndAccount(templateId, account.getId());
if (permission == null) {
throw new PermissionDeniedException("Account " + account.getAccountName() + " does not have permission to launch instances from template " + template.getName());
}
}
}
byte [] decodedUserData = null;
if (userData != null) {
if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
throw new InvalidParameterValueException("User data is too long");
}
decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
throw new InvalidParameterValueException("User data is too long");
}
if (decodedUserData.length < 1) {
throw new InvalidParameterValueException("User data is too short");
}
}
if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtual) {
_networkGroupMgr.createDefaultNetworkGroup(accountId);
}
if (networkGroups != null) {
if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtual) {
throw new InvalidParameterValueException("Network groups are not compatible with service offering " + offering.getName());
}
Set<String> nameSet = new HashSet<String>(); //handle duplicate names -- allowed
nameSet.addAll(Arrays.asList(networkGroups));
nameSet.add(NetworkGroupManager.DEFAULT_GROUP_NAME);
networkGroups = nameSet.toArray(new String[nameSet.size()]);
List<NetworkGroupVO> networkGroupVOs = _networkSecurityGroupDao.findByAccountAndNames(accountId, networkGroups);
if (networkGroupVOs.size() != nameSet.size()) {
throw new InvalidParameterValueException("Some network group names do not exist");
}
} else { //create a default group if necessary
if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtual && _networkGroupsEnabled) {
networkGroups = new String[]{NetworkGroupManager.DEFAULT_GROUP_NAME};
}
}
Long eventId = cmd.getStartEventId();
try {
return deployVirtualMachineImpl(userId, accountId, dataCenterId, serviceOfferingId, template, diskOfferingId, domain, password, displayName, group, userData, networkGroups, eventId, (1L*size*1024));//this api expects size in MB
} catch (ResourceAllocationException e) {
if(s_logger.isDebugEnabled()) {
s_logger.debug("Unable to deploy VM: " + e.getMessage());
}
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
throw e;
} catch (ExecutionException e) {
if(s_logger.isDebugEnabled()) {
s_logger.debug("Unable to deploy VM: " + e.getMessage());
}
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_HOST_LICENSE_EXPIRED", null, eventId);
throw e;
} catch (InvalidParameterValueException e) {
if(s_logger.isDebugEnabled()) {
s_logger.debug("Unable to deploy VM: " + e.getMessage());
}
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INVALID_PARAM_ERROR", null, eventId);
throw e;
} catch (InsufficientStorageCapacityException e) {
if(s_logger.isDebugEnabled()) {
s_logger.debug("Unable to deploy VM: " + e.getMessage());
}
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
throw e;
} catch (PermissionDeniedException e) {
if(s_logger.isDebugEnabled()) {
s_logger.debug("Unable to deploy VM: " + e.getMessage());
}
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: ACCOUNT_ERROR", null, eventId);
throw e;
} catch (ConcurrentOperationException e) {
if(s_logger.isDebugEnabled()) {
s_logger.debug("Unable to deploy VM: " + e.getMessage());
}
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
throw e;
} catch(Exception e) {
s_logger.warn("Unable to deploy VM : " + e.getMessage(), e);
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
throw new CloudRuntimeException("Unable to deploy VM : " + e.getMessage());
}
}
@Override
public DomainRouterVO findDomainRouterById(long domainRouterId) {
return _routerDao.findById(domainRouterId);
}
@Override
public List<DataCenterVO> listDataCenters(ListZonesByCmd cmd) {
Account account = UserContext.current().getAccount();
List<DataCenterVO> dcs = null;
Long domainId = cmd.getDomainId();
Long id = cmd.getId();
if(domainId != null){
//for domainId != null
//right now, we made the decision to only list zones associated with this domain
dcs = _dcDao.findZonesByDomainId(domainId); //private zones
}
else if((account == null || account.getType() == Account.ACCOUNT_TYPE_ADMIN)){
dcs = _dcDao.listAll(); //all zones
}else if(account.getType() == Account.ACCOUNT_TYPE_NORMAL){
//it was decided to return all zones for the user's domain, and everything above till root
//list all zones belonging to this domain, and all of its parents
//check the parent, if not null, add zones for that parent to list
dcs = new ArrayList<DataCenterVO>();
DomainVO domainRecord = _domainDao.findById(account.getDomainId());
if(domainRecord != null)
{
while(true){
dcs.addAll(_dcDao.findZonesByDomainId(domainRecord.getId()));
if(domainRecord.getParent() != null) {
domainRecord = _domainDao.findById(domainRecord.getParent());
} else {
break;
}
}
}
//add all public zones too
dcs.addAll(_dcDao.listPublicZones());
}else if(account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN){
//it was decided to return all zones for the domain admin, and everything above till root
dcs = new ArrayList<DataCenterVO>();
DomainVO domainRecord = _domainDao.findById(account.getDomainId());
//this covers path till root
if(domainRecord != null)
{
DomainVO localRecord = domainRecord;
while(true){
dcs.addAll(_dcDao.findZonesByDomainId(localRecord.getId()));
if(localRecord.getParent() != null) {
localRecord = _domainDao.findById(localRecord.getParent());
} else {
break;
}
}
}
//this covers till leaf
if(domainRecord != null){
//find all children for this domain based on a like search by path
List<DomainVO> allChildDomains = _domainDao.findAllChildren(domainRecord.getPath(), domainRecord.getId());
List<Long> allChildDomainIds = new ArrayList<Long>();
//create list of domainIds for search
for(DomainVO domain : allChildDomains){
allChildDomainIds.add(domain.getId());
}
//now make a search for zones based on this
if(allChildDomainIds.size() > 0){
List<DataCenterVO> childZones = _dcDao.findChildZones((allChildDomainIds.toArray()));
dcs.addAll(childZones);
}
}
//add all public zones too
dcs.addAll(_dcDao.listPublicZones());
}
Boolean available = cmd.isAvailable();
if (account != null) {
if ((available != null) && Boolean.FALSE.equals(available)) {
List<DomainRouterVO> routers = _routerDao.listBy(account.getId());
for (Iterator<DataCenterVO> iter = dcs.iterator(); iter.hasNext();) {
DataCenterVO dc = iter.next();
boolean found = false;
for (DomainRouterVO router : routers) {
if (dc.getId() == router.getDataCenterId()) {
found = true;
break;
}
}
if (!found) {
iter.remove();
}
}
}
}
if (id != null) {
List<DataCenterVO> singleZone = new ArrayList<DataCenterVO>();
for (DataCenterVO zone : dcs) {
if (zone.getId() == id) {
singleZone.add(zone);
}
}
return singleZone;
}
return dcs;
}
@Override
public HostVO getHostBy(long hostId) {
return _hostDao.findById(hostId);
}
@Override
public long getId() {
return MacAddress.getMacAddress().toLong();
}
protected void checkPortParameters(String publicPort, String privatePort, String privateIp, String proto) throws InvalidParameterValueException {
if (!NetUtils.isValidPort(publicPort)) {
throw new InvalidParameterValueException("publicPort is an invalid value");
}
if (!NetUtils.isValidPort(privatePort)) {
throw new InvalidParameterValueException("privatePort is an invalid value");
}
// s_logger.debug("Checking if " + privateIp + " is a valid private IP address. Guest IP address is: " + _configs.get("guest.ip.network"));
//
// if (!NetUtils.isValidPrivateIp(privateIp, _configs.get("guest.ip.network"))) {
// throw new InvalidParameterValueException("Invalid private ip address");
// }
if (!NetUtils.isValidProto(proto)) {
throw new InvalidParameterValueException("Invalid protocol");
}
}
@Override
public List<EventVO> getEvents(long userId, long accountId, Long domainId, String type, String level, Date startDate, Date endDate) {
SearchCriteria<EventVO> sc = _eventDao.createSearchCriteria();
if (userId > 0) {
sc.addAnd("userId", SearchCriteria.Op.EQ, userId);
}
if (accountId > 0) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
}
if (domainId != null) {
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
}
if (type != null) {
sc.addAnd("type", SearchCriteria.Op.EQ, type);
}
if (level != null) {
sc.addAnd("level", SearchCriteria.Op.EQ, level);
}
if (startDate != null && endDate != null) {
startDate = massageDate(startDate, 0, 0, 0);
endDate = massageDate(endDate, 23, 59, 59);
sc.addAnd("createDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
} else if (startDate != null) {
startDate = massageDate(startDate, 0, 0, 0);
sc.addAnd("createDate", SearchCriteria.Op.GTEQ, startDate);
} else if (endDate != null) {
endDate = massageDate(endDate, 23, 59, 59);
sc.addAnd("createDate", SearchCriteria.Op.LTEQ, endDate);
}
return _eventDao.search(sc, null);
}
private Date massageDate(Date date, int hourOfDay, int minute, int second) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, second);
return cal.getTime();
}
@Override
public List<UserAccountVO> searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException {
Account account = UserContext.current().getAccount();
Long domainId = cmd.getDomainId();
if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list users.");
}
} else {
// default domainId to the admin's domain
domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
}
Filter searchFilter = new Filter(UserAccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
Long id = cmd.getId();
Object username = cmd.getUsername();
Object type = cmd.getAccountType();
Object accountName = cmd.getAccountName();
Object state = cmd.getState();
Object keyword = cmd.getKeyword();
SearchBuilder<UserAccountVO> sb = _userAccountDao.createSearchBuilder();
sb.and("username", sb.entity().getUsername(), SearchCriteria.Op.LIKE);
if (id != null && id == 1) {
//system user should NOT be searchable
List<UserAccountVO> emptyList = new ArrayList<UserAccountVO>();
return emptyList;
} else if (id != null) {
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
} else {
//this condition is used to exclude system user from the search results
sb.and("id", sb.entity().getId(), SearchCriteria.Op.NEQ);
}
sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
if ((accountName == null) && (domainId != null)) {
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
SearchCriteria<UserAccountVO> sc = sb.create();
if (keyword != null) {
SearchCriteria<UserAccountVO> ssc = _userAccountDao.createSearchCriteria();
ssc.addOr("username", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("firstname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("lastname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("email", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("accountState", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("username", SearchCriteria.Op.SC, ssc);
}
if (username != null) {
sc.setParameters("username", "%" + username + "%");
}
if (id != null) {
sc.setParameters("id", id);
} else {
//Don't return system user, search builder with NEQ
sc.setParameters("id", 1);
}
if (type != null) {
sc.setParameters("type", type);
}
if (accountName != null) {
sc.setParameters("accountName", "%" + accountName + "%");
if (domainId != null) {
sc.setParameters("domainId", domainId);
}
} else if (domainId != null) {
DomainVO domainVO = _domainDao.findById(domainId);
sc.setJoinParameters("domainSearch", "path", domainVO.getPath() + "%");
}
if (state != null) {
sc.setParameters("state", state);
}
return _userAccountDao.search(sc, searchFilter);
}
//This method is used for permissions check for both disk and service offerings
private boolean isPermissible(Long accountDomainId, Long offeringDomainId){
if(accountDomainId == offeringDomainId)
{
return true; // account and service offering in same domain
}
DomainVO domainRecord = _domainDao.findById(accountDomainId);
if(domainRecord != null){
while(true){
if(domainRecord.getId() == offeringDomainId) {
return true;
}
//try and move on to the next domain
if(domainRecord.getParent() != null) {
domainRecord = _domainDao.findById(domainRecord.getParent());
} else {
break;
}
}
}
return false;
}
@Override
public List<ServiceOfferingVO> searchForServiceOfferings(ListServiceOfferingsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
//Note
//The list method for offerings is being modified in accordance with discussion with Will/Kevin
//For now, we will be listing the following based on the usertype
//1. For root, we will list all offerings
//2. For domainAdmin and regular users, we will list everything in their domains+parent domains ... all the way till root
Filter searchFilter = new Filter(ServiceOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchCriteria<ServiceOfferingVO> sc = _offeringsDao.createSearchCriteria();
Account account = UserContext.current().getAccount();
Object name = cmd.getServiceOfferingName();
Object id = cmd.getId();
Object keyword = cmd.getKeyword();
Long vmId = cmd.getVirtualMachineId();
Long domainId = cmd.getDomainId();
//Keeping this logic consistent with domain specific zones
//if a domainId is provided, we just return the so associated with this domain
if(domainId != null){
if(account.getType() == Account.ACCOUNT_TYPE_ADMIN){
return _offeringsDao.findServiceOfferingByDomainId(domainId);//no perm check
}else{
//check if the user's domain == so's domain || user's domain is a child of so's domain
if(isPermissible(account.getDomainId(), domainId)){
//perm check succeeded
return _offeringsDao.findServiceOfferingByDomainId(domainId);
}else{
throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "The account:"+account.getAccountName()+" does not fall in the same domain hierarchy as the service offering");
}
}
}
//For non-root users
if((account.getType() == Account.ACCOUNT_TYPE_NORMAL || account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)){
return searchServiceOfferingsInternal(account, name, id, vmId, keyword, searchFilter);
}
//for root users, the existing flow
if (keyword != null) {
SearchCriteria<ServiceOfferingVO> ssc = _offeringsDao.createSearchCriteria();
ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
} else if (vmId != null) {
UserVmVO vmInstance = _userVmDao.findById(vmId);
if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
}
if ((account != null) && !isAdmin(account.getType())) {
if (account.getId() != vmInstance.getAccountId()) {
throw new PermissionDeniedException("unable to find a virtual machine with id " + vmId + " for this account");
}
}
ServiceOfferingVO offering = _offeringsDao.findById(vmInstance.getServiceOfferingId());
sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId());
// Only return offerings with the same Guest IP type and storage pool preference
sc.addAnd("guestIpType", SearchCriteria.Op.EQ, offering.getGuestIpType());
sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, offering.getUseLocalStorage());
}
if (id != null) {
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
if (name != null) {
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
}
sc.addAnd("systemUse", SearchCriteria.Op.EQ, false);
return _offeringsDao.search(sc, searchFilter);
}
private List<ServiceOfferingVO> searchServiceOfferingsInternal(Account account, Object name, Object id, Long vmId, Object keyword, Filter searchFilter){
//it was decided to return all offerings for the user's domain, and everything above till root (for normal user or domain admin)
//list all offerings belonging to this domain, and all of its parents
//check the parent, if not null, add offerings for that parent to list
List<ServiceOfferingVO> sol = new ArrayList<ServiceOfferingVO>();
DomainVO domainRecord = _domainDao.findById(account.getDomainId());
boolean includePublicOfferings = true;
if(domainRecord != null)
{
while(true){
SearchCriteria<ServiceOfferingVO> sc = _offeringsDao.createSearchCriteria();
if (keyword != null) {
includePublicOfferings = false;
SearchCriteria<ServiceOfferingVO> ssc = _offeringsDao.createSearchCriteria();
ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
} else if (vmId != null) {
includePublicOfferings = false;
UserVmVO vmInstance = _userVmDao.findById(vmId);
if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
}
if ((account != null) && !isAdmin(account.getType())) {
if (account.getId() != vmInstance.getAccountId()) {
throw new PermissionDeniedException("unable to find a virtual machine with id " + vmId + " for this account");
}
}
ServiceOfferingVO offering = _offeringsDao.findById(vmInstance.getServiceOfferingId());
sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId());
// Only return offerings with the same Guest IP type and storage pool preference
sc.addAnd("guestIpType", SearchCriteria.Op.EQ, offering.getGuestIpType());
sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, offering.getUseLocalStorage());
}
if (id != null) {
includePublicOfferings = false;
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
if (name != null) {
includePublicOfferings = false;
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
}
sc.addAnd("systemUse", SearchCriteria.Op.EQ, false);
//for this domain
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainRecord.getId());
//search and add for this domain
sol.addAll(_offeringsDao.search(sc, searchFilter));
//try and move on to the next domain
if(domainRecord.getParent() != null) {
domainRecord = _domainDao.findById(domainRecord.getParent());
}
else {
break;//now we got all the offerings for this user/dom adm
}
}
}else{
s_logger.error("Could not find the domainId for account:"+account.getAccountName());
throw new CloudAuthenticationException("Could not find the domainId for account:"+account.getAccountName());
}
//add all the public offerings to the sol list before returning
if(includePublicOfferings) {
sol.addAll(_offeringsDao.findPublicServiceOfferings());
}
return sol;
}
@Override
public List<ClusterVO> searchForClusters(ListClustersCmd cmd) {
Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchCriteria<ClusterVO> sc = _clusterDao.createSearchCriteria();
Object id = cmd.getId();
Object name = cmd.getClusterName();
Object podId = cmd.getPodId();
Object zoneId = cmd.getZoneId();
if (id != null) {
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
if (name != null) {
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
}
if (podId != null) {
sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
}
if (zoneId != null) {
sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
}
return _clusterDao.search(sc, searchFilter);
}
@Override
public List<HostVO> searchForServers(ListHostsCmd cmd) {
Object name = cmd.getHostName();
Object type = cmd.getType();
Object state = cmd.getState();
Object zone = cmd.getZoneId();
Object pod = cmd.getPodId();
Object cluster = cmd.getClusterId();
Object id = cmd.getId();
Object keyword = cmd.getKeyword();
return searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), name, type, state, zone, pod, cluster, id, keyword);
}
private List<HostVO> searchForServers(Long startIndex, Long pageSize, Object name, Object type, Object state, Object zone, Object pod, Object cluster, Object id, Object keyword) {
Filter searchFilter = new Filter(HostVO.class, "id", Boolean.TRUE, startIndex, pageSize);
SearchCriteria<HostVO> sc = _hostDao.createSearchCriteria();
if (keyword != null) {
SearchCriteria<HostVO> ssc = _hostDao.createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("status", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (id != null) {
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
if (name != null) {
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
}
if (type != null) {
sc.addAnd("type", SearchCriteria.Op.EQ, type);
}
if (state != null) {
sc.addAnd("status", SearchCriteria.Op.EQ, state);
}
if (zone != null) {
sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
}
if (pod != null) {
sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
}
if (cluster != null) {
sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
}
return _hostDao.search(sc, searchFilter);
}
@Override
public List<HostPodVO> searchForPods(ListPodsByCmd cmd) {
Filter searchFilter = new Filter(HostPodVO.class, "dataCenterId", true, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchCriteria<HostPodVO> sc = _hostPodDao.createSearchCriteria();
String podName = cmd.getPodName();
Long id = cmd.getId();
Long zoneId = cmd.getZoneId();
Object keyword = cmd.getKeyword();
if (keyword != null) {
SearchCriteria<HostPodVO> ssc = _hostPodDao.createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (id != null) {
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
if (podName != null) {
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + podName + "%");
}
if (zoneId != null) {
sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
}
return _hostPodDao.search(sc, searchFilter);
}
@Override
public List<DataCenterVO> searchForZones(Criteria c) {
Long dataCenterId = (Long) c.getCriteria(Criteria.DATACENTERID);
if (dataCenterId != null) {
DataCenterVO dc = _dcDao.findById(dataCenterId);
List<DataCenterVO> datacenters = new ArrayList<DataCenterVO>();
datacenters.add(dc);
return datacenters;
}
Filter searchFilter = new Filter(DataCenterVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
SearchCriteria<DataCenterVO> sc = _dcDao.createSearchCriteria();
String zoneName = (String) c.getCriteria(Criteria.ZONENAME);
if (zoneName != null) {
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + zoneName + "%");
}
return _dcDao.search(sc, searchFilter);
}
@Override
public List<VlanVO> searchForVlans(ListVlanIpRangesCmd cmd) throws InvalidParameterValueException {
// If an account name and domain ID are specified, look up the account
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
Long accountId = null;
if (accountName != null && domainId != null) {
Account account = _accountDao.findActiveAccount(accountName, domainId);
if (account == null) {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
} else {
accountId = account.getId();
}
}
Filter searchFilter = new Filter(VlanVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
Object id = cmd.getId();
Object vlan = cmd.getVlan();
Object dataCenterId = cmd.getZoneId();
Object podId = cmd.getPodId();
Object keyword = cmd.getKeyword();
SearchBuilder<VlanVO> sb = _vlanDao.createSearchBuilder();
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("vlan", sb.entity().getVlanId(), SearchCriteria.Op.EQ);
sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
if (accountId != null) {
SearchBuilder<AccountVlanMapVO> accountVlanMapSearch = _accountVlanMapDao.createSearchBuilder();
accountVlanMapSearch.and("accountId", accountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
sb.join("accountVlanMapSearch", accountVlanMapSearch, sb.entity().getId(), accountVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
}
if (podId != null) {
SearchBuilder<PodVlanMapVO> podVlanMapSearch = _podVlanMapDao.createSearchBuilder();
podVlanMapSearch.and("podId", podVlanMapSearch.entity().getPodId(), SearchCriteria.Op.EQ);
sb.join("podVlanMapSearch", podVlanMapSearch, sb.entity().getId(), podVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
}
SearchCriteria<VlanVO> sc = sb.create();
if (keyword != null) {
SearchCriteria<VlanVO> ssc = _vlanDao.createSearchCriteria();
ssc.addOr("vlanId", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("ipRange", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("vlanId", SearchCriteria.Op.SC, ssc);
} else {
if (id != null) {
sc.setParameters("id", id);
}
if (vlan != null) {
sc.setParameters("vlan", vlan);
}
if (dataCenterId != null) {
sc.setParameters("dataCenterId", dataCenterId);
}
if (accountId != null) {
sc.setJoinParameters("accountVlanMapSearch", "accountId", accountId);
}
if (podId != null) {
sc.setJoinParameters("podVlanMapSearch", "podId", podId);
}
}
return _vlanDao.search(sc, searchFilter);
}
@Override
public Long getPodIdForVlan(long vlanDbId) {
List<PodVlanMapVO> podVlanMaps = _podVlanMapDao.listPodVlanMapsByVlan(vlanDbId);
if (podVlanMaps.isEmpty()) {
return null;
} else {
return podVlanMaps.get(0).getPodId();
}
}
@Override
public List<ConfigurationVO> searchForConfigurations(ListCfgsByCmd cmd) {
Filter searchFilter = new Filter(ConfigurationVO.class, "name", true, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchCriteria<ConfigurationVO> sc = _configDao.createSearchCriteria();
Object name = cmd.getConfigName();
Object category = cmd.getCategory();
Object keyword = cmd.getKeyword();
if (keyword != null) {
SearchCriteria<ConfigurationVO> ssc = _configDao.createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("instance", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("component", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("category", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("value", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (name != null) {
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
}
if (category != null) {
sc.addAnd("category", SearchCriteria.Op.EQ, category);
}
// hidden configurations are not displayed using the search API
sc.addAnd("category", SearchCriteria.Op.NEQ, "Hidden");
return _configDao.search(sc, searchFilter);
}
@Override
public List<HostVO> searchForAlertServers(Criteria c) {
Filter searchFilter = new Filter(HostVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
SearchCriteria<HostVO> sc = _hostDao.createSearchCriteria();
Object[] states = (Object[]) c.getCriteria(Criteria.STATE);
if (states != null) {
sc.addAnd("status", SearchCriteria.Op.IN, states);
}
return _hostDao.search(sc, searchFilter);
}
@Override
public List<VMTemplateVO> searchForTemplates(Criteria c) {
Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
Object name = c.getCriteria(Criteria.NAME);
Object isPublic = c.getCriteria(Criteria.ISPUBLIC);
Object id = c.getCriteria(Criteria.ID);
Object keyword = c.getCriteria(Criteria.KEYWORD);
Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);
SearchBuilder<VMTemplateVO> sb = _templateDao.createSearchBuilder();
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("publicTemplate", sb.entity().isPublicTemplate(), SearchCriteria.Op.EQ);
sb.and("format", sb.entity().getFormat(), SearchCriteria.Op.NEQ);
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
SearchCriteria<VMTemplateVO> sc = sb.create();
if (keyword != null) {
SearchCriteria<VMTemplateVO> ssc = _templateDao.createSearchCriteria();
ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (id != null) {
sc.setParameters("id", id);
}
if (name != null) {
sc.setParameters("name", "%" + name + "%");
}
if (isPublic != null) {
sc.setParameters("publicTemplate", isPublic);
}
if (creator != null) {
sc.setParameters("accountId", creator);
}
sc.setParameters("format", ImageFormat.ISO);
return _templateDao.search(sc, searchFilter);
}
@Override
public List<VMTemplateVO> listIsos(ListIsosCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
TemplateFilter isoFilter = TemplateFilter.valueOf(cmd.getIsoFilter());
Long accountId = null;
Account account = UserContext.current().getAccount();
Long domainId = cmd.getDomainId();
String accountName = cmd.getAccountName();
if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
// validate domainId before proceeding
if ((domainId != null) && (accountName != null)) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
}
Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new InvalidParameterValueException("Failed to list ISOs. Unable to find account " + accountName + " in domain " + domainId);
}
} else if (account != null) {
accountId = account.getId();
}
} else {
accountId = account.getId();
}
HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor());
return listTemplates(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), accountId, cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType);
}
@Override
public List<VMTemplateVO> listTemplates(ListTemplatesCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter());
Long accountId = null;
Account account = UserContext.current().getAccount();
Long domainId = cmd.getDomainId();
String accountName = cmd.getAccountName();
if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
// validate domainId before proceeding
if ((domainId != null) && (accountName != null)) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
}
Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new InvalidParameterValueException("Failed to list ISOs. Unable to find account " + accountName + " in domain " + domainId);
}
} else if (account != null) {
accountId = account.getId();
}
} else {
accountId = account.getId();
}
HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor());
return listTemplates(cmd.getId(), cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, accountId, cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType);
}
private List<VMTemplateVO> listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long accountId, Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType) throws InvalidParameterValueException {
VMTemplateVO template = null;
if (templateId != null) {
template = _templateDao.findById(templateId);
if (template == null) {
throw new InvalidParameterValueException("Please specify a valid template ID.");
}// If ISO requested then it should be ISO.
if (isIso && template.getFormat() != ImageFormat.ISO){
s_logger.error("Template Id " + templateId + " is not an ISO");
throw new InvalidParameterValueException("Template Id " + templateId + " is not an ISO");
}// If ISO not requested then it shouldn't be an ISO.
if (!isIso && template.getFormat() == ImageFormat.ISO){
s_logger.error("Incorrect format of the template id " + templateId);
throw new InvalidParameterValueException("Incorrect format " + template.getFormat() + " of the template id " + templateId);
}
}
Account account = null;
DomainVO domain = null;
if (accountId != null) {
account = _accountDao.findById(accountId);
domain = _domainDao.findById(account.getDomainId());
} else {
domain = _domainDao.findById(DomainVO.ROOT_DOMAIN);
}
List<VMTemplateVO> templates = new ArrayList<VMTemplateVO>();
if (template == null) {
templates = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, bootable, account, domain, pageSize, startIndex, zoneId, hyperType);
} else {
templates = new ArrayList<VMTemplateVO>();
templates.add(template);
}
return templates;
}
@Override
public List<VMTemplateVO> listPermittedTemplates(long accountId) {
return _launchPermissionDao.listPermittedTemplates(accountId);
}
@Override
public List<HostPodVO> listPods(long dataCenterId) {
return _hostPodDao.listByDataCenterId(dataCenterId);
}
@Override
public String changePrivateIPRange(boolean add, Long podId, String startIP, String endIP) throws InvalidParameterValueException {
return _configMgr.changePrivateIPRange(add, podId, startIP, endIP);
}
@Override
public User findUserById(Long userId) {
return _userDao.findById(userId);
}
@Override
public List<AccountVO> findAccountsLike(String accountName) {
return _accountDao.findAccountsLike(accountName);
}
@Override
public Account findActiveAccountByName(String accountName) {
return _accountDao.findActiveAccountByName(accountName);
}
@Override
public Account findActiveAccount(String accountName, Long domainId) {
if (domainId == null) {
domainId = DomainVO.ROOT_DOMAIN;
}
return _accountDao.findActiveAccount(accountName, domainId);
}
@Override
public Account findAccountByName(String accountName, Long domainId) {
if (domainId == null) {
domainId = DomainVO.ROOT_DOMAIN;
}
return _accountDao.findAccount(accountName, domainId);
}
@Override
public Account findAccountById(Long accountId) {
return _accountDao.findById(accountId);
}
@Override
public List<AccountVO> searchForAccounts(ListAccountsCmd cmd) {
Account account = UserContext.current().getAccount();
Long domainId = cmd.getDomainId();
Long accountId = cmd.getId();
String accountName = null;
if(accountId != null && accountId == 1){
//system account should NOT be searchable
List<AccountVO> emptyList = new ArrayList<AccountVO>();
return emptyList;
}
if ((account == null) || isAdmin(account.getType())) {
accountName = cmd.getSearchName(); // admin's can specify a name to search for
if (domainId == null) {
// default domainId to the admin's domain
domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
} else if (account != null) {
if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list accounts");
}
}
} else {
accountId = account.getId();
accountName = account.getAccountName(); // regular users must be constrained to their own account
}
Filter searchFilter = new Filter(AccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
Object type = cmd.getAccountType();
Object state = cmd.getState();
Object isCleanupRequired = cmd.isCleanupRequired();
Object keyword = cmd.getKeyword();
SearchBuilder<AccountVO> sb = _accountDao.createSearchBuilder();
sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("nid", sb.entity().getId(), SearchCriteria.Op.NEQ);
sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
sb.and("needsCleanup", sb.entity().getNeedsCleanup(), SearchCriteria.Op.EQ);
if ((accountId == null) && (domainId != null)) {
// if accountId isn't specified, we can do a domain match for the admin case
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
SearchCriteria<AccountVO> sc = sb.create();
if (keyword != null) {
SearchCriteria<AccountVO> ssc = _accountDao.createSearchCriteria();
ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("accountName", SearchCriteria.Op.SC, ssc);
}
if (accountName != null) {
sc.setParameters("accountName", "%" + accountName + "%");
}
if (accountId != null) {
sc.setParameters("id", accountId);
} else if (domainId != null) {
DomainVO domain = _domainDao.findById(domainId);
// I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
sc.setParameters("nid", 1L);
} else {
sc.setParameters("nid", 1L);
}
if (type != null) {
sc.setParameters("type", type);
}
if (state != null) {
sc.setParameters("state", state);
}
if (isCleanupRequired != null) {
sc.setParameters("needsCleanup", isCleanupRequired);
}
return _accountDao.search(sc, searchFilter);
}
@Override
public Account findAccountByIpAddress(String ipAddress) {
IPAddressVO address = _publicIpAddressDao.findById(ipAddress);
if ((address != null) && (address.getAllocatedToAccountId() != null)) {
return _accountDao.findById(address.getAllocatedToAccountId());
}
return null;
}
@Override
public boolean deleteLimit(Long limitId) {
// A limit ID must be passed in
if (limitId == null) {
return false;
}
return _resourceLimitDao.expunge(limitId);
}
@Override
public ResourceLimitVO findLimitById(long limitId) {
return _resourceLimitDao.findById(limitId);
}
@Override
public List<VMTemplateVO> listIsos(Criteria c) {
Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
Boolean ready = (Boolean) c.getCriteria(Criteria.READY);
Boolean isPublic = (Boolean) c.getCriteria(Criteria.ISPUBLIC);
Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);
Object keyword = c.getCriteria(Criteria.KEYWORD);
SearchCriteria<VMTemplateVO> sc = _templateDao.createSearchCriteria();
if (keyword != null) {
SearchCriteria<VMTemplateVO> ssc = _templateDao.createSearchCriteria();
ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (creator != null) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, creator);
}
if (ready != null) {
sc.addAnd("ready", SearchCriteria.Op.EQ, ready);
}
if (isPublic != null) {
sc.addAnd("publicTemplate", SearchCriteria.Op.EQ, isPublic);
}
sc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO);
return _templateDao.search(sc, searchFilter);
}
@Override
public List<VMInstanceVO> findVMInstancesLike(String vmInstanceName) {
return _vmInstanceDao.findVMInstancesLike(vmInstanceName);
}
@Override
public VMInstanceVO findVMInstanceById(long vmId) {
return _vmInstanceDao.findById(vmId);
}
@Override
public UserVmVO findUserVMInstanceById(long userVmId) {
return _userVmDao.findById(userVmId);
}
@Override
public ServiceOfferingVO findServiceOfferingById(long offeringId) {
return _offeringsDao.findById(offeringId);
}
@Override
public List<ServiceOfferingVO> listAllServiceOfferings() {
return _offeringsDao.listAllIncludingRemoved();
}
@Override
public List<HostVO> listAllActiveHosts() {
return _hostDao.listAll();
}
@Override
public DataCenterVO findDataCenterById(long dataCenterId) {
return _dcDao.findById(dataCenterId);
}
@Override
public VMTemplateVO updateTemplate(UpdateIsoCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
return updateTemplateOrIso(cmd);
}
@Override
public VMTemplateVO updateTemplate(UpdateTemplateCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
return updateTemplateOrIso(cmd);
}
private VMTemplateVO updateTemplateOrIso(UpdateTemplateOrIsoCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
Long id = cmd.getId();
String name = cmd.getTemplateName();
String displayText = cmd.getDisplayText();
String format = cmd.getFormat();
Long guestOSId = cmd.getOsTypeId();
Boolean passwordEnabled = cmd.isPasswordEnabled();
Boolean bootable = cmd.isBootable();
Account account= UserContext.current().getAccount();
//verify that template exists
VMTemplateVO template = findTemplateById(id);
if (template == null) {
throw new InvalidParameterValueException("unable to find template/iso with id " + id);
}
//Don't allow to modify system template
if (id == Long.valueOf(1)) {
throw new InvalidParameterValueException("Unable to update template/iso with id " + id);
}
//do a permission check
if (account != null) {
Long templateOwner = template.getAccountId();
if (!BaseCmd.isAdmin(account.getType())) {
if ((templateOwner == null) || (account.getId() != templateOwner.longValue())) {
throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied.");
}
} else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
Long templateOwnerDomainId = findDomainIdByAccountId(templateOwner);
if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied");
}
}
}
boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null && bootable == null);
if (!updateNeeded) {
return template;
}
template = _templateDao.createForUpdate(id);
if (name != null) {
template.setName(name);
}
if (displayText != null) {
template.setDisplayText(displayText);
}
ImageFormat imageFormat = null;
if (format != null) {
try {
imageFormat = ImageFormat.valueOf(format.toUpperCase());
} catch (IllegalArgumentException e) {
throw new InvalidParameterValueException("Image format: " + format + " is incorrect. Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
}
template.setFormat(imageFormat);
}
if (guestOSId != null) {
GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
if (guestOS == null) {
throw new InvalidParameterValueException("Please specify a valid guest OS ID.");
} else {
template.setGuestOSId(guestOSId);
}
}
if (passwordEnabled != null) {
template.setEnablePassword(passwordEnabled);
}
if (bootable != null) {
template.setBootable(bootable);
}
_templateDao.update(id, template);
return _templateDao.findById(id);
}
@Override
public boolean copyTemplate(long userId, long templateId, long sourceZoneId, long destZoneId, long startEventId) {
boolean success = false;
try {
success = _tmpltMgr.copy(userId, templateId, sourceZoneId, destZoneId, startEventId);
} catch (Exception e) {
s_logger.warn("Unable to copy template " + templateId + " from zone " + sourceZoneId + " to " + destZoneId , e);
success = false;
}
return success;
}
@Override
public VMTemplateVO findTemplateById(long templateId) {
return _templateDao.findById(templateId);
}
@Override
public List<UserVmVO> searchForUserVMs(ListVMsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
Account account = UserContext.current().getAccount();
Long domainId = cmd.getDomainId();
String accountName = cmd.getAccountName();
Long accountId = null;
boolean isAdmin = false;
String path = null;
if ((account == null) || isAdmin(account.getType())) {
isAdmin = true;
if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list virtual machines.");
}
if (accountName != null) {
account = _accountDao.findActiveAccount(accountName, domainId);
if (account == null) {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
accountId = account.getId();
}
}
if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
DomainVO domain = _domainDao.findById(account.getDomainId());
if (domain != null) {
path = domain.getPath();
}
}
} else {
accountId = account.getId();
}
Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
c.addCriteria(Criteria.ID, cmd.getId());
c.addCriteria(Criteria.NAME, cmd.getInstanceName());
c.addCriteria(Criteria.STATE, cmd.getState());
c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());
c.addCriteria(Criteria.GROUPID, cmd.getGroupId());
c.addCriteria(Criteria.FOR_VIRTUAL_NETWORK, cmd.getForVirtualNetwork());
c.addCriteria(Criteria.NETWORKID, cmd.getNetworkId());
if (path != null) {
c.addCriteria(Criteria.PATH, path);
}
// ignore these search requests if it's not an admin
if (isAdmin == true) {
c.addCriteria(Criteria.DOMAINID, domainId);
c.addCriteria(Criteria.PODID, cmd.getPodId());
c.addCriteria(Criteria.HOSTID, cmd.getHostId());
}
if (accountId != null) {
c.addCriteria(Criteria.ACCOUNTID, new Object[] {accountId});
}
c.addCriteria(Criteria.ISADMIN, isAdmin);
return searchForUserVMs(c);
}
@Override
public List<UserVmVO> searchForUserVMs(Criteria c) {
Filter searchFilter = new Filter(UserVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
SearchBuilder<UserVmVO> sb = _userVmDao.createSearchBuilder();
// some criteria matter for generating the join condition
Object[] accountIds = (Object[]) c.getCriteria(Criteria.ACCOUNTID);
Object domainId = c.getCriteria(Criteria.DOMAINID);
// get the rest of the criteria
Object id = c.getCriteria(Criteria.ID);
Object name = c.getCriteria(Criteria.NAME);
Object state = c.getCriteria(Criteria.STATE);
Object notState = c.getCriteria(Criteria.NOTSTATE);
Object zone = c.getCriteria(Criteria.DATACENTERID);
Object pod = c.getCriteria(Criteria.PODID);
Object hostId = c.getCriteria(Criteria.HOSTID);
Object hostName = c.getCriteria(Criteria.HOSTNAME);
Object keyword = c.getCriteria(Criteria.KEYWORD);
Object isAdmin = c.getCriteria(Criteria.ISADMIN);
Object ipAddress = c.getCriteria(Criteria.IPADDRESS);
Object groupId = c.getCriteria(Criteria.GROUPID);
Object useVirtualNetwork = c.getCriteria(Criteria.FOR_VIRTUAL_NETWORK);
Object path = c.getCriteria(Criteria.PATH);
Object networkId = c.getCriteria(Criteria.NETWORKID);
sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
sb.and("name", sb.entity().getHostName(), SearchCriteria.Op.LIKE);
sb.and("stateEQ", sb.entity().getState(), SearchCriteria.Op.EQ);
sb.and("stateNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ);
sb.and("stateNIN", sb.entity().getState(), SearchCriteria.Op.NIN);
sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
sb.and("hostIdEQ", sb.entity().getHostId(), SearchCriteria.Op.EQ);
sb.and("hostIdIN", sb.entity().getHostId(), SearchCriteria.Op.IN);
sb.and("guestIP", sb.entity().getGuestIpAddress(), SearchCriteria.Op.EQ);
if (domainId != null || path != null) {
// if accountId isn't specified, we can do a domain match for the admin case
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("id", domainSearch.entity().getId(), SearchCriteria.Op.EQ);
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
if (groupId != null && (Long)groupId == -1) {
SearchBuilder<InstanceGroupVMMapVO> vmSearch = _groupVMMapDao.createSearchBuilder();
vmSearch.and("instanceId", vmSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
sb.join("vmSearch", vmSearch, sb.entity().getId(), vmSearch.entity().getInstanceId(), JoinBuilder.JoinType.LEFTOUTER);
} else if (groupId != null) {
SearchBuilder<InstanceGroupVMMapVO> groupSearch = _groupVMMapDao.createSearchBuilder();
groupSearch.and("groupId", groupSearch.entity().getGroupId(), SearchCriteria.Op.EQ);
sb.join("groupSearch", groupSearch, sb.entity().getId(), groupSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
}
if (networkId != null) {
SearchBuilder<NicVO> nicSearch = _nicDao.createSearchBuilder();
nicSearch.and("networkId", nicSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
SearchBuilder<NetworkVO> networkSearch = _networkDao.createSearchBuilder();
networkSearch.and("networkId", networkSearch.entity().getId(), SearchCriteria.Op.EQ);
nicSearch.join("networkSearch", networkSearch, nicSearch.entity().getNetworkId(), networkSearch.entity().getId(), JoinBuilder.JoinType.INNER);
sb.join("nicSearch", nicSearch, sb.entity().getId(), nicSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
}
if (useVirtualNetwork != null) {
SearchBuilder<ServiceOfferingVO> serviceSearch = _offeringsDao.createSearchBuilder();
if ((Boolean)useVirtualNetwork){
serviceSearch.and("guestIpType", serviceSearch.entity().getGuestIpType(), SearchCriteria.Op.EQ);
} else {
serviceSearch.and("guestIpType", serviceSearch.entity().getGuestIpType(), SearchCriteria.Op.NEQ);
}
sb.join("serviceSearch", serviceSearch, sb.entity().getServiceOfferingId(), serviceSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
// populate the search criteria with the values passed in
SearchCriteria<UserVmVO> sc = sb.create();
if (groupId != null && (Long)groupId == -1){
sc.setJoinParameters("vmSearch", "instanceId", (Object)null);
} else if (groupId != null ) {
sc.setJoinParameters("groupSearch", "groupId", groupId);
}
if (useVirtualNetwork != null) {
sc.setJoinParameters("serviceSearch", "guestIpType", NetworkOffering.GuestIpType.Virtual.toString());
}
if (keyword != null) {
SearchCriteria<UserVmVO> ssc = _userVmDao.createSearchCriteria();
ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("displayName", SearchCriteria.Op.SC, ssc);
}
if (id != null) {
sc.setParameters("id", id);
}
if (accountIds != null) {
if (accountIds.length == 1) {
if (accountIds[0] != null) {
sc.setParameters("accountIdEQ", accountIds[0]);
}
} else {
sc.setParameters("accountIdIN", accountIds);
}
} else if (domainId != null) {
sc.setJoinParameters("domainSearch", "id", domainId);
}
if (path != null) {
sc.setJoinParameters("domainSearch", "path", path + "%");
}
if (networkId != null) {
sc.setJoinParameters("nicSearch", "networkId", networkId);
}
if (name != null) {
sc.setParameters("name", "%" + name + "%");
}
if (state != null) {
if (notState != null && (Boolean) notState == true) {
sc.setParameters("stateNEQ", state);
} else {
sc.setParameters("stateEQ", state);
}
}
if ((isAdmin != null) && ((Boolean) isAdmin != true)) {
sc.setParameters("stateNIN", "Destroyed", "Expunging");
}
if (zone != null) {
sc.setParameters("dataCenterId", zone);
if(state == null) {
sc.setParameters("stateNEQ", "Destroyed");
}
}
if (pod != null) {
sc.setParameters("podId", pod);
if(state == null) {
sc.setParameters("stateNEQ", "Destroyed");
}
}
if (hostId != null) {
sc.setParameters("hostIdEQ", hostId);
} else {
if (hostName != null) {
List<HostVO> hosts = _hostDao.findHostsLike((String) hostName);
if (hosts != null & !hosts.isEmpty()) {
Long[] hostIds = new Long[hosts.size()];
for (int i = 0; i < hosts.size(); i++) {
HostVO host = hosts.get(i);
hostIds[i] = host.getId();
}
sc.setParameters("hostIdIN", (Object[]) hostIds);
} else {
return new ArrayList<UserVmVO>();
}
}
}
if (ipAddress != null) {
sc.setParameters("guestIP", ipAddress);
}
return _userVmDao.search(sc, searchFilter);
}
@Override
public IPAddressVO findIPAddressById(String ipAddress) {
return _publicIpAddressDao.findById(ipAddress);
}
@Override
public List<EventVO> searchForEvents(ListEventsCmd cmd) throws PermissionDeniedException, InvalidParameterValueException {
Account account = UserContext.current().getAccount();
Long accountId = null;
boolean isAdmin = false;
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
if ((account == null) || isAdmin(account.getType())) {
isAdmin = true;
// validate domainId before proceeding
if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list events.");
}
if (accountName != null) {
Account userAccount = _accountDao.findAccount(accountName, domainId);
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
}
}
} else {
domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
}
} else {
accountId = account.getId();
}
Filter searchFilter = new Filter(EventVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal());
Object type = cmd.getType();
Object level = cmd.getLevel();
Date startDate = cmd.getStartDate();
Date endDate = cmd.getEndDate();
Object keyword = cmd.getKeyword();
Integer entryTime = cmd.getEntryTime();
Integer duration = cmd.getDuration();
if ((entryTime != null) && (duration != null)) {
if (entryTime <= duration){
throw new InvalidParameterValueException("Entry time must be greater than duration");
}
return listPendingEvents(entryTime, duration);
}
SearchBuilder<EventVO> sb = _eventDao.createSearchBuilder();
sb.and("levelL", sb.entity().getLevel(), SearchCriteria.Op.LIKE);
sb.and("levelEQ", sb.entity().getLevel(), SearchCriteria.Op.EQ);
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
sb.and("domainIdEQ", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
sb.and("createDateB", sb.entity().getCreateDate(), SearchCriteria.Op.BETWEEN);
sb.and("createDateG", sb.entity().getCreateDate(), SearchCriteria.Op.GTEQ);
sb.and("createDateL", sb.entity().getCreateDate(), SearchCriteria.Op.LTEQ);
if ((accountId == null) && (accountName == null) && (domainId != null) && isAdmin) {
// if accountId isn't specified, we can do a domain match for the admin case
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
SearchCriteria<EventVO> sc = sb.create();
if (keyword != null) {
SearchCriteria<EventVO> ssc = _eventDao.createSearchCriteria();
ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("level", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("level", SearchCriteria.Op.SC, ssc);
}
if (level != null) {
sc.setParameters("levelEQ", level);
}
if (accountId != null) {
sc.setParameters("accountId", accountId);
} else if (domainId != null) {
if (accountName != null) {
sc.setParameters("domainIdEQ", domainId);
sc.setParameters("accountName", "%" + accountName + "%");
sc.addAnd("removed", SearchCriteria.Op.NULL);
} else if (isAdmin) {
DomainVO domain = _domainDao.findById(domainId);
sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
}
}
if (type != null) {
sc.setParameters("type", type);
}
if (startDate != null && endDate != null) {
startDate = massageDate(startDate, 0, 0, 0);
endDate = massageDate(endDate, 23, 59, 59);
sc.setParameters("createDateB", startDate, endDate);
} else if (startDate != null) {
startDate = massageDate(startDate, 0, 0, 0);
sc.setParameters("createDateG", startDate);
} else if (endDate != null) {
endDate = massageDate(endDate, 23, 59, 59);
sc.setParameters("createDateL", endDate);
}
return _eventDao.searchAllEvents(sc, searchFilter);
}
@Override
public List<DomainRouterVO> listRoutersByHostId(long hostId) {
return _routerDao.listByHostId(hostId);
}
@Override
public List<DomainRouterVO> listAllActiveRouters() {
return _routerDao.listAll();
}
@Override
public List<DomainRouterVO> searchForRouters(ListRoutersCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
Long domainId = cmd.getDomainId();
String accountName = cmd.getAccountName();
Long accountId = null;
Account account = UserContext.current().getAccount();
// validate domainId before proceeding
if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list routers");
}
if (accountName != null) {
Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
}
}
} else {
domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
}
Filter searchFilter = new Filter(DomainRouterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
Object name = cmd.getRouterName();
Object state = cmd.getState();
Object zone = cmd.getZoneId();
Object pod = cmd.getPodId();
Object hostId = cmd.getHostId();
Object keyword = cmd.getKeyword();
SearchBuilder<DomainRouterVO> sb = _routerDao.createSearchBuilder();
sb.and("name", sb.entity().getHostName(), SearchCriteria.Op.LIKE);
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN);
sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ);
if ((accountId == null) && (domainId != null)) {
// if accountId isn't specified, we can do a domain match for the admin case
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
SearchCriteria<DomainRouterVO> sc = sb.create();
if (keyword != null) {
SearchCriteria<DomainRouterVO> ssc = _routerDao.createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (name != null) {
sc.setParameters("name", "%" + name + "%");
}
if (accountId != null) {
sc.setParameters("accountId", accountId);
} else if (domainId != null) {
DomainVO domain = _domainDao.findById(domainId);
sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
}
if (state != null) {
sc.setParameters("state", state);
}
if (zone != null) {
sc.setParameters("dataCenterId", zone);
}
if (pod != null) {
sc.setParameters("podId", pod);
}
if (hostId != null) {
sc.setParameters("hostId", hostId);
}
return _routerDao.search(sc, searchFilter);
}
@Override
public List<ConsoleProxyVO> searchForConsoleProxy(Criteria c) {
Filter searchFilter = new Filter(ConsoleProxyVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
SearchCriteria<ConsoleProxyVO> sc = _consoleProxyDao.createSearchCriteria();
Object id = c.getCriteria(Criteria.ID);
Object name = c.getCriteria(Criteria.NAME);
Object state = c.getCriteria(Criteria.STATE);
Object zone = c.getCriteria(Criteria.DATACENTERID);
Object pod = c.getCriteria(Criteria.PODID);
Object hostId = c.getCriteria(Criteria.HOSTID);
Object keyword = c.getCriteria(Criteria.KEYWORD);
if (keyword != null) {
SearchCriteria<ConsoleProxyVO> ssc = _consoleProxyDao.createSearchCriteria();
ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if(id != null) {
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
if (name != null) {
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
}
if (state != null) {
sc.addAnd("state", SearchCriteria.Op.EQ, state);
}
if (zone != null) {
sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
}
if (pod != null) {
sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
}
if (hostId != null) {
sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
}
return _consoleProxyDao.search(sc, searchFilter);
}
@Override
public List<VolumeVO> searchForVolumes(ListVolumesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
Account account = UserContext.current().getAccount();
Long domainId = cmd.getDomainId();
String accountName = cmd.getAccountName();
Long accountId = null;
boolean isAdmin = false;
if ((account == null) || isAdmin(account.getType())) {
isAdmin = true;
if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list volumes.");
}
if (accountName != null) {
Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domainId);
}
}
} else {
domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
}
} else {
accountId = account.getId();
}
Filter searchFilter = new Filter(VolumeVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
Object id = cmd.getId();
Long vmInstanceId = cmd.getVirtualMachineId();
Object name = cmd.getVolumeName();
Object keyword = cmd.getKeyword();
Object type = cmd.getType();
Object zone = null;
Object pod = null;
//Object host = null; TODO
if (isAdmin) {
zone = cmd.getZoneId();
pod = cmd.getPodId();
// host = cmd.getHostId(); TODO
} else {
domainId = null;
}
// hack for now, this should be done better but due to needing a join I opted to
// do this quickly and worry about making it pretty later
SearchBuilder<VolumeVO> sb = _volumeDao.createSearchBuilder();
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
sb.and("volumeType", sb.entity().getVolumeType(), SearchCriteria.Op.LIKE);
sb.and("instanceId", sb.entity().getInstanceId(), SearchCriteria.Op.EQ);
sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
// Don't return DomR and ConsoleProxy volumes
sb.and("domRNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
sb.and("domPNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
sb.and("domSNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
// Only return Volumes that are in the "Created" state
sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ);
// Only return volumes that are not destroyed
sb.and("destroyed", sb.entity().getDestroyed(), SearchCriteria.Op.EQ);
if ((accountId == null) && (domainId != null)) {
// if accountId isn't specified, we can do a domain match for the admin case
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
// now set the SC criteria...
SearchCriteria<VolumeVO> sc = sb.create();
if (keyword != null) {
SearchCriteria<VolumeVO> ssc = _volumeDao.createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("nameLabel", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("volumeType", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (name != null) {
sc.setParameters("name", "%" + name + "%");
}
if (id != null) {
sc.setParameters("id", id);
}
if (accountId != null) {
sc.setParameters("accountIdEQ", accountId);
} else if (domainId != null) {
DomainVO domain = _domainDao.findById(domainId);
sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
}
if (type != null) {
sc.setParameters("volumeType", "%" + type + "%");
}
if (vmInstanceId != null) {
sc.setParameters("instanceId", vmInstanceId);
}
if (zone != null) {
sc.setParameters("dataCenterId", zone);
}
if (pod != null) {
sc.setParameters("podId", pod);
}
// Don't return DomR and ConsoleProxy volumes
/*
sc.setParameters("domRNameLabel", "r-%");
sc.setParameters("domPNameLabel", "v-%");
sc.setParameters("domSNameLabel", "s-%");
*/
// Only return volumes that are not destroyed
sc.setParameters("destroyed", false);
List<VolumeVO> allVolumes = _volumeDao.search(sc, searchFilter);
List<VolumeVO> returnableVolumes = new ArrayList<VolumeVO>(); //these are ones without domr and console proxy
for(VolumeVO v:allVolumes)
{
VMTemplateVO template = _templateDao.findById(v.getTemplateId());
if(template!=null && (template.getTemplateType() == TemplateType.SYSTEM))
{
//do nothing
}
else
{
returnableVolumes.add(v);
}
}
return returnableVolumes;
}
@Override
public VolumeVO findVolumeByInstanceAndDeviceId(long instanceId, long deviceId) {
VolumeVO volume = _volumeDao.findByInstanceAndDeviceId(instanceId, deviceId).get(0);
if (volume != null && !volume.getDestroyed() && volume.getRemoved() == null) {
return volume;
} else {
return null;
}
}
@Override
public HostPodVO findHostPodById(long podId) {
return _hostPodDao.findById(podId);
}
@Override
public HostVO findSecondaryStorageHosT(long zoneId) {
return _storageMgr.getSecondaryStorageHost(zoneId);
}
@Override
public List<IPAddressVO> searchForIPAddresses(ListPublicIpAddressesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
Account account = UserContext.current().getAccount();
Long domainId = cmd.getDomainId();
String accountName = cmd.getAccountName();
Long accountId = null;
if ((account == null) || isAdmin(account.getType())) {
// validate domainId before proceeding
if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Unable to list IP addresses for domain " + domainId + ", permission denied.");
}
if (accountName != null) {
Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
}
} else {
domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
}
} else {
accountId = account.getId();
}
Boolean isAllocated = cmd.isAllocatedOnly();
if (isAllocated == null) {
isAllocated = Boolean.TRUE;
}
Filter searchFilter = new Filter(IPAddressVO.class, "address", false, cmd.getStartIndex(), cmd.getPageSizeVal());
Object zone = cmd.getZoneId();
Object address = cmd.getIpAddress();
Object vlan = cmd.getVlanId();
Object keyword = cmd.getKeyword();
Object forVirtualNetwork = cmd.isForVirtualNetwork();
SearchBuilder<IPAddressVO> sb = _publicIpAddressDao.createSearchBuilder();
sb.and("accountIdEQ", sb.entity().getAllocatedToAccountId(), SearchCriteria.Op.EQ);
sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
sb.and("address", sb.entity().getAddress(), SearchCriteria.Op.LIKE);
sb.and("vlanDbId", sb.entity().getVlanId(), SearchCriteria.Op.EQ);
if ((accountId == null) && (domainId != null)) {
// if accountId isn't specified, we can do a domain match for the admin case
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getAllocatedInDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
if (forVirtualNetwork != null) {
SearchBuilder<VlanVO> vlanSearch = _vlanDao.createSearchBuilder();
vlanSearch.and("vlanType", vlanSearch.entity().getVlanType(), SearchCriteria.Op.EQ);
sb.join("vlanSearch", vlanSearch, sb.entity().getVlanId(), vlanSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
if ((isAllocated != null) && (isAllocated == true)) {
sb.and("allocated", sb.entity().getAllocatedTime(), SearchCriteria.Op.NNULL);
}
SearchCriteria<IPAddressVO> sc = sb.create();
if (accountId != null) {
sc.setParameters("accountIdEQ", accountId);
} else if (domainId != null) {
DomainVO domain = _domainDao.findById(domainId);
sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
}
if (forVirtualNetwork != null) {
VlanType vlanType = (Boolean) forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
sc.setJoinParameters("vlanSearch", "vlanType", vlanType);
}
if (zone != null) {
sc.setParameters("dataCenterId", zone);
}
if ((address == null) && (keyword != null)) {
address = keyword;
}
if (address != null) {
sc.setParameters("address", address + "%");
}
if (vlan != null) {
sc.setParameters("vlanDbId", vlan);
}
return _publicIpAddressDao.search(sc, searchFilter);
}
@Override
public UserAccount authenticateUser(String username, String password, Long domainId, Map<String, Object[]> requestParameters) {
UserAccount user = null;
if (password != null) {
user = getUserAccount(username, password, domainId);
} else {
String key = getConfigurationValue("security.singlesignon.key");
if (key == null) {
// the SSO key is gone, don't authenticate
return null;
}
String singleSignOnTolerance = getConfigurationValue("security.singlesignon.tolerance.millis");
if (singleSignOnTolerance == null) {
// the SSO tolerance is gone (how much time before/after system time we'll allow the login request to be valid), don't authenticate
return null;
}
long tolerance = Long.parseLong(singleSignOnTolerance);
String signature = null;
long timestamp = 0L;
String unsignedRequest = null;
// - build a request string with sorted params, make sure it's all lowercase
// - sign the request, verify the signature is the same
List<String> parameterNames = new ArrayList<String>();
for (Object paramNameObj : requestParameters.keySet()) {
parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
}
Collections.sort(parameterNames);
try {
for (String paramName : parameterNames) {
// parameters come as name/value pairs in the form String/String[]
String paramValue = ((String[])requestParameters.get(paramName))[0];
if ("signature".equalsIgnoreCase(paramName)) {
signature = paramValue;
} else {
if ("timestamp".equalsIgnoreCase(paramName)) {
String timestampStr = paramValue;
try {
// If the timestamp is in a valid range according to our tolerance, verify the request signature, otherwise return null to indicate authentication failure
timestamp = Long.parseLong(timestampStr);
long currentTime = System.currentTimeMillis();
if (Math.abs(currentTime - timestamp) > tolerance) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Expired timestamp passed in to login, current time = " + currentTime + ", timestamp = " + timestamp);
}
return null;
}
} catch (NumberFormatException nfe) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Invalid timestamp passed in to login: " + timestampStr);
}
return null;
}
}
if (unsignedRequest == null) {
unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
} else {
unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
}
}
}
if ((signature == null) || (timestamp == 0L)) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Missing parameters in login request, signature = " + signature + ", timestamp = " + timestamp);
}
return null;
}
unsignedRequest = unsignedRequest.toLowerCase();
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
mac.init(keySpec);
mac.update(unsignedRequest.getBytes());
byte[] encryptedBytes = mac.doFinal();
String computedSignature = new String(Base64.encodeBase64(encryptedBytes));
boolean equalSig = signature.equals(computedSignature);
if (!equalSig) {
s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
} else {
user = getUserAccount(username, domainId);
}
} catch (Exception ex) {
s_logger.error("Exception authenticating user", ex);
return null;
}
}
if (user != null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("User: " + username + " in domain " + domainId + " has successfully logged in");
}
EventUtils.saveEvent(user.getId(), user.getAccountId(), EventTypes.EVENT_USER_LOGIN, "user has logged in");
return user;
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("User: " + username + " in domain " + domainId + " has failed to log in");
}
return null;
}
}
@Override
public void logoutUser(Long userId) {
UserAccount userAcct = _userAccountDao.findById(userId);
if (userAcct != null) {
EventUtils.saveEvent(userId, userAcct.getAccountId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out");
} // else log some kind of error event? This likely means the user doesn't exist, or has been deleted...
}
@Override
public List<VMTemplateVO> listAllTemplates() {
return _templateDao.listAllIncludingRemoved();
}
@Override
public List<GuestOSVO> listGuestOSByCriteria(ListGuestOsCmd cmd) {
Filter searchFilter = new Filter(GuestOSVO.class, "displayName", true, cmd.getStartIndex(), cmd.getPageSizeVal());
Long id = cmd.getId();
Long osCategoryId = cmd.getOsCategoryId();
SearchBuilder<GuestOSVO> sb = _guestOSDao.createSearchBuilder();
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("categoryId", sb.entity().getCategoryId(), SearchCriteria.Op.EQ);
SearchCriteria<GuestOSVO> sc = sb.create();
if (id != null) {
sc.setParameters("id",id);
}
if (osCategoryId != null) {
sc.setParameters("categoryId", osCategoryId);
}
return _guestOSDao.search(sc, searchFilter);
}
@Override
public List<GuestOSCategoryVO> listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd) {
Filter searchFilter = new Filter(GuestOSCategoryVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
Long id = cmd.getId();
SearchBuilder<GuestOSCategoryVO> sb = _guestOSCategoryDao.createSearchBuilder();
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
SearchCriteria<GuestOSCategoryVO> sc = sb.create();
if (id != null) {
sc.setParameters("id",id);
}
return _guestOSCategoryDao.search(sc, searchFilter);
}
@Override
public String getConfigurationValue(String name) {
return _configDao.getValue(name);
}
@Override
public ConsoleProxyInfo getConsoleProxy(long dataCenterId, long userVmId) {
return _consoleProxyMgr.assignProxy(dataCenterId, userVmId);
}
@Override
public ConsoleProxyVO startConsoleProxy(long instanceId, long startEventId) {
return _consoleProxyMgr.startProxy(instanceId, startEventId);
}
@Override
public ConsoleProxyVO stopConsoleProxy(long instanceId, long startEventId) {
_consoleProxyMgr.stopProxy(instanceId, startEventId);
return _consoleProxyDao.findById(instanceId);
}
@Override
public ConsoleProxyVO rebootConsoleProxy(long instanceId, long startEventId) {
_consoleProxyMgr.rebootProxy(instanceId, startEventId);
return _consoleProxyDao.findById(instanceId);
}
@Override
public String getConsoleAccessUrlRoot(long vmId) {
VMInstanceVO vm = this.findVMInstanceById(vmId);
if (vm != null) {
ConsoleProxyInfo proxy = getConsoleProxy(vm.getDataCenterId(), vmId);
if (proxy != null) {
return proxy.getProxyImageUrl();
}
}
return null;
}
@Override
public Pair<String, Integer> getVncPort(VirtualMachine vm) {
if (vm.getHostId() == null) {
s_logger.warn("VM " + vm.getHostName() + " does not have host, return -1 for its VNC port");
return new Pair<String, Integer>(null, -1);
}
if(s_logger.isTraceEnabled()) {
s_logger.trace("Trying to retrieve VNC port from agent about VM " + vm.getHostName());
}
GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getInstanceName()));
if(answer != null) {
return new Pair<String, Integer>(answer.getAddress(), answer.getPort());
}
return new Pair<String, Integer>(null, -1);
}
@Override
public ConsoleProxyVO findConsoleProxyById(long instanceId) {
return _consoleProxyDao.findById(instanceId);
}
@Override
public List<DomainVO> searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
Long domainId = cmd.getId();
Account account = UserContext.current().getAccount();
String path = null;
if (account != null && account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
DomainVO domain = _domainDao.findById(account.getDomainId());
if (domain != null) {
path = domain.getPath();
}
}
Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
String domainName = cmd.getDomainName();
Integer level = cmd.getLevel();
Object keyword = cmd.getKeyword();
SearchBuilder<DomainVO> sb = _domainDao.createSearchBuilder();
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
sb.and("level", sb.entity().getLevel(), SearchCriteria.Op.EQ);
sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);
SearchCriteria<DomainVO> sc = sb.create();
if (keyword != null) {
SearchCriteria<DomainVO> ssc = _domainDao.createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (domainName != null) {
sc.setParameters("name", "%" + domainName + "%");
}
if (level != null) {
sc.setParameters("level", level);
}
if (domainId != null) {
sc.setParameters("id", domainId);
}
if (path != null) {
sc.setParameters("path", "%" +path+"%");
}
return _domainDao.search(sc, searchFilter);
}
@Override
public List<DomainVO> searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
Long domainId = cmd.getId();
String domainName = cmd.getDomainName();
Boolean isRecursive = cmd.isRecursive();
Object keyword = cmd.getKeyword();
String path = null;
if (isRecursive == null) {
isRecursive = false;
}
Account account = UserContext.current().getAccount();
if (account != null) {
if (domainId != null) {
if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Unable to list domains children for domain id " + domainId + ", permission denied.");
}
} else {
domainId = account.getDomainId();
}
}
DomainVO domain = _domainDao.findById(domainId);
if (domain != null && isRecursive) {
path = domain.getPath();
domainId = null;
}
List<DomainVO> domainList = searchForDomainChildren(searchFilter, domainId, domainName,
keyword, path);
return domainList;
}
private List<DomainVO> searchForDomainChildren(Filter searchFilter,
Long domainId, String domainName, Object keyword, String path) {
SearchCriteria<DomainVO> sc = _domainDao.createSearchCriteria();
if (keyword != null) {
SearchCriteria<DomainVO> ssc = _domainDao.createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (domainId != null) {
sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
}
if (domainName != null) {
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + domainName + "%");
}
if (path != null) {
sc.addAnd("path", SearchCriteria.Op.NEQ, path);
sc.addAnd("path", SearchCriteria.Op.LIKE, path + "%");
}
return _domainDao.search(sc, searchFilter);
}
@Override
public DomainVO createDomain(CreateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
String name = cmd.getDomainName();
Long parentId = cmd.getParentDomainId();
Long ownerId = UserContext.current().getAccount().getId();
Account account = UserContext.current().getAccount();
if (ownerId == null) {
ownerId = Long.valueOf(1);
}
if (parentId == null) {
parentId = Long.valueOf(DomainVO.ROOT_DOMAIN);
}
DomainVO parentDomain = _domainDao.findById(parentId);
if (parentDomain == null) {
throw new InvalidParameterValueException("Unable to create domain " + name + ", parent domain " + parentId + " not found.");
}
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), parentId)) {
throw new PermissionDeniedException("Unable to create domain " + name + ", permission denied.");
}
SearchCriteria<DomainVO> sc = _domainDao.createSearchCriteria();
sc.addAnd("name", SearchCriteria.Op.EQ, name);
sc.addAnd("parent", SearchCriteria.Op.EQ, parentId);
List<DomainVO> domains = _domainDao.search(sc, null);
if ((domains == null) || domains.isEmpty()) {
DomainVO domain = new DomainVO(name, ownerId, parentId);
try {
DomainVO dbDomain = _domainDao.create(domain);
EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " created with owner id = " + ownerId
+ " and parentId " + parentId);
return dbDomain;
} catch (IllegalArgumentException ex) {
EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
+ " and parentId " + parentId);
throw ex;
}
} else {
EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
+ " and parentId " + parentId);
}
return null;
}
@Override
public boolean deleteDomain(DeleteDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
Account account = UserContext.current().getAccount();
Long domainId = cmd.getId();
Boolean cleanup = cmd.getCleanup();
if ((domainId == DomainVO.ROOT_DOMAIN) || ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId))) {
throw new PermissionDeniedException("Unable to delete domain " + domainId + ", permission denied.");
}
try {
DomainVO domain = _domainDao.findById(domainId);
if (domain != null) {
long ownerId = domain.getAccountId();
if ((cleanup != null) && cleanup.booleanValue()) {
boolean success = cleanupDomain(domainId, ownerId);
if (!success) {
EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Failed to clean up domain resources and sub domains, domain with id " + domainId + " was not deleted.");
s_logger.error("Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domainId + ").");
return false;
}
} else {
if (!_domainDao.remove(domainId)) {
EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
s_logger.error("Delete failed on domain " + domain.getName() + " (id: " + domainId + "); please make sure all users and sub domains have been removed from the domain before deleting");
return false;
} else {
EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
}
}
} else {
throw new InvalidParameterValueException("Failed to delete domain nable " + domainId + ", domain not found");
}
return true;
} catch (InvalidParameterValueException ex) {
throw ex;
} catch (Exception ex) {
s_logger.error("Exception deleting domain with id " + domainId, ex);
return false;
}
}
private boolean cleanupDomain(Long domainId, Long ownerId) {
boolean success = true;
{
SearchCriteria<DomainVO> sc = _domainDao.createSearchCriteria();
sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
List<DomainVO> domains = _domainDao.search(sc, null);
// cleanup sub-domains first
for (DomainVO domain : domains) {
success = (success && cleanupDomain(domain.getId(), domain.getAccountId()));
}
}
{
// delete users which will also delete accounts and release resources for those accounts
SearchCriteria<AccountVO> sc = _accountDao.createSearchCriteria();
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
List<AccountVO> accounts = _accountDao.search(sc, null);
for (AccountVO account : accounts) {
SearchCriteria<UserVO> userSc = _userDao.createSearchCriteria();
userSc.addAnd("accountId", SearchCriteria.Op.EQ, account.getId());
List<UserVO> users = _userDao.search(userSc, null);
for (UserVO user : users) {
success = (success && _accountMgr.deleteUserInternal(user.getId(), 0));
}
}
}
// delete the domain itself
boolean deleteDomainSuccess = _domainDao.remove(domainId);
if (!deleteDomainSuccess) {
EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
} else {
EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
}
return success && deleteDomainSuccess;
}
@Override
public DomainVO updateDomain(UpdateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
Long domainId = cmd.getId();
String domainName = cmd.getDomainName();
//check if domain exists in the system
DomainVO domain = _domainDao.findById(domainId);
if (domain == null) {
throw new InvalidParameterValueException("Unable to find domain " + domainId);
} else if (domain.getParent() == null) {
//check if domain is ROOT domain - and deny to edit it
throw new InvalidParameterValueException("ROOT domain can not be edited");
}
// check permissions
Account account = UserContext.current().getAccount();
if ((account != null) && !isChildDomain(account.getDomainId(), domain.getId())) {
throw new PermissionDeniedException("Unable to update domain " + domainId + ", permission denied");
}
if (domainName == null || domainName.equals(domain.getName())) {
return _domainDao.findById(domainId);
}
SearchCriteria<DomainVO> sc = _domainDao.createSearchCriteria();
sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
List<DomainVO> domains = _domainDao.search(sc, null);
if ((domains == null) || domains.isEmpty()) {
//whilst updating a domain name, update its path and update all its children's path
domain = _domainDao.findById(domainId);
String updatedDomainPath = getUpdatedDomainPath(domain.getPath(),domainName);
updateDomainChildren(domain,updatedDomainPath);
_domainDao.update(domainId, domainName, updatedDomainPath);
EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
return _domainDao.findById(domainId);
} else {
domain = _domainDao.findById(domainId);
EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
s_logger.error("Domain with name " + domainName + " already exists in the system");
throw new CloudRuntimeException("Failed to update domain " + domainId);
}
}
private String getUpdatedDomainPath(String oldPath, String newName){
String[] tokenizedPath = oldPath.split("/");
tokenizedPath[tokenizedPath.length-1] = newName;
StringBuilder finalPath = new StringBuilder();
for(String token : tokenizedPath){
finalPath.append(token);
finalPath.append("/");
}
return finalPath.toString();
}
private void updateDomainChildren(DomainVO domain, String updatedDomainPrefix){
List<DomainVO> domainChildren = _domainDao.findAllChildren(domain.getPath(), domain.getId());
//for each child, update the path
for(DomainVO dom : domainChildren){
dom.setPath(dom.getPath().replaceFirst(domain.getPath(), updatedDomainPrefix));
_domainDao.update(dom.getId(), dom);
}
}
@Override
public Long findDomainIdByAccountId(Long accountId) {
if (accountId == null) {
return null;
}
AccountVO account = _accountDao.findById(accountId);
if (account != null) {
return account.getDomainId();
}
return null;
}
@Override
public DomainVO findDomainByPath(String domainPath) {
return _domainDao.findDomainByPath(domainPath);
}
@Override
public List<? extends Alert> searchForAlerts(ListAlertsCmd cmd) {
Filter searchFilter = new Filter(AlertVO.class, "lastSent", false, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchCriteria<AlertVO> sc = _alertDao.createSearchCriteria();
Object type = cmd.getType();
Object keyword = cmd.getKeyword();
if (keyword != null) {
SearchCriteria<AlertVO> ssc = _alertDao.createSearchCriteria();
ssc.addOr("subject", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("subject", SearchCriteria.Op.SC, ssc);
}
if (type != null) {
sc.addAnd("type", SearchCriteria.Op.EQ, type);
}
return _alertDao.search(sc, searchFilter);
}
@Override
public List<CapacityVO> listCapacities(ListCapacityCmd cmd) {
// make sure capacity is accurate before displaying it anywhere
// NOTE: listCapacities is currently called by the UI only, so this
// shouldn't be called much since it checks all hosts/VMs
// to figure out what has been allocated.
_alertMgr.recalculateCapacity();
Filter searchFilter = new Filter(CapacityVO.class, "capacityType", true, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchCriteria<CapacityVO> sc = _capacityDao.createSearchCriteria();
Object type = cmd.getType();
Object zoneId = cmd.getZoneId();
Object podId = cmd.getPodId();
Object hostId = cmd.getHostId();
if (type != null) {
sc.addAnd("capacityType", SearchCriteria.Op.EQ, type);
}
if (zoneId != null) {
sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
}
if (podId != null) {
sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
}
if (hostId != null) {
sc.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId);
}
return _capacityDao.search(sc, searchFilter);
}
@Override
public long getMemoryUsagebyHost(Long hostId) {
long mem = 0;
List<VMInstanceVO> vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.DomainRouter);
mem += vms.size() * _routerRamSize * 1024L * 1024L;
vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.SecondaryStorageVm);
mem += vms.size() * _ssRamSize * 1024L * 1024L;
vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.ConsoleProxy);
mem += vms.size() * _proxyRamSize * 1024L * 1024L;
List<UserVmVO> instances = _userVmDao.listUpByHostId(hostId);
for (UserVmVO vm : instances) {
ServiceOffering so = findServiceOfferingById(vm.getServiceOfferingId());
mem += so.getRamSize() * 1024L * 1024L;
}
return mem;
}
@Override
public DiskOfferingVO findDiskOfferingById(long diskOfferingId) {
return _diskOfferingDao.findById(diskOfferingId);
}
@Override
public List<DiskOfferingVO> findPrivateDiskOffering() {
return _diskOfferingDao.findPrivateDiskOffering();
}
protected boolean templateIsCorrectType(VMTemplateVO template) {
return true;
}
public static boolean isAdmin(short accountType) {
return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
(accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
(accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
}
@Override @DB
public boolean updateTemplatePermissions(UpdateTemplatePermissionsCmd cmd) {
return updateTemplateOrIsoPermissions(cmd);
}
@Override @DB
public boolean updateTemplatePermissions(UpdateIsoPermissionsCmd cmd) {
return updateTemplateOrIsoPermissions(cmd);
}
@DB
protected boolean updateTemplateOrIsoPermissions(UpdateTemplateOrIsoPermissionsCmd cmd) {
Transaction txn = Transaction.currentTxn();
//Input validation
Long id = cmd.getId();
Account account = UserContext.current().getAccount();
List<String> accountNames = cmd.getAccountNames();
Long userId = UserContext.current().getUserId();
Boolean isFeatured = cmd.isFeatured();
Boolean isPublic = cmd.isPublic();
String operation = cmd.getOperation();
String mediaType = "";
VMTemplateVO template = _templateDao.findById(id);
if (template == null || !templateIsCorrectType(template)) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find " + mediaType + " with id " + id);
}
if(cmd instanceof UpdateTemplatePermissionsCmd)
{
mediaType = "template";
if(template.getFormat().equals(ImageFormat.ISO))
{
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please provide a valid template");
}
}
if(cmd instanceof UpdateIsoPermissionsCmd)
{
mediaType = "iso";
if(!template.getFormat().equals(ImageFormat.ISO))
{
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please provide a valid iso");
}
}
if (account != null)
{
if (!isAdmin(account.getType()) && (template.getAccountId() != account.getId())) {
throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
} else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
Long templateOwnerDomainId = findDomainIdByAccountId(template.getAccountId());
if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update permissions for " + mediaType + " with id " + id);
}
}
}
// If command is executed via 8096 port, set userId to the id of System account (1)
if (userId == null) {
userId = Long.valueOf(User.UID_SYSTEM);
}
// If the template is removed throw an error.
if (template.getRemoved() != null){
s_logger.error("unable to update permissions for " + mediaType + " with id " + id + " as it is removed ");
throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id + " as it is removed ");
}
if (id == Long.valueOf(1)) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
}
boolean isAdmin = ((account == null) || isAdmin(account.getType()));
boolean allowPublicUserTemplates = Boolean.parseBoolean(getConfigurationValue("allow.public.user.templates"));
if (!isAdmin && !allowPublicUserTemplates && isPublic != null && isPublic) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private " + mediaType + "s can be created.");
}
// // package up the accountNames as a list
// List<String> accountNameList = new ArrayList<String>();
if (accountNames != null)
{
if ((operation == null) || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset")))
{
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." +
" Given operation is: '" + operation + "'");
}
// StringTokenizer st = new StringTokenizer(accountNames, ",");
// while (st.hasMoreTokens()) {
// accountNameList.add(st.nextToken());
// }
}
Long accountId = template.getAccountId();
if (accountId == null) {
// if there is no owner of the template then it's probably already a public template (or domain private template) so publishing to individual users is irrelevant
throw new InvalidParameterValueException("Update template permissions is an invalid operation on template " + template.getName());
}
VMTemplateVO updatedTemplate = _templateDao.createForUpdate();
if (isPublic != null) {
updatedTemplate.setPublicTemplate(isPublic.booleanValue());
}
if (isFeatured != null) {
updatedTemplate.setFeatured(isFeatured.booleanValue());
}
_templateDao.update(template.getId(), updatedTemplate);
Long domainId;
domainId = (null == account) ? DomainVO.ROOT_DOMAIN : account.getDomainId(); // Account == null for 8096 and so its safe for domainid = ROOT
if ("add".equalsIgnoreCase(operation)) {
txn.start();
for (String accountName : accountNames) {
Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
if (permittedAccount != null) {
if (permittedAccount.getId() == account.getId()) {
continue; // don't grant permission to the template owner, they implicitly have permission
}
LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId());
if (existingPermission == null) {
LaunchPermissionVO launchPermission = new LaunchPermissionVO(id, permittedAccount.getId());
_launchPermissionDao.persist(launchPermission);
}
} else {
txn.rollback();
throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + ", account not found. "
+ "No permissions updated, please verify the account names and retry.");
}
}
txn.commit();
} else if ("remove".equalsIgnoreCase(operation)) {
List<Long> accountIds = new ArrayList<Long>();
for (String accountName : accountNames) {
Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
if (permittedAccount != null) {
accountIds.add(permittedAccount.getId());
}
}
_launchPermissionDao.removePermissions(id, accountIds);
} else if ("reset".equalsIgnoreCase(operation)) {
// do we care whether the owning account is an admin? if the
// owner is an admin, will we still set public to false?
updatedTemplate = _templateDao.createForUpdate();
updatedTemplate.setPublicTemplate(false);
updatedTemplate.setFeatured(false);
_templateDao.update(template.getId(), updatedTemplate);
_launchPermissionDao.removeAllPermissions(id);
}
return true;
}
@Override
public List<String> listTemplatePermissions(ListTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
Account account = UserContext.current().getAccount();
Long domainId = cmd.getDomainId();
String acctName = cmd.getAccountName();
Long id = cmd.getId();
Long accountId = null;
if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
// validate domainId before proceeding
if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list " + cmd.getMediaType() + " permissions.");
}
if (acctName != null) {
Account userAccount = _accountDao.findActiveAccount(acctName, domainId);
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new PermissionDeniedException("Unable to find account " + acctName + " in domain " + domainId);
}
}
}
} else {
accountId = account.getId();
}
VMTemplateVO template = _templateDao.findById(id.longValue());
if (template == null || !templateIsCorrectType(template)) {
throw new InvalidParameterValueException("unable to find " + cmd.getMediaType() + " with id " + id);
}
if (accountId != null && !template.isPublicTemplate()) {
if (account.getType() == Account.ACCOUNT_TYPE_NORMAL && template.getAccountId() != accountId) {
throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
} else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
DomainVO accountDomain = _domainDao.findById(account.getDomainId());
Account templateAccount = _accountDao.findById(template.getAccountId());
DomainVO templateDomain = _domainDao.findById(templateAccount.getDomainId());
if (!templateDomain.getPath().contains(accountDomain.getPath())) {
throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
}
}
}
if (id == Long.valueOf(1)) {
throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
}
List<String> accountNames = new ArrayList<String>();
List<LaunchPermissionVO> permissions = _launchPermissionDao.findByTemplate(id);
if ((permissions != null) && !permissions.isEmpty()) {
for (LaunchPermissionVO permission : permissions) {
Account acct = _accountDao.findById(permission.getAccountId());
accountNames.add(acct.getAccountName());
}
}
return accountNames;
}
private List<DiskOfferingVO> searchDiskOfferingsInternal(Account account, Object name, Object id, Object keyword, Filter searchFilter){
//it was decided to return all offerings for the user's domain, and everything above till root (for normal user or domain admin)
//list all offerings belonging to this domain, and all of its parents
//check the parent, if not null, add offerings for that parent to list
List<DiskOfferingVO> dol = new ArrayList<DiskOfferingVO>();
DomainVO domainRecord = _domainDao.findById(account.getDomainId());
boolean includePublicOfferings = true;
if(domainRecord != null)
{
while(true){
SearchBuilder<DiskOfferingVO> sb = _diskOfferingDao.createSearchBuilder();
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
SearchCriteria<DiskOfferingVO> sc = sb.create();
if (keyword != null) {
includePublicOfferings = false;
SearchCriteria<DiskOfferingVO> ssc = _diskOfferingDao.createSearchCriteria();
ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (name != null) {
includePublicOfferings = false;
sc.setParameters("name", "%" + name + "%");
}
if (id != null) {
includePublicOfferings = false;
sc.setParameters("id", id);
}
//for this domain
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainRecord.getId());
//search and add for this domain
dol.addAll(_diskOfferingDao.search(sc, searchFilter));
//try and move on to the next domain
if(domainRecord.getParent() != null) {
domainRecord = _domainDao.findById(domainRecord.getParent());
}
else {
break;//now we got all the offerings for this user/dom adm
}
}
}else{
s_logger.error("Could not find the domainId for account:"+account.getAccountName());
throw new CloudAuthenticationException("Could not find the domainId for account:"+account.getAccountName());
}
//add all the public offerings to the sol list before returning
if(includePublicOfferings) {
dol.addAll(_diskOfferingDao.findPublicDiskOfferings());
}
return dol;
}
@Override
public List<DiskOfferingVO> searchForDiskOfferings(ListDiskOfferingsCmd cmd) {
//Note
//The list method for offerings is being modified in accordance with discussion with Will/Kevin
//For now, we will be listing the following based on the usertype
//1. For root, we will list all offerings
//2. For domainAdmin and regular users, we will list everything in their domains+parent domains ... all the way till root
Filter searchFilter = new Filter(DiskOfferingVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchBuilder<DiskOfferingVO> sb = _diskOfferingDao.createSearchBuilder();
// SearchBuilder and SearchCriteria are now flexible so that the search builder can be built with all possible
// search terms and only those with criteria can be set. The proper SQL should be generated as a result.
Account account = UserContext.current().getAccount();
Object name = cmd.getDiskOfferingName();
Object id = cmd.getId();
Object keyword = cmd.getKeyword();
Long domainId = cmd.getDomainId();
//Keeping this logic consistent with domain specific zones
//if a domainId is provided, we just return the disk offering associated with this domain
if(domainId != null){
if(account.getType() == Account.ACCOUNT_TYPE_ADMIN){
return _diskOfferingDao.listByDomainId(domainId);//no perm check
}else{
//check if the user's domain == do's domain || user's domain is a child of so's domain
if(isPermissible(account.getDomainId(), domainId)){
//perm check succeeded
return _diskOfferingDao.listByDomainId(domainId);
}else{
throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "The account:"+account.getAccountName()+" does not fall in the same domain hierarchy as the disk offering");
}
}
}
//For non-root users
if((account.getType() == Account.ACCOUNT_TYPE_NORMAL || account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)){
return searchDiskOfferingsInternal(account, name, id, keyword, searchFilter);
}
//For root users, preserving existing flow
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
// FIXME: disk offerings should search back up the hierarchy for available disk offerings...
/*
sb.addAnd("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
if (domainId != null) {
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.addAnd("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId());
}
*/
SearchCriteria<DiskOfferingVO> sc = sb.create();
if (keyword != null) {
SearchCriteria<DiskOfferingVO> ssc = _diskOfferingDao.createSearchCriteria();
ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (name != null) {
sc.setParameters("name", "%" + name + "%");
}
if (id != null) {
sc.setParameters("id", id);
}
// FIXME: disk offerings should search back up the hierarchy for available disk offerings...
/*
if (domainId != null) {
sc.setParameters("domainId", domainId);
//
//DomainVO domain = _domainDao.findById((Long)domainId);
//
// I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
//sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
//
}
*/
return _diskOfferingDao.search(sc, searchFilter);
}
// @Override
// public AsyncJobResult queryAsyncJobResult(QueryAsyncJobResultCmd cmd) throws PermissionDeniedException {
// return queryAsyncJobResult(cmd.getId());
// }
@Override
public AsyncJobResult queryAsyncJobResult(long jobId) throws PermissionDeniedException {
AsyncJobVO job = _asyncMgr.getAsyncJob(jobId);
if (job == null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("queryAsyncJobResult error: Permission denied, invalid job id " + jobId);
}
throw new PermissionDeniedException("Permission denied, invalid job id " + jobId);
}
// treat any requests from API server as trusted requests
if (!UserContext.current().isApiServer() && job.getAccountId() != UserContext.current().getAccount().getId()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Mismatched account id in job and user context, perform further securty check. job id: "
+ jobId + ", job owner account: " + job.getAccountId() + ", accound id in current context: " + UserContext.current().getAccount().getId());
}
Account account = UserContext.current().getAccount();
if (account != null) {
if (isAdmin(account.getType())) {
Account jobAccount = _accountDao.findById(job.getAccountId());
if (jobAccount == null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("queryAsyncJobResult error: Permission denied, account no long exist for account id in context, job id: " + jobId
+ ", accountId " + job.getAccountId());
}
throw new PermissionDeniedException("Permission denied, invalid job ownership, job id: " + jobId);
}
if (!_domainDao.isChildDomain(account.getDomainId(), jobAccount.getDomainId())) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("queryAsyncJobResult error: Permission denied, invalid ownership for job " + jobId + ", job account owner: "
+ job.getAccountId() + " in domain: " + jobAccount.getDomainId() + ", account id in context: " + account.getId() +
" in domain: " + account.getDomainId());
}
throw new PermissionDeniedException("Permission denied, invalid job ownership, job id: " + jobId);
}
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("queryAsyncJobResult error: Permission denied, invalid ownership for job " + jobId + ", job account owner: "
+ job.getAccountId() + ", account id in context: " + account.getId());
}
throw new PermissionDeniedException("Permission denied, invalid job ownership, job id: " + jobId);
}
}
}
return _asyncMgr.queryAsyncJobResult(jobId);
}
@Override
public AsyncJobVO findAsyncJobById(long jobId) {
return _asyncMgr.getAsyncJob(jobId);
}
@Override
public String[] getApiConfig() {
return new String[] { "commands.properties" };
}
protected class AccountCleanupTask implements Runnable {
@Override
public void run() {
try {
GlobalLock lock = GlobalLock.getInternLock("AccountCleanup");
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;
}
Transaction txn = null;
try {
txn = Transaction.open(Transaction.CLOUD_DB);
List<AccountVO> accounts = _accountDao.findCleanups();
s_logger.info("Found " + accounts.size() + " accounts to cleanup");
for (AccountVO account : accounts) {
s_logger.debug("Cleaning up " + account.getId());
try {
_accountMgr.deleteAccount(account);
} catch (Exception e) {
s_logger.error("Skipping due to error on account " + account.getId(), e);
}
}
} catch (Exception e) {
s_logger.error("Exception ", e);
} finally {
if(txn != null) {
txn.close();
}
lock.unlock();
}
} catch (Exception e) {
s_logger.error("Exception ", e);
}
}
}
protected class EventPurgeTask implements Runnable {
@Override
public void run() {
try {
GlobalLock lock = GlobalLock.getInternLock("EventPurge");
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, -_purgeDelay);
Date purgeTime = purgeCal.getTime();
s_logger.debug("Deleting events older than: "+purgeTime.toString());
List<EventVO> oldEvents = _eventDao.listOlderEvents(purgeTime);
s_logger.debug("Found "+oldEvents.size()+" events to be purged");
for (EventVO event : oldEvents){
_eventDao.expunge(event.getId());
}
} catch (Exception e) {
s_logger.error("Exception ", e);
} finally {
lock.unlock();
}
} catch (Exception e) {
s_logger.error("Exception ", e);
}
}
}
@Override
public StoragePoolVO findPoolById(Long id) {
return _poolDao.findById(id);
}
@Override
public List<? extends StoragePoolVO> searchForStoragePools(ListStoragePoolsCmd cmd) {
Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
c.addCriteria(Criteria.CLUSTERID, cmd.getClusterId());
c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
c.addCriteria(Criteria.PATH, cmd.getPath());
c.addCriteria(Criteria.PODID, cmd.getPodId());
c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());
return searchForStoragePools(c);
}
@Override
public List<? extends StoragePoolVO> searchForStoragePools(Criteria c) {
Filter searchFilter = new Filter(StoragePoolVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
SearchCriteria<StoragePoolVO> sc = _poolDao.createSearchCriteria();
Object name = c.getCriteria(Criteria.NAME);
Object host = c.getCriteria(Criteria.HOST);
Object path = c.getCriteria(Criteria.PATH);
Object zone = c.getCriteria(Criteria.DATACENTERID);
Object pod = c.getCriteria(Criteria.PODID);
Object cluster = c.getCriteria(Criteria.CLUSTERID);
Object address = c.getCriteria(Criteria.ADDRESS);
Object keyword = c.getCriteria(Criteria.KEYWORD);
if (keyword != null) {
SearchCriteria<StoragePoolVO> ssc = _poolDao.createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (name != null) {
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
}
if (host != null) {
sc.addAnd("host", SearchCriteria.Op.EQ, host);
}
if (path != null) {
sc.addAnd("path", SearchCriteria.Op.EQ, path);
}
if (zone != null) {
sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
}
if (pod != null) {
sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
}
if (address != null) {
sc.addAnd("hostAddress", SearchCriteria.Op.EQ, address);
}
if (cluster != null) {
sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
}
return _poolDao.search(sc, searchFilter);
}
@Override
public List<String> searchForStoragePoolDetails(long poolId, String value)
{
return _poolDao.searchForStoragePoolDetails(poolId, value);
}
@Override
public List<AsyncJobVO> searchForAsyncJobs(ListAsyncJobsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
Filter searchFilter = new Filter(AsyncJobVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchBuilder<AsyncJobVO> sb = _jobDao.createSearchBuilder();
Object accountId = null;
Long domainId = cmd.getDomainId();
Account account = UserContext.current().getAccount();
if ((account == null) || isAdmin(account.getType())) {
String accountName = cmd.getAccountName();
if ((accountName != null) && (domainId != null)) {
Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new InvalidParameterValueException("Failed to list async jobs for account " + accountName + " in domain " + domainId + "; account not found.");
}
} else if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Failed to list async jobs for domain " + domainId + "; permission denied.");
}
// we can do a domain match for the admin case
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
SearchBuilder<AccountVO> accountSearch = _accountDao.createSearchBuilder();
accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId(), JoinType.INNER);
sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinType.INNER);
}
} else {
accountId = account.getId();
}
Object keyword = cmd.getKeyword();
Object startDate = cmd.getStartDate();
SearchCriteria<AsyncJobVO> sc = _jobDao.createSearchCriteria();
if (keyword != null) {
sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
}
if (accountId != null) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
} else if (domainId != null) {
DomainVO domain = _domainDao.findById(domainId);
sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
}
if (startDate != null) {
sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
}
return _jobDao.search(sc, searchFilter);
}
@Override
public boolean isChildDomain(Long parentId, Long childId) {
return _domainDao.isChildDomain(parentId, childId);
}
public SecondaryStorageVmVO startSecondaryStorageVm(long instanceId, long startEventId) {
return _secStorageVmMgr.startSecStorageVm(instanceId, startEventId);
}
public SecondaryStorageVmVO stopSecondaryStorageVm(long instanceId, long startEventId) {
_secStorageVmMgr.stopSecStorageVm(instanceId, startEventId);
return _secStorageVmDao.findById(instanceId);
}
public SecondaryStorageVmVO rebootSecondaryStorageVm(long instanceId, long startEventId) {
_secStorageVmMgr.rebootSecStorageVm(instanceId, startEventId);
return _secStorageVmDao.findById(instanceId);
}
public boolean destroySecondaryStorageVm(long instanceId, long startEventId) {
return _secStorageVmMgr.destroySecStorageVm(instanceId, startEventId);
}
@Override
public List<SecondaryStorageVmVO> searchForSecondaryStorageVm(Criteria c) {
Filter searchFilter = new Filter(SecondaryStorageVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
SearchCriteria<SecondaryStorageVmVO> sc = _secStorageVmDao.createSearchCriteria();
Object id = c.getCriteria(Criteria.ID);
Object name = c.getCriteria(Criteria.NAME);
Object state = c.getCriteria(Criteria.STATE);
Object zone = c.getCriteria(Criteria.DATACENTERID);
Object pod = c.getCriteria(Criteria.PODID);
Object hostId = c.getCriteria(Criteria.HOSTID);
Object keyword = c.getCriteria(Criteria.KEYWORD);
if (keyword != null) {
SearchCriteria<SecondaryStorageVmVO> ssc = _secStorageVmDao.createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if(id != null) {
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
if (name != null) {
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
}
if (state != null) {
sc.addAnd("state", SearchCriteria.Op.EQ, state);
}
if (zone != null) {
sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
}
if (pod != null) {
sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
}
if (hostId != null) {
sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
}
return _secStorageVmDao.search(sc, searchFilter);
}
@Override @SuppressWarnings({"unchecked", "rawtypes"})
public List<? extends VMInstanceVO> searchForSystemVm(ListSystemVMsCmd cmd) {
Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
c.addCriteria(Criteria.ID, cmd.getId());
c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());
c.addCriteria(Criteria.PODID, cmd.getPodId());
c.addCriteria(Criteria.HOSTID, cmd.getHostId());
c.addCriteria(Criteria.NAME, cmd.getSystemVmName());
c.addCriteria(Criteria.STATE, cmd.getState());
String type = cmd.getSystemVmType();
List systemVMs = new ArrayList();
if (type == null) { //search for all vm types
systemVMs.addAll(searchForConsoleProxy(c));
systemVMs.addAll(searchForSecondaryStorageVm(c));
} else if((type != null) && (type.equalsIgnoreCase("secondarystoragevm"))) { // search for ssvm
systemVMs.addAll(searchForSecondaryStorageVm(c));
} else if((type != null) && (type.equalsIgnoreCase("consoleproxy"))) { // search for consoleproxy
systemVMs.addAll(searchForConsoleProxy(c));
}
return systemVMs;
}
@Override
public VMInstanceVO findSystemVMById(long instanceId) {
VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(instanceId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
if(systemVm == null) {
return null;
}
if(systemVm.getType() == VirtualMachine.Type.ConsoleProxy) {
return _consoleProxyDao.findById(instanceId);
}
return _secStorageVmDao.findById(instanceId);
}
@Override
public VirtualMachine startSystemVM(StartSystemVMCmd cmd) {
if (_useNewNetworking) {
return startSystemVm(cmd.getId());
}
//verify input
Long id = cmd.getId();
VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
if (systemVm == null) {
throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
}
if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: "+id);
return startConsoleProxy(id, eventId);
} else {
long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_START, "Starting secondary storage Vm Id: "+id);
return startSecondaryStorageVm(id, eventId);
}
}
@Override
public VirtualMachine startSystemVm(long vmId) {
UserContext context = UserContext.current();
long callerId = context.getUserId();
long callerAccountId = context.getAccount().getId();
VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(vmId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
if (systemVm == null) {
throw new InvalidParameterValueException("unable to find a system vm with id " + vmId);
}
if (systemVm.getType() == VirtualMachine.Type.ConsoleProxy) {
long eventId = EventUtils.saveScheduledEvent(callerId, callerAccountId, EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: "+vmId);
return startConsoleProxy(vmId, eventId);
} else if (systemVm.getType() == VirtualMachine.Type.SecondaryStorageVm) {
long eventId = EventUtils.saveScheduledEvent(callerId, callerAccountId, EventTypes.EVENT_SSVM_START, "Starting secondary storage Vm Id: "+vmId);
return startSecondaryStorageVm(vmId, eventId);
} else {
throw new InvalidParameterValueException("Unable to find a system vm: " + vmId);
}
}
@Override
public VirtualMachine stopSystemVm(long vmId) {
UserContext context = UserContext.current();
long callerId = context.getUserId();
long callerAccountId = context.getAccount().getId();
// verify parameters
VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(vmId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
if (systemVm == null) {
throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + vmId);
}
// FIXME: We need to return the system VM from this method, so what do we do with the boolean response from stopConsoleProxy and stopSecondaryStorageVm?
if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
long eventId = EventUtils.saveScheduledEvent(callerId, callerAccountId, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+vmId);
return stopConsoleProxy(vmId, eventId);
} else {
long eventId = EventUtils.saveScheduledEvent(callerId, callerAccountId, EventTypes.EVENT_SSVM_STOP, "stopping secondary storage Vm Id: "+vmId);
return stopSecondaryStorageVm(vmId, eventId);
}
}
@Override
public VMInstanceVO stopSystemVM(StopSystemVmCmd cmd) {
Long id = cmd.getId();
// verify parameters
VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
if (systemVm == null) {
throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
}
// FIXME: We need to return the system VM from this method, so what do we do with the boolean response from stopConsoleProxy and stopSecondaryStorageVm?
if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+id);
return stopConsoleProxy(id, eventId);
} else {
long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_STOP, "stopping secondary storage Vm Id: "+id);
return stopSecondaryStorageVm(id, eventId);
}
}
@Override
public VMInstanceVO rebootSystemVM(RebootSystemVmCmd cmd) {
VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(cmd.getId(), VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
if (systemVm == null) {
throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + cmd.getId());
}
if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: "+cmd.getId());
return rebootConsoleProxy(cmd.getId(), eventId);
} else {
long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_REBOOT, "Rebooting secondary storage vm with Id: "+cmd.getId());
return rebootSecondaryStorageVm(cmd.getId(), eventId);
}
}
private String signRequest(String request, String key) {
try
{
s_logger.info("Request: "+request);
s_logger.info("Key: "+key);
if(key != null && request != null)
{
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),
"HmacSHA1");
mac.init(keySpec);
mac.update(request.getBytes());
byte[] encryptedBytes = mac.doFinal();
return new String ((Base64.encodeBase64(encryptedBytes)));
}
} catch (Exception ex) {
s_logger.error("unable to sign request", ex);
}
return null;
}
@Override
public ArrayList<String> getCloudIdentifierResponse(GetCloudIdentifierCmd cmd) throws InvalidParameterValueException{
Long userId = cmd.getUserId();
//verify that user exists
User user = findUserById(userId);
if ((user == null) || (user.getRemoved() != null)) {
throw new InvalidParameterValueException("Unable to find active user by id " + userId);
}
String cloudIdentifier = _configDao.getValue("cloud.identifier");
if (cloudIdentifier == null) {
cloudIdentifier = "";
}
String signature = "";
try {
//get the user obj to get his secret key
user = getUser(userId);
String secretKey = user.getSecretKey();
String input = cloudIdentifier;
signature = signRequest(input, secretKey);
} catch (Exception e) {
s_logger.warn("Exception whilst creating a signature:"+e);
}
ArrayList<String> cloudParams = new ArrayList<String>();
cloudParams.add(cloudIdentifier);
cloudParams.add(signature);
return cloudParams;
}
@Override
public NetworkGroupVO findNetworkGroupByName(Long accountId, String groupName) {
NetworkGroupVO groupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
return groupVO;
}
@Override
public NetworkGroupVO findNetworkGroupById(long networkGroupId) {
NetworkGroupVO groupVO = _networkSecurityGroupDao.findById(networkGroupId);
return groupVO;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isHypervisorSnapshotCapable() {
return _isHypervisorSnapshotCapable;
}
@Override
public List<EventVO> listPendingEvents(int entryTime, int duration) {
Calendar calMin = Calendar.getInstance();
Calendar calMax = Calendar.getInstance();
calMin.add(Calendar.SECOND, -entryTime);
calMax.add(Calendar.SECOND, -duration);
Date minTime = calMin.getTime();
Date maxTime = calMax.getTime();
List<EventVO> startedEvents = _eventDao.listStartedEvents(minTime, maxTime);
List<EventVO> pendingEvents = new ArrayList<EventVO>();
for (EventVO event : startedEvents){
EventVO completedEvent = _eventDao.findCompletedEvent(event.getId());
if(completedEvent == null){
pendingEvents.add(event);
}
}
return pendingEvents;
}
@Override
public List<PreallocatedLunVO> getPreAllocatedLuns(ListPreallocatedLunsCmd cmd) {
Filter searchFilter = new Filter(PreallocatedLunVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchCriteria<PreallocatedLunVO> sc = _lunDao.createSearchCriteria();
Object targetIqn = cmd.getTargetIqn();
Object scope = cmd.getScope();
if (targetIqn != null) {
sc.addAnd("targetIqn", SearchCriteria.Op.EQ, targetIqn);
}
if (scope == null || scope.toString().equalsIgnoreCase("ALL")) {
return _lunDao.search(sc, searchFilter);
} else if(scope.toString().equalsIgnoreCase("ALLOCATED")) {
sc.addAnd("volumeId", SearchCriteria.Op.NNULL);
sc.addAnd("taken", SearchCriteria.Op.NNULL);
return _lunDao.search(sc, searchFilter);
} else if(scope.toString().equalsIgnoreCase("FREE")) {
sc.addAnd("volumeId", SearchCriteria.Op.NULL);
sc.addAnd("taken", SearchCriteria.Op.NULL);
return _lunDao.search(sc, searchFilter);
}
return null;
}
@Override
public boolean checkLocalStorageConfigVal()
{
String value = _configs.get("use.local.storage");
if(value!=null && value.equalsIgnoreCase("true")) {
return true;
} else {
return false;
}
}
@Override
public boolean checkIfMaintenable(long hostId) {
//get the poolhostref record
List<StoragePoolHostVO> poolHostRecordSet = _poolHostDao.listByHostId(hostId);
if(poolHostRecordSet!=null)
{
//the above list has only 1 record
StoragePoolHostVO poolHostRecord = poolHostRecordSet.get(0);
//get the poolId and get hosts associated in that pool
List<StoragePoolHostVO> hostsInPool = _poolHostDao.listByPoolId(poolHostRecord.getPoolId());
if(hostsInPool!=null && hostsInPool.size()>1)
{
return true; //since there are other hosts to take over as master in this pool
}
}
return false;
}
@Override
public Map<String, String> listCapabilities(ListCapabilitiesCmd cmd) {
Map<String, String> capabilities = new HashMap<String, String>();
String networkGroupsEnabled = _configs.get("direct.attach.network.groups.enabled");
if(networkGroupsEnabled == null) {
networkGroupsEnabled = "false";
}
capabilities.put("networkGroupsEnabled", networkGroupsEnabled);
capabilities.put("cloudStackVersion", getVersion());
return capabilities;
}
@Override
public GuestOSVO getGuestOs(Long guestOsId)
{
return _guestOSDao.findById(guestOsId);
}
@Override
public VolumeVO getRootVolume(Long instanceId)
{
return _volumeDao.findByInstanceAndType(instanceId, Volume.VolumeType.ROOT).get(0);
}
@Override
public long getPsMaintenanceCount(long podId){
List<StoragePoolVO> poolsInTransition = new ArrayList<StoragePoolVO>();
poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));
return poolsInTransition.size();
}
@Override
public boolean isPoolUp(long instanceId){
VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
if(rootVolume!=null){
Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
if(!poolStatus.equals(Status.Up)) {
return false;
} else {
return true;
}
}
return false;
}
@Override
public Long extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException {
Long volumeId = cmd.getId();
String url = cmd.getUrl();
Long zoneId = cmd.getZoneId();
AsyncJobVO job = null; // FIXME: cmd.getJob();
String mode = cmd.getMode();
Account account = UserContext.current().getAccount();
VolumeVO volume = _volumeDao.findById(volumeId);
if (volume == null) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find volume with id " + volumeId);
}
if (_dcDao.findById(zoneId) == null) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid zone.");
}
if(volume.getPoolId() == null){
throw new ServerApiException(BaseCmd.PARAM_ERROR, "The volume doesnt belong to a storage pool so cant extract it");
}
//Extract activity only for detached volumes or for volumes whose instance is stopped
if(volume.getInstanceId() != null && ApiDBUtils.findVMInstanceById(volume.getInstanceId()).getState() != State.Stopped ){
s_logger.debug("Invalid state of the volume with ID: " + volumeId + ". It should be either detached or the VM should be in stopped state.");
throw new PermissionDeniedException("Invalid state of the volume with ID: " + volumeId + ". It should be either detached or the VM should be in stopped state.");
}
VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
boolean isExtractable = template != null && template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM;
if( !isExtractable && account!=null && account.getType() != Account.ACCOUNT_TYPE_ADMIN){ // Global admins are allowed to extract
throw new PermissionDeniedException("The volume:" +volumeId+ " is not allowed to be extracted");
}
Upload.Mode extractMode;
if( mode == null || (!mode.equals(Upload.Mode.FTP_UPLOAD.toString()) && !mode.equals(Upload.Mode.HTTP_DOWNLOAD.toString())) ){
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid extract Mode ");
}else{
extractMode = mode.equals(Upload.Mode.FTP_UPLOAD.toString()) ? Upload.Mode.FTP_UPLOAD : Upload.Mode.HTTP_DOWNLOAD;
}
if (account != null) {
if(!isAdmin(account.getType())){
if (volume.getAccountId() != account.getId()){
throw new PermissionDeniedException("Unable to find volume with ID: " + volumeId + " for account: " + account.getAccountName());
}
} else {
Account userAccount = _accountDao.findById(volume.getAccountId());
if((userAccount == null) || !_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
throw new PermissionDeniedException("Unable to extract volume:" + volumeId + " - permission denied.");
}
}
}
// If mode is upload perform extra checks on url and also see if there is an ongoing upload on the same.
if (extractMode == Upload.Mode.FTP_UPLOAD){
URI uri = new URI(url);
if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
throw new IllegalArgumentException("Unsupported scheme for url: " + url);
}
String host = uri.getHost();
try {
InetAddress hostAddr = InetAddress.getByName(host);
if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
throw new IllegalArgumentException("Illegal host specified in url");
}
if (hostAddr instanceof Inet6Address) {
throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
}
} catch (UnknownHostException uhe) {
throw new IllegalArgumentException("Unable to resolve " + host);
}
if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Upload.Type.VOLUME) ){
throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
}
}
long userId = UserContext.current().getUserId();
long accountId = volume.getAccountId();
String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId);
StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId());
Long sourceHostId = _storageMgr.findHostIdForStoragePool(srcPool);
List<HostVO> storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
HostVO sserver = storageServers.get(0);
EventUtils.saveStartedEvent(userId, accountId, cmd.getEventType(), "Starting extraction of " +volume.getName()+ " mode:"+mode, cmd.getStartEventId());
List<UploadVO> extractURLList = _uploadDao.listByTypeUploadStatus(volumeId, Upload.Type.VOLUME, UploadVO.Status.DOWNLOAD_URL_CREATED);
if (extractMode == Upload.Mode.HTTP_DOWNLOAD && extractURLList.size() > 0){
return extractURLList.get(0).getId(); // If download url already exists then return
}else {
UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, Upload.Type.VOLUME, url, extractMode);
s_logger.debug("Extract Mode - " +uploadJob.getMode());
uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
// Update the async Job
ExtractResponse resultObj = new ExtractResponse(volumeId, volume.getName(), accountId, UploadVO.Status.COPY_IN_PROGRESS.toString(), uploadJob.getId());
resultObj.setResponseName(cmd.getName());
AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
if (asyncExecutor != null) {
job = asyncExecutor.getJob();
_asyncMgr.updateAsyncJobAttachment(job.getId(), Upload.Type.VOLUME.toString(), volumeId);
_asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
}
// Copy the volume from the source storage pool to secondary storage
CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
// Check if you got a valid answer.
if (cvAnswer == null || !cvAnswer.getResult()) {
String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
//Update the async job.
resultObj.setResultString(errorString);
resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
if (asyncExecutor != null) {
_asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
}
//Update the DB that volume couldn't be copied
uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);
uploadJob.setErrorString(errorString);
uploadJob.setLastUpdated(new Date());
_uploadDao.update(uploadJob.getId(), uploadJob);
EventUtils.saveEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, errorString);
throw new CloudRuntimeException(errorString);
}
String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd";
//Update the DB that volume is copied and volumePath
uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);
uploadJob.setLastUpdated(new Date());
uploadJob.setInstallPath(volumeLocalPath);
_uploadDao.update(uploadJob.getId(), uploadJob);
if (extractMode == Mode.FTP_UPLOAD){ // Now that the volume is copied perform the actual uploading
_uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, cmd.getStartEventId(), job.getId(), _asyncMgr);
return uploadJob.getId();
}else{ // Volume is copied now make it visible under apache and create a URL.
_uploadMonitor.createVolumeDownloadURL(volumeId, volumeLocalPath, Upload.Type.VOLUME, zoneId, uploadJob.getId());
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_INFO, cmd.getEventType(), "Completed extraction of "+volume.getName()+ " in mode:" +mode, null, cmd.getStartEventId());
return uploadJob.getId();
}
}
}
@Override
public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) {
Account account = UserContext.current().getAccount();
Long groupId = cmd.getId();
String groupName = cmd.getGroupName();
// Verify input parameters
InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue());
if (group == null) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a vm group with id " + groupId);
}
if (account != null) {
Account tempAccount = _accountDao.findById(group.getAccountId());
if (!isAdmin(account.getType()) && (account.getId() != group.getAccountId())) {
throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a group with id " + groupId + " for this account");
} else if (!_domainDao.isChildDomain(account.getDomainId(), tempAccount.getDomainId())) {
throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid group id (" + groupId + ") given, unable to update the group.");
}
}
//Check if name is already in use by this account (exclude this group)
boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName);
if (isNameInUse && !group.getName().equals(groupName)) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update vm group, a group with name " + groupName + " already exisits for account");
}
if (groupName != null) {
_vmGroupDao.updateVmGroup(groupId, groupName);
}
InstanceGroupVO vmGroup = _vmGroupDao.findById(groupId);
return vmGroup;
}
@Override
public List<InstanceGroupVO> searchForVmGroups(ListVMGroupsCmd cmd) {
Account account = UserContext.current().getAccount();
Long domainId = cmd.getDomainId();
String accountName = cmd.getAccountName();
Long accountId = null;
if ((account == null) || isAdmin(account.getType())) {
if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list vm groups.");
}
if (accountName != null) {
account = _accountDao.findActiveAccount(accountName, domainId);
if (account == null) {
throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
}
accountId = account.getId();
}
} else {
domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
}
} else {
accountName = account.getAccountName();
accountId = account.getId();
domainId = account.getDomainId();
}
Filter searchFilter = new Filter(InstanceGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
Object id = cmd.getId();
Object name = cmd.getGroupName();
Object keyword = cmd.getKeyword();
SearchBuilder<InstanceGroupVO> sb = _vmGroupDao.createSearchBuilder();
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
if ((accountId == null) && (domainId != null)) {
// if accountId isn't specified, we can do a domain match for the admin case
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
SearchCriteria<InstanceGroupVO> sc = sb.create();
if (keyword != null) {
SearchCriteria<InstanceGroupVO> ssc = _vmGroupDao.createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
}
if (id != null) {
sc.setParameters("id", id);
}
if (name != null) {
sc.setParameters("name", "%" + name + "%");
}
if (accountId != null) {
sc.setParameters("accountId", accountId);
} else if (domainId != null) {
DomainVO domain = _domainDao.findById(domainId);
if (domain != null){
sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
}
}
return _vmGroupDao.search(sc, searchFilter);
}
@Override
public InstanceGroupVO getGroupForVm(long vmId){
return _vmMgr.getGroupForVm(vmId);
}
@Override
public List<VlanVO> searchForZoneWideVlans(long dcId, String vlanType, String vlanId){
return _vlanDao.searchForZoneWideVlans(dcId, vlanType, vlanId);
}
@Override
public String getVersion(){
final Class<?> c = ManagementServer.class;
String fullVersion = c.getPackage().getImplementationVersion();
String version = "unknown";
if(fullVersion.length() > 0){
version = fullVersion.substring(0,fullVersion.lastIndexOf("."));
}
return version;
}
private Long saveScheduledEvent(Long userId, Long accountId, String type, String description)
{
EventVO event = new EventVO();
event.setUserId(userId);
event.setAccountId(accountId);
event.setType(type);
event.setState(Event.State.Scheduled);
event.setDescription("Scheduled async job for "+description);
event = _eventDao.persist(event);
return event.getId();
}
@Override @DB
public String uploadCertificate(UploadCustomCertificateCmd cmd) throws ServerApiException{
CertificateVO cert = null;
Long certVOId = null;
try
{
Transaction.currentTxn();
String certificate = cmd.getCertificate();
cert = _certDao.listAll().get(0); //always 1 record in db (from the deploydb time)
cert = _certDao.acquireInLockTable(cert.getId());
//assign mgmt server id to mark as processing under this ms
if(cert == null){
String msg = "Unable to obtain lock on the cert from uploadCertificate()";
s_logger.error(msg);
throw new ResourceUnavailableException(msg);
}else{
if(cert.getUpdated().equalsIgnoreCase("Y")){
if(s_logger.isDebugEnabled()) {
s_logger.debug("A custom certificate already exists in the DB, will replace it with the new one being uploaded");
}
}else{
if(s_logger.isDebugEnabled()) {
s_logger.debug("No custom certificate exists in the DB, will upload a new one");
}
}
//validate if the cert follows X509 format, if not, don't persist to db
InputStream is = new ByteArrayInputStream(certificate.getBytes("UTF-8"));
BufferedInputStream bis = new BufferedInputStream(is);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
while (bis.available() > 1) {
Certificate localCert = cf.generateCertificate(bis);//throws certexception if not valid cert format
if(s_logger.isDebugEnabled()){
s_logger.debug("The custom certificate generated for validation is:"+localCert.toString());
}
}
certVOId = _certDao.persistCustomCertToDb(certificate,cert,this.getId());//0 implies failure
if(s_logger.isDebugEnabled()) {
s_logger.debug("Custom certificate persisted to the DB");
}
}
if (certVOId != 0)
{
//certficate uploaded to db successfully
//get a list of all Console proxies from the cp table
List<ConsoleProxyVO> cpList = _consoleProxyDao.listAll();
if(cpList.size() == 0){
String msg = "Unable to find any console proxies in the system for certificate update";
s_logger.warn(msg);
throw new ResourceUnavailableException(msg);
}
//get a list of all hosts in host table for type cp
List<HostVO> cpHosts = _hostDao.listByType(com.cloud.host.Host.Type.ConsoleProxy);
if(cpHosts.size() == 0){
String msg = "Unable to find any console proxy hosts in the system for certificate update";
s_logger.warn(msg);
throw new ResourceUnavailableException(msg);
}
//create a hashmap for fast lookup
Map<String,Long> hostNameToHostIdMap = new HashMap<String, Long>();
//updated console proxies id list
List<Long> updatedCpIdList = new ArrayList<Long>();
for(HostVO cpHost : cpHosts){
hostNameToHostIdMap.put(cpHost.getName(), cpHost.getId());
}
for(ConsoleProxyVO cp : cpList)
{
Long cpHostId = hostNameToHostIdMap.get(cp.getHostName());
//now send a command to each console proxy host
UpdateCertificateCommand certCmd = new UpdateCertificateCommand(_certDao.findById(certVOId).getCertificate(), false);
try {
Answer updateCertAns = _agentMgr.send(cpHostId, certCmd);
if(updateCertAns.getResult() == true)
{
//we have the cert copied over on cpvm
long eventId = saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "rebooting console proxy with Id: "+cp.getId());
_consoleProxyMgr.rebootProxy(cp.getId(), eventId);
//when cp reboots, the context will be reinit with the new cert
if(s_logger.isDebugEnabled()) {
s_logger.debug("Successfully updated custom certificate on console proxy vm id:"+cp.getId()+" ,console proxy host id:"+cpHostId);
}
updatedCpIdList.add(cp.getId());
}
} catch (AgentUnavailableException e) {
s_logger.warn("Unable to send update certificate command to the console proxy resource as agent is unavailable for console proxy vm id:"+cp.getId()+" ,console proxy host id:"+cpHostId, e);
} catch (OperationTimedoutException e) {
s_logger.warn("Unable to send update certificate command to the console proxy resource as there was a timeout for console proxy vm id:"+cp.getId()+" ,console proxy host id:"+cpHostId, e);
}
}
if(updatedCpIdList.size() == cpList.size()){
//success case, all updated
return ("Updated:"+updatedCpIdList.size()+" out of:"+cpList.size()+" console proxies");
}else{
//failure case, if even one update fails
throw new ManagementServerException("Updated:"+updatedCpIdList.size()+" out of:"+cpList.size()+" console proxies with successfully updated console proxy ids being:"+(updatedCpIdList.size() > 0 ? updatedCpIdList.toString():""));
}
}
else
{
throw new ManagementServerException("Unable to persist custom certificate to the cloud db");
}
}catch (Exception e) {
s_logger.warn("Failed to successfully update the cert across console proxies on management server:"+this.getId());
if(e instanceof ResourceUnavailableException) {
throw new ServerApiException(BaseCmd.RESOURCE_UNAVAILABLE_ERROR, e.getMessage());
} else if(e instanceof ManagementServerException) {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, e.getMessage());
} else if(e instanceof IndexOutOfBoundsException){
String msg = "Custom certificate record in the db deleted; this should never happen. Please create a new record in the certificate table";
s_logger.error(msg,e);
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, msg);
}
else if(e instanceof FileNotFoundException){
String msg = "Invalid file path for custom cert found during cert validation";
s_logger.error(msg,e);
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, msg);
}
else if(e instanceof CertificateException){
String msg = "The file format for custom cert does not conform to the X.509 specification";
s_logger.error(msg,e);
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, msg);
}
else if(e instanceof UnsupportedEncodingException){
String msg = "Unable to encode the certificate into UTF-8 input stream for validation";
s_logger.error(msg,e);
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, msg);
}
else if(e instanceof IOException){
String msg = "Cannot generate input stream during custom cert validation";
s_logger.error(msg,e);
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, msg);
} else {
String msg = "Cannot upload custom certificate, internal error.";
s_logger.error(msg,e);
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, msg);
}
}finally{
_certDao.releaseFromLockTable(cert.getId());
}
}
@Override
public String[] getHypervisors(ListHypervisorsCmd cmd) {
String hypers = _configDao.getValue(Config.HypervisorList.key());
if (hypers == "" || hypers == null) {
return null;
}
return hypers.split(",");
}
@Override
public List<RemoteAccessVpnVO> searchForRemoteAccessVpns(ListRemoteAccessVpnsCmd cmd) throws InvalidParameterValueException,
PermissionDeniedException {
// do some parameter validation
Account account = UserContext.current().getAccount();
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
Long accountId = null;
Account ipAddressOwner = null;
String ipAddress = cmd.getPublicIp();
if (ipAddress != null) {
IPAddressVO ipAddressVO = _publicIpAddressDao.findById(ipAddress);
if (ipAddressVO == null) {
throw new InvalidParameterValueException("Unable to list remote access vpns, IP address " + ipAddress + " not found.");
} else {
Long ipAddrAcctId = ipAddressVO.getAllocatedToAccountId();
if (ipAddrAcctId == null) {
throw new InvalidParameterValueException("Unable to list remote access vpns, IP address " + ipAddress + " is not associated with an account.");
}
ipAddressOwner = _accountDao.findById(ipAddrAcctId);
}
}
if ((account == null) || isAdmin(account.getType())) {
// validate domainId before proceeding
if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Unable to list remote access vpns for domain id " + domainId + ", permission denied.");
}
if (accountName != null) {
Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
}
} else if (ipAddressOwner != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), ipAddressOwner.getDomainId())) {
throw new PermissionDeniedException("Unable to list remote access vpn for IP address " + ipAddress + ", permission denied.");
}
} else {
domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
}
} else {
accountId = account.getId();
}
Filter searchFilter = new Filter(RemoteAccessVpnVO.class, "vpnServerAddress", true, cmd.getStartIndex(), cmd.getPageSizeVal());
Object id = cmd.getId();
Object zoneId = cmd.getZoneId();
SearchBuilder<RemoteAccessVpnVO> sb = _remoteAccessVpnDao.createSearchBuilder();
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("zoneId", sb.entity().getZoneId(), SearchCriteria.Op.EQ);
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
sb.and("ipAddress", sb.entity().getVpnServerAddress(), SearchCriteria.Op.EQ);
if ((accountId == null) && (domainId != null)) {
// if accountId isn't specified, we can do a domain match for the admin case
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
SearchCriteria<RemoteAccessVpnVO> sc = sb.create();
if (id != null) {
sc.setParameters("id", id);
}
if (ipAddress != null) {
sc.setParameters("ipAddress", ipAddress);
}
if (zoneId != null) {
sc.setParameters("zoneId", zoneId);
}
if (accountId != null) {
sc.setParameters("accountId", accountId);
} else if (domainId != null) {
DomainVO domain = _domainDao.findById(domainId);
sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
}
return _remoteAccessVpnDao.search(sc, searchFilter);
}
@Override
public List<VpnUserVO> searchForVpnUsers(ListVpnUsersCmd cmd) {
Account account = UserContext.current().getAccount();
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
Long accountId = null;
String username = cmd.getUsername();
if ((account == null) || isAdmin(account.getType())) {
// validate domainId before proceeding
if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Unable to list remote access vpn users for domain id " + domainId + ", permission denied.");
}
if (accountName != null) {
Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
}
} else {
domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
}
} else {
accountId = account.getId();
}
Filter searchFilter = new Filter(VpnUserVO.class, "username", true, cmd.getStartIndex(), cmd.getPageSizeVal());
Object id = cmd.getId();
SearchBuilder<VpnUserVO> sb = _vpnUsersDao.createSearchBuilder();
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("username", sb.entity().getUsername(), SearchCriteria.Op.EQ);
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
if ((accountId == null) && (domainId != null)) {
// if accountId isn't specified, we can do a domain match for the admin case
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
SearchCriteria<VpnUserVO> sc = sb.create();
if (id != null) {
sc.setParameters("id", id);
}
if (username != null) {
sc.setParameters("username", username);
}
if (accountId != null) {
sc.setParameters("accountId", accountId);
} else if (domainId != null) {
DomainVO domain = _domainDao.findById(domainId);
sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
}
return _vpnUsersDao.search(sc, searchFilter);
}
@Override
public String getHashKey() {
// although we may have race conditioning here, database transaction serialization should
// give us the same key
if(_hashKey == null) {
_hashKey = _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), UUID.randomUUID().toString());
}
return _hashKey;
}
}