/**
* 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.beans.PropertyDescriptor;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
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.exceptions.APIException;
import com.abiquo.api.exceptions.InternalServerErrorException;
import com.abiquo.api.services.cloud.VirtualMachineService;
import com.abiquo.api.services.stub.NodecollectorServiceStub;
import com.abiquo.api.services.stub.VsmServiceStub;
import com.abiquo.api.tracer.TracerLogger;
import com.abiquo.model.enumerator.HypervisorType;
import com.abiquo.model.enumerator.MachineState;
import com.abiquo.model.enumerator.RemoteServiceType;
import com.abiquo.model.transport.error.CommonError;
import com.abiquo.model.transport.error.ErrorsDto;
import com.abiquo.model.util.AddressingUtils;
import com.abiquo.server.core.cloud.Hypervisor;
import com.abiquo.server.core.cloud.VirtualAppliance;
import com.abiquo.server.core.cloud.VirtualDatacenterRep;
import com.abiquo.server.core.cloud.VirtualMachine;
import com.abiquo.server.core.cloud.VirtualMachineState;
import com.abiquo.server.core.infrastructure.Datacenter;
import com.abiquo.server.core.infrastructure.Datastore;
import com.abiquo.server.core.infrastructure.InfrastructureRep;
import com.abiquo.server.core.infrastructure.Machine;
import com.abiquo.server.core.infrastructure.MachinesToCreateDto;
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.Repository;
import com.abiquo.server.core.infrastructure.UcsRack;
import com.abiquo.server.core.util.network.IPAddress;
import com.abiquo.tracer.ComponentType;
import com.abiquo.tracer.EventType;
import com.abiquo.tracer.SeverityType;
import com.softwarementors.commons.collections.ListUtils;
/*
* THIS CLASS RESOURCE IS USED AS THE DEFAULT ONE TO DEVELOP THE REST AND
* FOR THIS REASON IS OVER-COMMENTED AND DOESN'T HAVE JAVADOC! PLEASE DON'T COPY-PASTE ALL OF THIS
* COMMENTS BECAUSE IS WILL BE SO UGLY TO MAINTAIN THE CODE IN THE API!
*
*/
// Annotate it as a @Service and set the default @Transactional method attributes.
@Service
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public class InfrastructureService extends DefaultApiService
{
private static final Logger LOGGER = LoggerFactory.getLogger(InfrastructureService.class);
public static final String CHECK_RESOURCE = "check";
@Autowired
protected InfrastructureRep repo;
@Autowired
protected RemoteServiceService remoteServiceService;
@Autowired
protected VirtualMachineService virtualMachineService;
@Autowired
protected MachineService machineService;
@Autowired
protected NodecollectorServiceStub nodecollectorServiceStub;
@Autowired
protected VsmServiceStub vsmServiceStub;
@Autowired
protected VirtualDatacenterRep vdcRep;
public InfrastructureService()
{
}
public InfrastructureService(final EntityManager em)
{
repo = new InfrastructureRep(em);
vdcRep = new VirtualDatacenterRep(em);
remoteServiceService = new RemoteServiceService(em);
virtualMachineService = new VirtualMachineService(em);
tracer = new TracerLogger();
}
public InfrastructureService(final EntityManager em,
final NodecollectorServiceStub ncserviceStub)
{
this(em);
nodecollectorServiceStub = ncserviceStub;
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public Rack addRack(final Rack rack, final Integer datacenterId)
{
Datacenter datacenter = this.getDatacenter(datacenterId);
// Check if there is a rack with the same name in the Datacenter
if (repo.existsAnyRackWithName(datacenter, rack.getName()))
{
tracer.log(SeverityType.MINOR, ComponentType.RACK, EventType.RACK_CREATE,
"rack.duplicatedname", rack.getName());
addConflictErrors(APIError.RACK_DUPLICATED_NAME);
flushErrors();
}
// Set the default values if they are not initialized.
if (rack.getVlanIdMin() == null)
{
rack.setVlanIdMin(Rack.VLAN_ID_MIN_DEFAULT_VALUE);
}
if (rack.getVlanIdMax() == null)
{
rack.setVlanIdMax(Rack.VLAN_ID_MAX_DEFAULT_VALUE);
}
if (rack.getVlanPerVdcReserved() == null)
{
rack.setVlanPerVdcReserved(Rack.VLAN_PER_VDC_EXPECTED_DEFAULT_VALUE);
}
if (rack.getNrsq() == null)
{
rack.setNrsq(Rack.NRSQ_DEFAULT_VALUE);
}
if (rack.getNrsq() == null)
{
rack.setNrsq(Rack.NRSQ_DEFAULT_VALUE);
}
// Set the datacenter that belongs to
rack.setDatacenter(datacenter);
// Call the inherited 'validate' function in the DefaultApiService
validate(rack);
repo.insertRack(rack);
tracer.log(SeverityType.INFO, ComponentType.RACK, EventType.RACK_CREATE, "rack.created",
rack.getName());
return rack;
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public List<Machine> addMachines(final List<Machine> machinesToCreate,
final Integer datacenterId, final Integer rackId)
{
List<Machine> machinesCreated = new ArrayList<Machine>();
for (Machine currentMachine : machinesToCreate)
{
machinesCreated.add(addMachine(currentMachine, datacenterId, rackId));
}
return machinesCreated;
}
@Transactional(propagation = Propagation.REQUIRED)
public Map<String, Object> addMachines(final Integer datacenterId, final Integer rackId,
final MachinesToCreateDto createInfo) throws Exception
{
validateCreateInfo(createInfo);
return addMachines(datacenterId, rackId, createInfo.getIpFrom(), createInfo.getIpTo(),
createInfo.getHypervisor(), createInfo.getUser(), createInfo.getPassword(), createInfo
.getPort(), createInfo.getvSwitch());
}
@Transactional(propagation = Propagation.REQUIRED)
public Map<String, Object> addMachines(final Integer datacenterId, final Integer rackId,
final String ipFrom, final String ipTo, final String hypervisor, final String user,
final String password, final Integer port, final String vSwitch)
{
List<Machine> createdMachines = new ArrayList<Machine>();
// Create the IPAddress objects again to check the IP correct format
IPAddress ipFromOK = IPAddress.newIPAddress(ipFrom.toString());
IPAddress ipToOK = IPAddress.newIPAddress(ipTo.toString());
if (ipFromOK.isBiggerThan(ipToOK))
{
addConflictErrors(new CommonError(APIError.MACHINE_INVALID_IP_RANGE.getCode(),
"IP From can not be bigger than IP To!"));
}
// prepare NODE COLLECTOR
// Datacenter datacenter = getDatacenter(datacenterId);
// RemoteService nodecollector =
// getRemoteService(datacenter.getId(), RemoteServiceType.NODE_COLLECTOR);
// getting machines
HypervisorType hyType = HypervisorType.fromValue(hypervisor);
List<Machine> discoveredMachines =
// nodecollectorServiceStub.getRemoteHypervisors(nodecollector, ipFromOK, ipToOK, hyType,
// user, password, port);
this.discoverRemoteHypevisors(datacenterId, ipFromOK, ipToOK, hyType, user, password,
port, vSwitch);
Map<String, Object> map = new HashMap<String, Object>();
Set<CommonError> errors = new HashSet<CommonError>();
// saving machines
for (Machine machine : discoveredMachines)
{
try
{
enableMaxFreeSpaceDatastore(machine);
machine.setVirtualSwitch(vSwitch);
Machine m = addMachine(machine, datacenterId, rackId);
createdMachines.add(m);
}
catch (APIException ex)
{
errors.addAll(addIpInErrors(ex.getErrors(), machine.getHypervisor().getIp()));
}
}
map.put("machines", createdMachines);
if (!errors.isEmpty())
{
map.put("errors", errors);
}
return map;
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Machine addMachine(final Machine machine, final Integer datacenterId,
final Integer rackId)
{
machine.setId(null);
// Gets the rack. It throws the NotFoundException if needed.
Rack rack = getRack(datacenterId, rackId);
Datacenter datacenter = rack.getDatacenter();
UcsRack ucsRack = repo.findUcsRackById(rackId);
if (ucsRack != null)
{
addConflictErrors(APIError.MACHINE_CAN_NOT_BE_ADDED_IN_UCS_RACK);
flushErrors();
}
checkAvailableCores(machine);
Boolean anyEnabled = Boolean.FALSE;
for (Datastore datastore : machine.getDatastores())
{
if (datastore.isEnabled())
{
anyEnabled = Boolean.TRUE;
}
validate(datastore);
// updates shared datastores
List<Datastore> datastoresShared = repo.findShares(datastore);
for (Datastore dstore : datastoresShared)
{
dstore.setSize(datastore.getSize());
dstore.setUsedSize(datastore.getUsedSize());
}
repo.insertDatastore(datastore);
}
if (!anyEnabled)
{
addValidationErrors(APIError.MACHINE_ANY_DATASTORE_DEFINED);
flushErrors();
}
// Insert the machine into database
machine.setDatacenter(datacenter);
machine.setRack(rack);
if (machine.getVirtualSwitch().contains("/"))
{
addValidationErrors(APIError.MACHINE_INVALID_VIRTUAL_SWITCH_NAME);
flushErrors();
}
validate(machine.getHypervisor());
// [ABICLOUDPREMIUM-2996] These values cannot be changed. Must always reflect the real ones.
// Even if the POST to create the machine was made with the information from NodeCollector,
// we need to make sure those values have not been changed.
Machine remoteMachine =
discoverRemoteHypervisor(datacenterId, IPAddress.newIPAddress(machine.getHypervisor()
.getIp()), machine.getHypervisor().getType(), machine.getHypervisor().getUser(),
machine.getHypervisor().getPassword(), machine.getHypervisor().getPort());
machine.setState(remoteMachine.getState());
machine.setVirtualRamInMb(remoteMachine.getVirtualRamInMb());
machine.setVirtualCpuCores(remoteMachine.getVirtualCpuCores());
validate(machine);
// Part 2: Insert the and machine into database.
if (repo
.existAnyHypervisorWithIpInDatacenter(machine.getHypervisor().getIp(), datacenterId))
{
addConflictErrors(APIError.HYPERVISOR_EXIST_IP);
}
if (repo.existAnyHypervisorWithIpServiceInDatacenter(
machine.getHypervisor().getIpService(), datacenterId))
{
addConflictErrors(APIError.HYPERVISOR_EXIST_SERVICE_IP);
}
flushErrors();
repo.insertMachine(machine);
if (machine.getHypervisor().getId() == null || machine.getHypervisor().getId().equals(0))
{
repo.insertHypervisor(machine.getHypervisor());
}
// Get the remote service to monitor the machine
RemoteService vsmRS =
getRemoteService(datacenter.getId(), RemoteServiceType.VIRTUAL_SYSTEM_MONITOR);
vsmServiceStub.monitor(vsmRS, machine.getHypervisor());
tracer.log(SeverityType.INFO, ComponentType.MACHINE, EventType.MACHINE_CREATE,
"machine.created", machine.getName(), machine.getHypervisor().getIp(), machine
.getHypervisor().getType(), machine.getState());
if (machine.getInitiatorIQN() == null)
{
tracer.log(SeverityType.WARNING, ComponentType.MACHINE, EventType.MACHINE_CREATE,
"machine.withoutiqn", machine.getName(), machine.getHypervisor().getIp());
}
return machine;
}
// Return a rack.
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public Rack getRack(final Integer datacenterId, final Integer rackId)
{
// Find the rack by itself and by its datacenter.
Rack rack = repo.findRackByIds(datacenterId, rackId);
if (rack == null)
{
addNotFoundErrors(APIError.NON_EXISTENT_RACK);
flushErrors();
}
return rack;
}
public Rack getRackById(final Integer rackId)
{
// Find the rack by itself and by its datacenter.
Rack rack = repo.findRackById(rackId);
if (rack == null)
{
addNotFoundErrors(APIError.NON_EXISTENT_RACK);
flushErrors();
}
return rack;
}
// GET the list of Racks by Datacenter.
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public List<Rack> getRacksByDatacenter(final Integer datacenterId)
{
return getRacksByDatacenter(datacenterId, null);
}
// GET the list of Racks by Datacenter.
public List<Rack> getRacksByDatacenter(final Integer datacenterId, final String filter)
{
// get the datacenter.
Datacenter datacenter = this.getDatacenter(datacenterId);
return repo.findRacks(datacenter, filter);
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public boolean isAssignedTo(final Integer datacenterId, final Integer rackId)
{
Rack rack = getRack(datacenterId, rackId);
return isAssignedTo(datacenterId, rack);
}
public boolean isAssignedTo(final Integer datacenterId, final Rack rack)
{
return rack != null && rack.getDatacenter().getId().equals(datacenterId);
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public boolean isAssignedTo(final Integer datacenterId, final RemoteServiceType type)
{
RemoteService remoteService = null;
if (type != null)
{
remoteService = getRemoteService(datacenterId, type);
}
return type != null && remoteService != null
&& remoteService.getDatacenter().getId().equals(datacenterId);
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public boolean isAssignedTo(final Integer datacenterId, final String remoteServiceMapping)
{
RemoteServiceType type =
RemoteServiceType.valueFromName(remoteServiceMapping.toUpperCase());
return isAssignedTo(datacenterId, type);
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public Rack modifyRack(final Integer datacenterId, final Integer rackId, final Rack rack)
{
Rack old = getRack(datacenterId, rackId);
// Check
if (repo.existsAnyOtherRackWithName(old, rack.getName()))
{
tracer.log(SeverityType.MINOR, ComponentType.RACK, EventType.RACK_CREATE,
"rack.duplicatedname", rack.getName());
addConflictErrors(APIError.RACK_DUPLICATED_NAME);
flushErrors();
}
old.setName(rack.getName());
old.setShortDescription(rack.getShortDescription());
old.setLongDescription(rack.getLongDescription());
old.setHaEnabled(rack.isHaEnabled());
if (hasVlanConfig(rack))
{
old.setNrsq(rack.getNrsq());
old.setVlanIdMax(rack.getVlanIdMax());
old.setVlanIdMin(rack.getVlanIdMin());
old.setVlanPerVdcReserved(rack.getVlanPerVdcReserved());
old.setVlansIdAvoided(rack.getVlansIdAvoided());
}
validate(old);
repo.updateRack(old);
tracer.log(SeverityType.INFO, ComponentType.RACK, EventType.RACK_MODIFY, "rack.updated",
old.getName(), rack.getName(), rack.getShortDescription(), rack.isHaEnabled() ? "yes"
: "no");
return old;
}
@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public void removeRack(final Rack rack)
{
removeRack(rack, false);
}
@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public void removeRack(final Rack rack, final boolean force)
{
List<Machine> machines = getMachines(rack);
if (machines != null)
{
for (Machine machine : machines)
{
if (machine.getHypervisor() != null)
{
machineService.removeMachine(machine.getId(), force);
}
}
}
deleteMachineRulesFromRack(rack);
repo.deleteRack(rack);
tracer.log(SeverityType.INFO, ComponentType.RACK, EventType.RACK_DELETE, "rack.deleted",
rack.getName());
}
protected void deleteMachineRulesFromRack(final Rack rack)
{
// PREMIUM
}
public List<Machine> getMachines(final Rack rack)
{
return repo.findRackMachines(rack);
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public List<RemoteService> getRemoteServices()
{
return repo.findAllRemoteServices();
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public List<RemoteService> getRemoteServicesByDatacenter(final Integer datacenterId)
{
Datacenter datacenter = repo.findById(datacenterId);
if (datacenter == null)
{
addNotFoundErrors(APIError.NON_EXISTENT_DATACENTER);
flushErrors();
}
return repo.findRemoteServicesByDatacenter(datacenter);
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public RemoteServiceDto addRemoteService(final RemoteService rs, final Integer datacenterId)
{
return remoteServiceService.addRemoteService(rs, datacenterId);
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public RemoteService getRemoteService(final Integer id)
{
return repo.findRemoteServiceById(id);
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public RemoteService getRemoteService(final Integer datacenterId, final RemoteServiceType type)
{
Datacenter datacenter = repo.findById(datacenterId);
if (datacenter == null)
{
addNotFoundErrors(APIError.NON_EXISTENT_DATACENTER);
flushErrors();
}
List<RemoteService> services = repo.findRemoteServiceWithTypeInDatacenter(datacenter, type);
RemoteService remoteService = null;
if (!services.isEmpty())
{
// Only one remote service of each type by datacenter.
remoteService = services.get(0);
}
else
{
addNotFoundErrors(APIError.NON_EXISTENT_REMOTE_SERVICE_TYPE);
flushErrors();
}
return remoteService;
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public RemoteServiceDto modifyRemoteService(final Integer id, final RemoteServiceDto dto)
throws URISyntaxException
{
return remoteServiceService.modifyRemoteService(id, dto);
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public void removeRemoteService(final Integer id)
{
remoteServiceService.removeRemoteService(id);
}
/*
* Get the Datacenter and check if it exists.
*/
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public Datacenter getDatacenter(final Integer datacenterId)
{
Datacenter datacenter = repo.findById(datacenterId);
if (datacenter == null)
{
// Adding the NON_EXISTENT_DATACENTER to the list of NotFoundErrors and flush them.
addNotFoundErrors(APIError.NON_EXISTENT_DATACENTER);
flushErrors();
}
return datacenter;
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public Repository getRepositoryFromLocation(final String location)
{
return repo.findRepositoryByLocation(location);
}
// @Transactional(readOnly = true, propagation = Propagation.REQUIRED)
// public Integer getDatacenterIdByRepository(Repository repository)
// {
// return repository.getDatacenter().getId();
// }
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public Repository getRepository(final Datacenter dc)
{
Repository rep = repo.findRepositoryByDatacenter(dc);
if (rep == null)
{
addConflictErrors(APIError.VIMAGE_DATACENTER_REPOSITORY_NOT_FOUND);
flushErrors();
}
return rep;
}
public Collection<VirtualMachine> getVirtualMachinesByMachine(final Integer machineId)
{
Machine machine = repo.findMachineById(machineId);
return virtualMachineService.findByHypervisor(machine.getHypervisor());
}
@Transactional(propagation = Propagation.REQUIRED)
public void updateUsedResourcesByMachine(final Integer machineId)
{
Machine machine = repo.findMachineById(machineId);
updateUsedResourcesByMachine(machine);
}
public void updateUsedResourcesByMachine(final Machine machine)
{
Collection<VirtualMachine> vms = getVirtualMachinesByMachine(machine.getId());
Integer ramUsed = 0;
Integer cpuUsed = 0;
long hdUsed = 0;
for (VirtualMachine vm : vms)
{
if (vm.getState() != null && !vm.getState().equals(VirtualMachineState.NOT_ALLOCATED))
{
ramUsed += vm.getRam();
cpuUsed += vm.getCpu();
hdUsed += vm.getHdInBytes();
}
}
machine.setVirtualRamUsedInMb(ramUsed);
machine.setVirtualCpusUsed(cpuUsed);
repo.updateMachine(machine);
}
public boolean hasVlanConfig(final Rack rack)
{
return rack.getNrsq() != null && rack.getVlanIdMax() != null && rack.getVlanIdMin() != null
&& rack.getVlanPerVdcReserved() != null;
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public HypervisorType discoverRemoteHypervisorType(final Integer datacenterId, final String ip)
{
Datacenter datacenter = getDatacenter(datacenterId);
RemoteService nodecollector =
getRemoteService(datacenter.getId(), RemoteServiceType.NODE_COLLECTOR);
return nodecollectorServiceStub.getRemoteHypervisorType(nodecollector, ip);
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public Machine discoverRemoteHypervisor(final Integer datacenterId, final IPAddress ip,
final HypervisorType hypType, final String user, final String password, final Integer port)
{
Datacenter datacenter = getDatacenter(datacenterId);
RemoteService nodecollector =
getRemoteService(datacenter.getId(), RemoteServiceType.NODE_COLLECTOR);
Machine machine =
nodecollectorServiceStub.getRemoteHypervisor(nodecollector, ip, hypType, user,
password, port);
return machine;
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public List<Machine> discoverRemoteHypevisors(final Integer datacenterId,
final IPAddress ipFrom, final IPAddress ipTo, final HypervisorType hypType,
final String user, final String password, final Integer port, final String vswitch)
{
Datacenter datacenter = getDatacenter(datacenterId);
RemoteService nodecollector =
getRemoteService(datacenter.getId(), RemoteServiceType.NODE_COLLECTOR);
List<Machine> candidateMachines =
nodecollectorServiceStub.getRemoteHypervisors(nodecollector, ipFrom, ipTo, hypType,
user, password, port);
if (vswitch != null)
{
candidateMachines = filterByVSwitch(candidateMachines, vswitch);
}
// We do not allow machines from ucs to be added if already exists in Abiquo.
return excludeAlreadyInAbiquo(datacenterId, candidateMachines);
}
public MachineState checkMachineState(final Integer datacenterId, final String ip,
final HypervisorType hypervisorType, final String user, final String password,
final Integer port)
{
RemoteService nodecollector =
getRemoteService(datacenterId, RemoteServiceType.NODE_COLLECTOR);
// getting all Virtual Machines from Hypervisor (managed and not managed) (NODE COLLETOR)
Machine m =
nodecollectorServiceStub.getRemoteHypervisor(nodecollector, IPAddress.newIPAddress(ip),
hypervisorType, user, password, port);
return m.getState();
}
public void isStonithUp(final Integer datacenterId, final String ip, final String user,
final String password, final Integer port)
{
RemoteService nodecollector =
getRemoteService(datacenterId, RemoteServiceType.NODE_COLLECTOR);
if (!nodecollectorServiceStub.isStonithUp(nodecollector, ip, port, user, password))
{
addValidationErrors(APIError.MACHINE_INVALID_IPMI_CONF);
flushErrors();
}
}
public void checkAvailableCores(final Machine machine)
{
// PREMIUM
}
// ----------------- //
// ---- PRIVATE ---- //
// ----------------- //
private void enableMaxFreeSpaceDatastore(final Machine machine)
{
if (machine.getDatastores() != null && !machine.getDatastores().isEmpty())
{
Datastore datastoreToEnable = null;
long freeSpace = 0;
for (Datastore d : machine.getDatastores())
{
if (freeSpace < d.getSize() - d.getUsedSize())
{
freeSpace = d.getSize() - d.getUsedSize();
datastoreToEnable = d;
}
}
if (datastoreToEnable != null)
{
datastoreToEnable.setEnabled(true);
}
else
{
// if any datastore has free space, select the first
machine.getDatastores().get(0).setEnabled(true);
}
}
else
{
// no datastores to enable
addConflictErrors(APIError.MACHINE_ANY_DATASTORE_DEFINED);
flushErrors();
}
}
private Set<CommonError> addIpInErrors(final Set<CommonError> errors, final String ip)
{
Set<CommonError> newErrors = new HashSet<CommonError>();
if (errors != null && !errors.isEmpty())
{
for (CommonError commonError : errors)
{
CommonError newError =
new CommonError(commonError.getCode(), "[" + ip + "] "
+ commonError.getMessage());
newErrors.add(newError);
}
}
return newErrors;
}
/**
* @param datacenterId Datacenter id.
* @param candidateMachines machines that we retrieved.
* @return List<Machine> that are not in Abiquo.
*/
protected List<Machine> excludeAlreadyInAbiquo(final Integer datacenterId,
final List<Machine> candidateMachines)
{
List<Machine> machines = new ArrayList<Machine>();
// We do not allow machines from ucs to be added if already exists in Abiquo.
for (Machine m : candidateMachines)
{
if (repo.existAnyHypervisorWithIpInDatacenter(m.getHypervisor().getIp(), datacenterId))
{
LOGGER
.warn("Discovering blades: There is a machine already in Abiquo with this ip!!");
continue;
}
machines.add(m);
}
return machines;
}
/**
* Filters the candidateMachines into the ones that have the vswitch with @param vswitch.
*
* @param candidateMachines candidate machines to be returned.
* @param vswitch name of the switch to filter
*/
protected List<Machine> filterByVSwitch(final List<Machine> candidateMachines,
final String vswitch)
{
List<Machine> filteredVSwitch = new ArrayList<Machine>();
// Filter the machines that doesn't have the switch name
for (Machine currentMachine : candidateMachines)
{
String[] switches = currentMachine.getVirtualSwitch().split("/");
for (String currentSwitch : switches)
{
if (currentSwitch.equalsIgnoreCase(vswitch))
{
// The machine has the vswitch!
currentMachine.setVirtualSwitch(vswitch);
filteredVSwitch.add(currentMachine);
}
}
}
return filteredVSwitch;
}
private void validateCreateInfo(final MachinesToCreateDto dto) throws Exception
{
String[] properties =
{"ipFrom", "ipTo", "hypervisor", "user", "password", "port", "vSwitch"};
for (PropertyDescriptor pd : BeanUtils.getPropertyDescriptors(dto.getClass()))
{
if (ListUtils.createList(properties).contains(pd.getName()))
{
if (pd.getReadMethod().invoke(dto) == null)
{
addValidationErrors(new CommonError(APIError.STATUS_BAD_REQUEST.getCode(), pd
.getName()
+ " can't be null"));
flushErrors();
}
}
}
if (!AddressingUtils.isValidIP(dto.getIpFrom()))
{
addValidationErrors(new CommonError(APIError.STATUS_BAD_REQUEST.getCode(),
"Invalid ip From"));
flushErrors();
}
if (!AddressingUtils.isValidIP(dto.getIpTo()))
{
addValidationErrors(new CommonError(APIError.STATUS_BAD_REQUEST.getCode(),
"Invalid ip To"));
flushErrors();
}
if (IPAddress.newIPAddress(dto.getIpFrom()).isBiggerThan(
IPAddress.newIPAddress(dto.getIpTo())))
{
addValidationErrors(new CommonError(APIError.STATUS_BAD_REQUEST.getCode(),
"ip From can't be bigger than ip To"));
flushErrors();
}
}
/**
* Checks one by one all {@link RemoteService} associated with the @{link Datacenter}.
*
* @param datacenterId
* @return ErrorsDto
*/
public ErrorsDto checkRemoteServiceStatusByDatacenter(final Datacenter datacenter)
{
List<RemoteService> remoteServicesByDatacenter =
getRemoteServicesByDatacenter(datacenter.getId());
ErrorsDto errors = new ErrorsDto();
for (RemoteService r : remoteServicesByDatacenter)
{
ErrorsDto checkRemoteServiceStatus =
remoteServiceService.checkRemoteServiceStatus(datacenter, r.getType(), r.getUri());
errors.addAll(checkRemoteServiceStatus);
}
return errors;
}
/**
* Returns a single virtual machine based on its infrastructure properties and its id.
*
* @param datacenterId identifier of the datacenter
* @param rackId identifier of the rack
* @param machineId identifier of the physical machine
* @param vmId identifier of the virtual machine
* @return the object {@link VirtualMachine} found.
*/
public VirtualMachine getVirtualMachineFromInfrastructure(final Integer datacenterId,
final Integer rackId, final Integer machineId, final Integer vmId)
{
/** check if the machine exists. */
Machine pm = repo.findMachineByIds(datacenterId, rackId, machineId);
if (pm == null)
{
addNotFoundErrors(APIError.NON_EXISTENT_MACHINE);
flushErrors();
}
return virtualMachineService.getVirtualMachineByHypervisor(pm.getHypervisor(), vmId);
}
/**
* Returns the list of virtual machines based on its infrastructure deployment site.
*
* @param datacenterId identifier of the datacenter.
* @param rackId identifier of the rack
* @param machineId identifier of the machin
* @return the list of {@link VirtualMachine} deployed in the physical machine.
*/
public List<VirtualMachine> getVirtualMachinesFromInfrastructure(final Integer datacenterId,
final Integer rackId, final Integer machineId)
{
/** check if the machine exists. */
Machine pm = repo.findMachineByIds(datacenterId, rackId, machineId);
if (pm == null)
{
addNotFoundErrors(APIError.NON_EXISTENT_MACHINE);
flushErrors();
}
return (List<VirtualMachine>) virtualMachineService.findByHypervisor(pm.getHypervisor());
}
/**
* Deletes machine non managed by abiquo.
*
* @param datacenterId
* @param rackId
* @param machineId
* @param trace
*/
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public void deleteNotManagedVirtualMachines(final Integer datacenterId, final Integer rackId,
final Integer machineId)
{
if (!machineService.isAssignedTo(datacenterId, rackId, machineId))
{
addNotFoundErrors(APIError.NOT_ASSIGNED_MACHINE_DATACENTER_RACK);
flushErrors();
}
Hypervisor hypervisor = machineService.getMachine(machineId).getHypervisor();
if (hypervisor == null)
{
addNotFoundErrors(APIError.VIRTUAL_MACHINE_WITHOUT_HYPERVISOR);
flushErrors();
}
deleteNotManagedVirtualMachines(hypervisor);
updateUsedResourcesByMachine(machineId);
if (tracer != null)
{
tracer.log(SeverityType.INFO, ComponentType.MACHINE,
EventType.MACHINE_DELETE_VMS_NOTMANAGED, "virtualMachine.notManagedVMDeleted",
hypervisor.getIp());
}
}
public ErrorsDto checkRemoteServiceStatus(final Datacenter datacenter,
final RemoteServiceType type, final String url)
{
return checkRemoteServiceStatus(datacenter, type, url, false);
}
public ErrorsDto checkRemoteServiceStatus(final Datacenter datacenter,
final RemoteServiceType type, final String url, final boolean flushErrors)
{
return remoteServiceService.checkRemoteServiceStatus(datacenter, type, url, flushErrors);
}
protected void deleteNotManagedVirtualMachines(final Hypervisor hypervisor)
{
List<VirtualMachine> vmachines = repo.getNotManagedVirtualMachines(hypervisor);
RemoteService vsm =
getRemoteService(hypervisor.getMachine().getDatacenter().getId(),
RemoteServiceType.VIRTUAL_SYSTEM_MONITOR);
for (VirtualMachine vm : vmachines)
{
try
{
vsmServiceStub.unsubscribe(vsm, vm);
}
catch (InternalServerErrorException ex)
{
LOGGER
.error(String
.format(
"An unexpected error has ocurred when try to unsubscribe the virtual machine '%s', it probably unsubscribed yet",
vm.getName()));
}
vdcRep.deleteVirtualMachine(vm);
}
}
/**
* We check how many empty machines are in a rack. Then we power on or off to fit the
* configuration. In 2.0 only in {@link UcsRack}.
*
* @param Rack we are deploy void
* @since 2.0
*/
public void adjustPoweredMachinesInRack(final Rack rack)
{
// PREMIUM
}
protected void powerOnMachine(final List<Machine> machines)
{
// PREMIUM
}
protected void shutDownMachine(final List<Machine> machines)
{
// PREMIUM
}
public Machine powerOn(final int machineId)
{
// XXX community impl
LOGGER.error("[powerOn] community not implemented");
return null;
}
public Machine powerOff(final int machineId, final MachineState state)
{
// XXX community impl
LOGGER.error("[powerOff] community not implemented");
return null;
}
@Transactional(readOnly = true)
public VirtualAppliance getVirtualApplianceFromVirtualMachineHelper(final VirtualMachine vm)
{
return vdcRep.findVirtualApplianceByVirtualMachine(vm);
}
}