/**
* 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.stub;
import java.net.SocketTimeoutException;
import java.util.LinkedList;
import java.util.List;
import org.apache.wink.client.ClientRuntimeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.abiquo.api.exceptions.APIError;
import com.abiquo.api.pools.impl.AMClientPool;
import com.abiquo.api.services.DefaultApiService;
import com.abiquo.api.services.EnterpriseService;
import com.abiquo.api.services.InfrastructureService;
import com.abiquo.appliancemanager.client.AMClient;
import com.abiquo.appliancemanager.client.AMClientException;
import com.abiquo.appliancemanager.transport.EnterpriseRepositoryDto;
import com.abiquo.appliancemanager.transport.TemplateDto;
import com.abiquo.appliancemanager.transport.TemplateIdDto;
import com.abiquo.appliancemanager.transport.TemplateIdsDto;
import com.abiquo.appliancemanager.transport.TemplateStateDto;
import com.abiquo.appliancemanager.transport.TemplateStatusEnumType;
import com.abiquo.appliancemanager.transport.TemplatesStateDto;
import com.abiquo.model.enumerator.RemoteServiceType;
import com.abiquo.model.transport.error.CommonError;
import com.abiquo.server.core.enterprise.DatacenterLimits;
@Service
public class AMServiceStub extends DefaultApiService
{
private final static Logger LOGGER = LoggerFactory.getLogger(AMServiceStub.class);
@Autowired
protected AMClientPool clientPool;
@Autowired
protected InfrastructureService infService;
@Autowired
protected EnterpriseService entService;
public TemplateDto getTemplate(final Integer datacenterId, final Integer enterpriseId,
final String ovfId)
{
final AMClient amClient = getAMClient(datacenterId, enterpriseId, false);
try
{
return amClient.getTemplate(enterpriseId, ovfId);
}
catch (Exception e)
{
reportError(e);
return null;// unreachable
}
finally
{
returnClientToPool(amClient);
}
}
public TemplateDto getTemplateBySystem(final Integer datacenterId, final Integer enterpriseId,
final String ovfId)
{
final AMClient amClient = getAMClientBySystem(datacenterId, enterpriseId, false);
try
{
return amClient.getTemplate(enterpriseId, ovfId);
}
catch (Exception e)
{
reportError(e);
return null;// unreachable
}
finally
{
returnClientToPool(amClient);
}
}
public void delete(final Integer datacenterId, final Integer enterpriseId, final String ovfId)
{
final AMClient amClient = getAMClient(datacenterId, enterpriseId, false);
try
{
amClient.deleteTemplate(enterpriseId, ovfId);
}
catch (Exception e)
{
reportError(e);
}
finally
{
returnClientToPool(amClient);
}
}
public String preBundleTemplate(final Integer datacenterId, final Integer enterpriseId,
final String instanceName)
{
final AMClient amClient = getAMClient(datacenterId, enterpriseId, false);
try
{
return amClient.preBundleTemplate(enterpriseId, instanceName);
}
catch (Exception e)
{
reportError(e);
return null;// unreachable
}
finally
{
returnClientToPool(amClient);
}
}
public EnterpriseRepositoryDto getRepository(final Integer datacenterId,
final Integer enterpriseId)
{
final AMClient amClient = getAMClient(datacenterId, enterpriseId, false);
try
{
return amClient.getRepository(enterpriseId);
}
catch (Exception e)
{
reportError(e);
return null;// unreachable
}
finally
{
returnClientToPool(amClient);
}
}
public TemplatesStateDto getTemplatesState(final Integer datacenterId,
final Integer enterpriseId, final String... ovfIds)
{
final AMClient amClient = getAMClient(datacenterId, enterpriseId, false);
try
{
return amClient.getTemplatesState(enterpriseId, templateIds(ovfIds));
}
catch (Exception e)
{
reportError(e);
return null;// unreachable
}
finally
{
returnClientToPool(amClient);
}
}
public TemplateStateDto getTemplateState(final Integer datacenterId,
final Integer enterpriseId, final String id)
{
final AMClient amClient = getAMClient(datacenterId, enterpriseId, false);
try
{
return amClient.getTemplateStatus(enterpriseId, id);
}
catch (Exception e)
{
TemplateStateDto st = new TemplateStateDto();
st.setOvfId(id);
st.setStatus(TemplateStatusEnumType.DOWNLOADING);
st.setDownloadingProgress(0.0);
LOGGER.warn("Can't update the download progress of {} caused by: {}", id,
e.getMessage());
return st;
// reportError(e);
// return null;// unreachable
}
finally
{
returnClientToPool(amClient);
}
}
public void install(final Integer datacenterId, final Integer enterpriseId, final String id)
{
final AMClient amClient = getAMClient(datacenterId, enterpriseId, false);
try
{
amClient.installTemplateDefinition(enterpriseId, id);
}
catch (Exception e)
{
reportError(e);
}
finally
{
returnClientToPool(amClient);
}
}
public List<TemplateDto> refreshRepository(final Integer enterpriseId,
final Integer datacenterId, final String currentRepositoryLocation)
{
final AMClient amClient = getAMClient(datacenterId, enterpriseId, false);
String repositoryLocation = null;
try
{
repositoryLocation = amClient.getRepositoryConfiguration().getLocation();
}
catch (AMClientException e1)
{
returnClientToPool(amClient);
addConflictErrors(APIError.VMTEMPLATE_SYNCH_DC_REPO);
reportError(e1);
}
if (!currentRepositoryLocation.equalsIgnoreCase(repositoryLocation))
{
addConflictErrors(APIError.VMTEMPLATE_REPOSITORY_CHANGED);
flushErrors();
}
try
{
amClient.refreshRepository(enterpriseId);
List<TemplateStateDto> downloads =
amClient.getTemplatesState(enterpriseId, TemplateStatusEnumType.DOWNLOAD)
.getCollection();
List<TemplateDto> disks = new LinkedList<TemplateDto>();
for (TemplateStateDto download : downloads)
{
try
{
disks.add(amClient.getTemplate(enterpriseId, download.getOvfId()));
}
catch (Exception e)
{
LOGGER.error("Can't initialize template {}", download.getOvfId(), e);
}
}
return disks;
}
catch (Exception e)
{
addConflictErrors(APIError.VMTEMPLATE_SYNCH_DC_REPO);
reportError(e);
return null;// unreachable
}
finally
{
returnClientToPool(amClient);
}
}
private TemplateIdsDto templateIds(final String... ovfids)
{
TemplateIdsDto ids = new TemplateIdsDto();
for (String id : ovfids)
{
TemplateIdDto tId = new TemplateIdDto();
tId.setOvfId(id);
ids.add(tId);
}
return ids;
}
/**
* CLIENT
*/
private AMClient getAMClient(final Integer dcId, final Integer enterpriseId,
final boolean withTimeout)
{
// Check that the enterprise can use the datacenter
DatacenterLimits limits =
entService.findLimitsByEnterpriseAndDatacenter(enterpriseId, dcId);
if (limits == null)
{
addConflictErrors(APIError.ENTERPRISE_NOT_ALLOWED_DATACENTER);
flushErrors();
}
final String amUri =
infService.getRemoteService(dcId, RemoteServiceType.APPLIANCE_MANAGER).getUri();
try
{
return clientPool.borrowObject(amUri, withTimeout);
}
catch (Exception e)
{
LOGGER.error(APIError.AM_CLIENT.getMessage(), e);
addUnexpectedErrors(APIError.AM_CLIENT);
flushErrors();
return null;
}
}
/**
* Do not check the UserSession as it is called by AMEventProcessor
*/
private AMClient getAMClientBySystem(final Integer dcId, final Integer enterpriseId,
final boolean withTimeout)
{
final String amUri =
infService.getRemoteService(dcId, RemoteServiceType.APPLIANCE_MANAGER).getUri();
try
{
return clientPool.borrowObject(amUri, withTimeout);
}
catch (Exception e)
{
LOGGER.error(APIError.AM_CLIENT.getMessage(), e);
addUnexpectedErrors(APIError.AM_CLIENT);
flushErrors();
return null;
}
}
private void returnClientToPool(final AMClient client)
{
try
{
clientPool.returnObject(client);
}
catch (Exception e)
{
LOGGER.trace("Unable to return AMClient instance to pool.", e);
}
}
private void reportError(final Exception e)
{
if (e instanceof AMClientException)
{
LOGGER.error(APIError.AM_FAILED_REQUEST.getMessage(), e.getMessage());
addServiceUnavailableErrors(new CommonError(APIError.AM_FAILED_REQUEST.getCode(),
APIError.AM_FAILED_REQUEST.getMessage() + '\n' + e.getMessage()));
}
else if (isATimeout(e))
{
LOGGER.warn(APIError.AM_TIMEOUT.getMessage(), e.getMessage());
addServiceUnavailableErrors(APIError.AM_TIMEOUT);
}
else
{
LOGGER.error(APIError.AM_UNAVAILABE.getMessage(), e.getMessage());
addServiceUnavailableErrors(APIError.AM_UNAVAILABE);
}
flushErrors();
}
private boolean isATimeout(final Exception e)
{
return e instanceof ClientRuntimeException
&& e.getCause() instanceof SocketTimeoutException
|| //
e instanceof ClientRuntimeException && e.getCause().getCause() != null
&& e.getCause().getCause() instanceof SocketTimeoutException;
}
}