/**
* Abiquo community edition
* cloud management application for hybrid clouds
* Copyright (C) 2008-2010 - Abiquo Holdings S.L.
*
* This application is free software; you can redistribute it and/or
* modify it under the terms of the GNU LESSER GENERAL PUBLIC
* LICENSE as published by the Free Software Foundation under
* version 3 of the License
*
* This software 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
* LESSER GENERAL PUBLIC LICENSE v.3 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
package com.abiquo.api.services.cloud;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import javax.persistence.EntityManager;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.abiquo.api.config.ConfigService;
import com.abiquo.api.exceptions.APIError;
import com.abiquo.api.resources.cloud.PrivateNetworkResource;
import com.abiquo.api.services.DefaultApiService;
import com.abiquo.api.services.NetworkService;
import com.abiquo.api.services.UserService;
import com.abiquo.api.spring.security.SecurityService;
import com.abiquo.model.enumerator.HypervisorType;
import com.abiquo.model.transport.error.CommonError;
import com.abiquo.server.core.cloud.NodeVirtualImage;
import com.abiquo.server.core.cloud.VirtualDatacenter;
import com.abiquo.server.core.cloud.VirtualDatacenterDto;
import com.abiquo.server.core.cloud.VirtualDatacenterRep;
import com.abiquo.server.core.cloud.VirtualDatacenter.OrderByEnum;
import com.abiquo.server.core.common.Limit;
import com.abiquo.server.core.enterprise.DatacenterLimits;
import com.abiquo.server.core.enterprise.DatacenterLimitsDAO;
import com.abiquo.server.core.enterprise.Enterprise;
import com.abiquo.server.core.enterprise.User;
import com.abiquo.server.core.infrastructure.Datacenter;
import com.abiquo.server.core.infrastructure.InfrastructureRep;
import com.abiquo.server.core.infrastructure.network.DhcpOption;
import com.abiquo.server.core.infrastructure.network.Network;
import com.abiquo.server.core.infrastructure.network.VLANNetwork;
import com.abiquo.server.core.infrastructure.network.VLANNetworkDto;
import com.abiquo.server.core.infrastructure.storage.VolumeManagement;
import com.abiquo.server.core.util.FilterOptions;
@Service
@Transactional(readOnly = true)
public class VirtualDatacenterService extends DefaultApiService
{
public static final String FENCE_MODE = "bridge";
// Used services
@Autowired
UserService userService;
@Autowired
InfrastructureRep datacenterRepo;
// New repos and DAOs
@Autowired
VirtualDatacenterRep repo;
@Autowired
DatacenterLimitsDAO datacenterLimitsDao;
@Autowired
NetworkService networkService;
@Autowired
SecurityService securityService;
public VirtualDatacenterService()
{
}
// use this to initialize it for tests
public VirtualDatacenterService(final EntityManager em)
{
repo = new VirtualDatacenterRep(em);
datacenterRepo = new InfrastructureRep(em);
datacenterLimitsDao = new DatacenterLimitsDAO(em);
userService = new UserService(em);
datacenterLimitsDao = new DatacenterLimitsDAO(em);
securityService = new SecurityService();
networkService = new NetworkService(em);
}
public Collection<VirtualDatacenter> getVirtualDatacenters(final Enterprise enterprise,
final Datacenter datacenter, final FilterOptions filterOptions)
{
User user = userService.getCurrentUser();
return getVirtualDatacenters(enterprise, datacenter, user, filterOptions);
}
public Collection<VirtualDatacenter> getVirtualDatacenters(Enterprise enterprise,
final Datacenter datacenter, final User user, final FilterOptions filterOptions)
{
boolean findByUser =
user != null && !securityService.canManageOtherEnterprises()
&& !securityService.canManageOtherUsers()
&& !StringUtils.isEmpty(user.getAvailableVirtualDatacenters());
if (enterprise == null && user != null)
{
enterprise = user.getEnterprise();
}
if (findByUser)
{
return repo.findByEnterpriseAndDatacenterFilter(enterprise, datacenter, user,
filterOptions);
}
else
{
return repo.findByEnterpriseAndDatacenterFilter(enterprise, datacenter, filterOptions);
}
}
public Collection<VirtualDatacenter> getVirtualDatacentersByDatacenter(
final Datacenter datacenter, final Integer startwith, final Integer limit,
final String filter, final OrderByEnum orderByEnum, final Boolean asc)
{
return repo.findByDatacenter(datacenter, startwith, limit, filter, orderByEnum, asc);
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public VirtualDatacenter getVirtualDatacenter(final Integer id)
{
VirtualDatacenter vdc = repo.findById(id);
if (vdc == null)
{
addNotFoundErrors(APIError.NON_EXISTENT_VIRTUAL_DATACENTER);
flushErrors();
}
return vdc;
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public VirtualDatacenter createVirtualDatacenter(final VirtualDatacenterDto dto,
final Datacenter datacenter, final Enterprise enterprise) throws Exception
{
if (!isValidEnterpriseDatacenter(enterprise, datacenter))
{
addForbiddenErrors(APIError.DATACENTER_NOT_ALLOWED);
flushErrors();
}
Network network = createNetwork();
VirtualDatacenter vdc = createVirtualDatacenter(dto, datacenter, enterprise, network);
// set as default vlan (as it is the first one) and create it.
VLANNetwork vlan =
networkService.createPrivateNetwork(vdc.getId(), PrivateNetworkResource
.createPersistenceObject(dto.getVlan()), false);
// find the default vlan stablished by the enterprise-datacenter limits
DatacenterLimits dcLimits =
datacenterRepo.findDatacenterLimits(vdc.getEnterprise(), vdc.getDatacenter());
if (dcLimits.getDefaultVlan() != null)
{
vdc.setDefaultVlan(dcLimits.getDefaultVlan());
}
else
{
vdc.setDefaultVlan(vlan);
}
repo.update(vdc);
assignVirtualDatacenterToUser(vdc);
return vdc;
}
private void assignVirtualDatacenterToUser(final VirtualDatacenter vdc)
{
User currentUser = userService.getCurrentUser();
// if (currentUser.getRole().getType() == Role.Type.USER
// && currentUser.getAvailableVirtualDatacenters() != null)
if (!securityService.canManageOtherEnterprises()
&& !securityService.canManageOtherUsers()
&& org.springframework.util.StringUtils.hasText(currentUser
.getAvailableVirtualDatacenters()))
{
String availableVirtualDatacenters =
currentUser.getAvailableVirtualDatacenters() + "," + vdc.getId();
currentUser.setAvailableVirtualDatacenters(availableVirtualDatacenters);
userService.updateUser(currentUser);
}
}
protected boolean isValidEnterpriseDatacenter(final Enterprise enterprise,
final Datacenter datacenter)
{
return true;
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public VirtualDatacenter updateVirtualDatacenter(final Integer id,
final VirtualDatacenterDto dto)
{
VirtualDatacenter vdc = getVirtualDatacenter(id);
userService.checkCurrentEnterpriseForPostMethods(vdc.getEnterprise());
return updateVirtualDatacenter(vdc, dto);
}
protected VirtualDatacenter updateVirtualDatacenter(final VirtualDatacenter vdc,
final VirtualDatacenterDto dto)
{
vdc.setName(dto.getName());
setLimits(dto, vdc);
if (!vdc.isValid())
{
addValidationErrors(vdc.getValidationErrors());
flushErrors();
}
if (!isValidVlanHardLimitPerVdc(vdc.getVlanHard()))
{
String vlanXvdc = ConfigService.getSystemProperty(ConfigService.VLAN_PER_VDC);
String errorMsg =
APIError.LIMITS_INVALID_HARD_LIMIT_FOR_VLANS_PER_VDC.getMessage().replace("{0}",
vlanXvdc);
CommonError error =
new CommonError(APIError.LIMITS_INVALID_HARD_LIMIT_FOR_VLANS_PER_VDC.getCode(),
errorMsg);
addConflictErrors(error);
flushErrors();
}
repo.update(vdc);
return vdc;
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public void deleteVirtualDatacenter(final Integer id)
{
VirtualDatacenter vdc = getVirtualDatacenter(id);
userService.checkCurrentEnterpriseForPostMethods(vdc.getEnterprise());
if (repo.containsVirtualAppliances(vdc))
{
addConflictErrors(APIError.VIRTUAL_DATACENTER_CONTAINS_VIRTUAL_APPLIANCES);
}
if (repo.containsResources(vdc, VolumeManagement.DISCRIMINATOR))
{
addConflictErrors(APIError.VIRTUAL_DATACENTER_CONTAINS_RESOURCES);
}
// delete dhcpOption
if (vdc.getDefaultVlan() != null)
{
List<DhcpOption> dhcpList = vdc.getDefaultVlan().getDhcpOption();
if (!dhcpList.isEmpty())
{
datacenterRepo.deleteAllDhcpOption(dhcpList);
}
}
flushErrors();
repo.delete(vdc);
}
private Network createNetwork()
{
Network network = new Network(UUID.randomUUID().toString());
repo.insertNetwork(network);
return network;
}
private VirtualDatacenter createVirtualDatacenter(final VirtualDatacenterDto dto,
final Datacenter datacenter, final Enterprise enterprise, final Network network)
{
VirtualDatacenter vdc =
new VirtualDatacenter(enterprise, datacenter, network, dto.getHypervisorType(), dto
.getName());
setLimits(dto, vdc);
validateVirtualDatacenter(vdc, dto.getVlan(), datacenter);
repo.insert(vdc);
return vdc;
}
private void setLimits(final VirtualDatacenterDto dto, final VirtualDatacenter vdc)
{
vdc.setCpuCountLimits(new Limit((long) dto.getCpuCountSoftLimit(), (long) dto
.getCpuCountHardLimit()));
vdc.setHdLimitsInMb(new Limit(dto.getHdSoftLimitInMb(), dto.getHdHardLimitInMb()));
vdc.setRamLimitsInMb(new Limit((long) dto.getRamSoftLimitInMb(), (long) dto
.getRamHardLimitInMb()));
vdc.setStorageLimits(new Limit(dto.getStorageSoft(), dto.getStorageHard()));
vdc.setVlansLimits(new Limit(dto.getVlansSoft(), dto.getVlansHard()));
vdc.setPublicIPLimits(new Limit(dto.getPublicIpsSoft(), dto.getPublicIpsHard()));
}
private void validateVirtualDatacenter(final VirtualDatacenter vdc, final VLANNetworkDto vlan,
final Datacenter datacenter)
{
if (vlan == null)
{
addValidationErrors(APIError.NETWORK_INVALID_CONFIGURATION);
}
if (!vdc.isValid())
{
addValidationErrors(vdc.getValidationErrors());
}
else if (!isValidVlanHardLimitPerVdc(vdc.getVlanHard()))
{
String vlanXvdc = ConfigService.getSystemProperty(ConfigService.VLAN_PER_VDC);
String errorMsg =
APIError.LIMITS_INVALID_HARD_LIMIT_FOR_VLANS_PER_VDC.getMessage().replace("{0}",
vlanXvdc);
CommonError error =
new CommonError(APIError.LIMITS_INVALID_HARD_LIMIT_FOR_VLANS_PER_VDC.getCode(),
errorMsg);
addValidationErrors(error);
}
if (vdc.getHypervisorType() != null
&& !isValidHypervisorForDatacenter(vdc.getHypervisorType(), datacenter))
{
addValidationErrors(APIError.VIRTUAL_DATACENTER_INVALID_HYPERVISOR_TYPE);
}
flushErrors();
}
private boolean isValidVlanHardLimitPerVdc(final long vlansHard)
{
String limitS = ConfigService.getVlanPerVdc();
int limit = Integer.valueOf(limitS);
return limit == 0 || limit >= vlansHard;
}
private boolean isValidHypervisorForDatacenter(final HypervisorType type,
final Datacenter datacenter)
{
return datacenterRepo.findHypervisors(datacenter).contains(type);
}
public Collection<NodeVirtualImage> getNodeVirtualImageByEnterprise(final Enterprise enterprise)
{
return repo.findNodeVirtualImageByEnterprise(enterprise);
}
public void detach(final VirtualDatacenter virtualDatacenter)
{
repo.detach(virtualDatacenter);
}
}