/**
* 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;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import javax.persistence.EntityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.exceptions.APIError;
import com.abiquo.api.services.cloud.VirtualDatacenterService;
import com.abiquo.api.tracer.TracerLogger;
import com.abiquo.model.enumerator.HypervisorType;
import com.abiquo.model.enumerator.RemoteServiceType;
import com.abiquo.model.transport.SingleResourceTransportDto;
import com.abiquo.model.transport.error.ErrorDto;
import com.abiquo.model.transport.error.ErrorsDto;
import com.abiquo.server.core.cloud.VirtualDatacenter;
import com.abiquo.server.core.enterprise.DatacenterLimits;
import com.abiquo.server.core.enterprise.Enterprise;
import com.abiquo.server.core.enterprise.EnterpriseRep;
import com.abiquo.server.core.infrastructure.Datacenter;
import com.abiquo.server.core.infrastructure.InfrastructureRep;
import com.abiquo.server.core.infrastructure.Machine;
import com.abiquo.server.core.infrastructure.Rack;
import com.abiquo.server.core.infrastructure.RemoteService;
import com.abiquo.server.core.infrastructure.RemoteServiceDto;
import com.abiquo.server.core.infrastructure.RemoteServicesDto;
import com.abiquo.server.core.infrastructure.network.Network;
import com.abiquo.server.core.infrastructure.storage.StorageDevice;
import com.abiquo.server.core.infrastructure.storage.Tier;
import com.abiquo.server.core.pricing.PricingRep;
import com.abiquo.server.core.pricing.PricingTemplate;
import com.abiquo.server.core.pricing.PricingTier;
import com.abiquo.tracer.ComponentType;
import com.abiquo.tracer.EventType;
import com.abiquo.tracer.SeverityType;
@Service
@Transactional(readOnly = true)
public class DatacenterService extends DefaultApiService
{
private static final Logger LOGGER = LoggerFactory.getLogger(DatacenterService.class);
@Autowired
InfrastructureRep repo;
@Autowired
InfrastructureService infrastructureService;
@Autowired
RemoteServiceService remoteServiceService;
@Autowired
VirtualDatacenterService virtualDatacenterService;
@Autowired
UserService userService;
@Autowired
EnterpriseRep enterpriseRep;
@Autowired
PricingRep pricingRep;
public DatacenterService()
{
}
public DatacenterService(final EntityManager em)
{
repo = new InfrastructureRep(em);
infrastructureService = new InfrastructureService(em);
remoteServiceService = new RemoteServiceService(em);
virtualDatacenterService = new VirtualDatacenterService(em);
userService = new UserService(em);
tracer = new TracerLogger();
}
public Collection<Datacenter> getDatacenters(final Enterprise enterprise)
{
Collection<DatacenterLimits> dcLimits = repo.findDatacenterLimits(enterprise);
Set<Datacenter> dcs = new HashSet<Datacenter>();
for (DatacenterLimits dcl : dcLimits)
{
dcs.add(dcl.getDatacenter());
}
return dcs;
}
public Collection<Datacenter> getDatacenters()
{
return repo.findAll();
}
@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public Datacenter addDatacenter(final Datacenter datacenter) throws Exception
{
if (repo.existsAnyDatacenterWithName(datacenter.getName()))
{
tracer.log(SeverityType.MINOR, ComponentType.DATACENTER, EventType.DC_CREATE,
"datacenter.repeated", datacenter.getName());
addConflictErrors(APIError.DATACENTER_DUPLICATED_NAME);
flushErrors();
}
// Create the public network before the datacenter
// This network will store all the public VLANs of the datacenter.
Network network = new Network(UUID.randomUUID().toString());
repo.insertNetwork(network);
isValidDatacenter(datacenter);
datacenter.setNetwork(network);
repo.insert(datacenter);
// Assign datacenter to the own enterprise
DatacenterLimits dcLimits =
new DatacenterLimits(userService.getCurrentUser().getEnterprise(), datacenter);
enterpriseRep.insertLimit(dcLimits);
List<PricingTemplate> pricingTemplateList = pricingRep.findPricingTemplats();
BigDecimal zero = new BigDecimal(0);
// Add the default tiers
for (int i = 1; i <= 4; i++)
{
Tier tier =
new Tier("Default Tier " + i, "Description of the default tier " + i, datacenter);
repo.insertTier(tier);
if (!pricingTemplateList.isEmpty())
{
for (PricingTemplate pt : pricingTemplateList)
{
PricingTier pricingTier = new PricingTier(zero, pt, tier);
pricingRep.insertPricingTier(pricingTier);
}
}
}
// Log the event
tracer.log(SeverityType.INFO, ComponentType.DATACENTER, EventType.DC_CREATE,
"datacenter.created", datacenter.getName(), datacenter.getLocation());
return datacenter;
}
@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public RemoteServicesDto addRemoteServices(final List<RemoteService> remoteServices,
final Datacenter datacenter)
{
// Add the Remote Services in database in case are informed in the request
RemoteServicesDto responseRemoteService = new RemoteServicesDto();
if (remoteServices != null)
{
for (RemoteService rs : remoteServices)
{
SingleResourceTransportDto srtDto =
remoteServiceService.addRemoteService(rs, datacenter);
if (srtDto instanceof RemoteServiceDto)
{
RemoteServiceDto rsDto = (RemoteServiceDto) srtDto;
if (rsDto != null)
{
responseRemoteService.add(rsDto);
if (rsDto.getConfigurationErrors() != null
&& !rsDto.getConfigurationErrors().isEmpty())
{
if (responseRemoteService.getConfigErrors() == null)
{
responseRemoteService.setConfigErrors(new ErrorsDto());
}
responseRemoteService.getConfigErrors().addAll(
rsDto.getConfigurationErrors());
}
}
}
else if (srtDto instanceof ErrorsDto)
{
if (responseRemoteService.getConfigErrors() == null)
{
responseRemoteService.setConfigErrors(new ErrorsDto());
}
responseRemoteService.getConfigErrors().addAll((ErrorsDto) srtDto);
}
}
}
if (responseRemoteService.getConfigErrors() != null
&& !responseRemoteService.getConfigErrors().isEmpty())
{
// Log the event
for (ErrorDto error : responseRemoteService.getConfigErrors().getCollection())
{
tracer.log(SeverityType.MAJOR, ComponentType.DATACENTER,
EventType.REMOTE_SERVICES_ERROR, "remoteServices.down", datacenter.getName(),
error.getMessage());
}
}
else
{
// Log the event
tracer.log(SeverityType.INFO, ComponentType.DATACENTER,
EventType.REMOTE_SERVICES_SUCCESS, "remoteServices.successfulCreation",
datacenter.getName());
}
if (responseRemoteService.getConfigErrors() != null
&& !responseRemoteService.getConfigErrors().isEmpty())
{
// Log the event
tracer
.log(
SeverityType.MAJOR,
ComponentType.DATACENTER,
EventType.DC_CREATE,
"Datacenter '"
+ datacenter.getName()
+ "' has been created but some Remote Services had configuration errors. Please check the events to fix the problems.");
}
else
{
// Log the event
tracer.log(
SeverityType.INFO,
ComponentType.DATACENTER,
EventType.DC_CREATE,
"Datacenter '" + datacenter.getName() + "' has been created in "
+ datacenter.getLocation());
}
return responseRemoteService;
}
public Datacenter getDatacenter(final Integer id)
{
Datacenter datacenter = repo.findById(id);
if (datacenter == null)
{
addNotFoundErrors(APIError.NON_EXISTENT_DATACENTER);
flushErrors();
}
return datacenter;
}
@Transactional(propagation = Propagation.REQUIRED)
public Datacenter modifyDatacenter(final Integer datacenterId, final Datacenter datacenter)
{
Datacenter old = getDatacenter(datacenterId);
if (repo.existsAnyOtherWithName(old, datacenter.getName()))
{
addConflictErrors(APIError.DATACENTER_DUPLICATED_NAME);
flushErrors();
}
old.setName(datacenter.getName());
old.setLocation(datacenter.getLocation());
isValidDatacenter(old);
repo.update(old);
tracer.log(SeverityType.INFO, ComponentType.DATACENTER, EventType.DC_MODIFY,
"datacenter.modified", old.getName(), datacenter.getName(), datacenter.getLocation());
return old;
}
public Set<HypervisorType> getHypervisorTypes(final Datacenter datacenter)
{
return repo.findHypervisors(datacenter);
}
public List<Enterprise> findEnterprisesByDatacenterWithNetworks(final Datacenter datacenter,
final Boolean network, final Integer firstElem, final Integer numElem)
{
return repo.findEnterprisesByDataCenter(datacenter, network, firstElem, numElem);
}
private void isValidDatacenter(final Datacenter datacenter)
{
if (!datacenter.isValid())
{
addValidationErrors(datacenter.getValidationErrors());
}
flushErrors();
}
public List<Rack> getRacks(final Datacenter datacenter)
{
return repo.findRacks(datacenter);
}
public List<Rack> getRacksWithHAEnabled(final Datacenter datacenter)
{
return repo.findRacksWithHAEnabled(datacenter);
}
public List<Machine> getEnabledMachines(final Rack rack)
{
return repo.findRackEnabledForHAMachines(rack);
}
public void removeDatacenter(final Integer id)
{
Datacenter datacenter = repo.findById(id);
if (datacenter == null)
{
addNotFoundErrors(APIError.NON_EXISTENT_DATACENTER);
flushErrors();
}
// only delete the datacenter if it doesn't have any virtual datacenter and any storage
// device associated
Collection<VirtualDatacenter> vdcs =
virtualDatacenterService.getVirtualDatacentersByDatacenter(datacenter, 0, 0, "",
VirtualDatacenter.OrderByEnum.NAME, true);
if (vdcs == null || vdcs.isEmpty())
{
List<StorageDevice> sDevices = getStorageDevices(datacenter);
if (sDevices == null || sDevices.isEmpty())
{
// deleting datacenter
deleteAllocationRules(datacenter);
deleteNetwork(datacenter);
deletePricingTiers(datacenter.getId());
List<Rack> racks = getRacks(datacenter);
if (racks != null)
{
for (Rack rack : racks)
{
infrastructureService.removeRack(rack);
}
}
repo.delete(datacenter);
LOGGER.debug("Deleting datacenter");
tracer.log(SeverityType.INFO, ComponentType.DATACENTER, EventType.DC_DELETE,
"datacenter.removed", datacenter.getName());
}
else
{
tracer.log(SeverityType.CRITICAL, ComponentType.DATACENTER, EventType.DC_DELETE,
"datacenter.withStorageDevices");
addConflictErrors(APIError.DATACENTER_DELETE_STORAGE);
flushErrors();
}
}
else
{
tracer.log(SeverityType.CRITICAL, ComponentType.DATACENTER, EventType.DC_DELETE,
"datacenter.withVDC");
addConflictErrors(APIError.DATACENTER_DELETE_VIRTUAL_DATACENTERS);
flushErrors();
}
}
public boolean isAssignedTo(final Integer datacenterId, final RemoteServiceType type)
{
return infrastructureService.isAssignedTo(datacenterId, type);
}
// overrided on premium
protected List<StorageDevice> getStorageDevices(final Datacenter datacenter)
{
return null;
}
// overrided on premium
protected void deleteAllocationRules(final Datacenter datacenter)
{
}
// overrided on premium
protected void deleteNetwork(final Datacenter datacenter)
{
}
// overrided on premium
protected void deletePricingTiers(final Integer datacenterId)
{
}
}