/**
* 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.resources.cloud;
import static com.abiquo.api.util.URIResolver.buildPath;
import java.util.List;
import javax.annotation.Resource;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import org.apache.wink.common.annotations.Parent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import com.abiquo.api.exceptions.APIError;
import com.abiquo.api.exceptions.BadRequestException;
import com.abiquo.api.resources.AbstractResource;
import com.abiquo.api.services.NetworkService;
import com.abiquo.api.services.UserService;
import com.abiquo.api.services.cloud.VirtualDatacenterService;
import com.abiquo.api.util.IRESTBuilder;
import com.abiquo.api.util.URIResolver;
import com.abiquo.model.rest.RESTLink;
import com.abiquo.model.transport.LinksDto;
import com.abiquo.server.core.cloud.VirtualDatacenter;
import com.abiquo.server.core.cloud.VirtualDatacenterDto;
import com.abiquo.server.core.cloud.VirtualDatacenterWithDatacenterDto;
import com.abiquo.server.core.infrastructure.Datacenter;
import com.abiquo.server.core.infrastructure.DatacenterDto;
import com.abiquo.server.core.infrastructure.network.IpPoolManagement;
import com.abiquo.server.core.infrastructure.network.IpsPoolManagementDto;
import com.abiquo.server.core.infrastructure.network.VLANNetwork;
import com.abiquo.server.core.infrastructure.network.VLANNetworkDto;
import com.abiquo.server.core.util.PagedList;
@Parent(VirtualDatacentersResource.class)
@Path(VirtualDatacenterResource.VIRTUAL_DATACENTER_PARAM)
@Controller
public class VirtualDatacenterResource extends AbstractResource
{
public static final String VIRTUAL_DATACENTER = "virtualdatacenter";
public static final String VIRTUAL_DATACENTER_PARAM = "{" + VIRTUAL_DATACENTER + "}";
public static final String VIRTUAL_DATACENTER_GET_IPS_PATH = "/action/ips";
public static final String VIRTUAL_DATACENTER_GET_IPS_REL = "ips";
public static final String VIRTUAL_DATACENTER_DHCP_INFO_PATH = "/action/dhcpinfo";
public static final String VIRTUAL_DATACENTER_DHCP_INFO_REL = "dhcpinfo";
public static final String DEFAULT_VLAN_PATH = "/action/defaultvlan";
public static final String DEFAULT_VLAN_REL = "defaultvlan";
public static final String DEFAULT_NETWORK_REL = "defaultnetwork";
public static final String TYPE = "type";
public static final String ALL = "all";
// @Autowired
@Resource(name = "virtualDatacenterService")
VirtualDatacenterService service;
@Autowired
NetworkService netService;
@Autowired
UserService userService;
@Context
UriInfo uriInfo;
/**
* Returns a virtual datacenter
*
* @title Retireve a virtual datacenter
* @param id identifier of the virtual datacenter
* @param restBuilder a Context-injected object to create the links of the Dto
* @return a {VirtualDatacenterDto} object with the requested virtual datacenter
* @throws Exception
*/
@GET
@Produces(VirtualDatacenterDto.MEDIA_TYPE)
public VirtualDatacenterDto getVirtualDatacenter(
@PathParam(VIRTUAL_DATACENTER) final Integer id, @Context final IRESTBuilder restBuilder)
throws Exception
{
VirtualDatacenter vdc = service.getVirtualDatacenter(id);
return createTransferObject(vdc, restBuilder);
}
/**
* Modifies a virtual datacenter
*
* @title Modify a virtual datacenter
* @param id identifier of the virtual datacenter
* @param dto virtual datacenter to modify
* @param restBuilder a Context-injected object to create the links of the Dto
* @return a {VirtualDatacenterDto} with the modified virtual datacenter
* @throws Exception
*/
@PUT
@Consumes(VirtualDatacenterDto.MEDIA_TYPE)
@Produces(VirtualDatacenterDto.MEDIA_TYPE)
public VirtualDatacenterDto updateVirtualDatacenter(
@PathParam(VIRTUAL_DATACENTER) final Integer id, final VirtualDatacenterDto dto,
@Context final IRESTBuilder restBuilder) throws Exception
{
VirtualDatacenter vdc = service.updateVirtualDatacenter(id, dto);
userService.checkCurrentEnterpriseForPostMethods(vdc.getEnterprise());
return createTransferObject(vdc, restBuilder);
}
/**
* Deletes a virtual datacenter
*
* @title Delete a virtual datacenter
* @param id identifirer of the virtual datacenter
*/
@DELETE
public void deleteVirtualDatacenter(@PathParam(VIRTUAL_DATACENTER) final Integer id)
{
service.deleteVirtualDatacenter(id);
}
/**
* Returns all IPs from a virtual datacenter
*
* @title Retrieve all Ips
* @param id identifier of the virtual datacenter
* @param startwith
* @param orderBy
* @param filter
* @param limit
* @param desc_or_asc
* @param type
* @param restBuilder a Context-injected object to create the links of the Dto
* @return a {IpsPoolManagementDto} with all ips from the virtual datacenter
* @throws Exception
*/
@SuppressWarnings("unchecked")
@GET
@Path(VirtualDatacenterResource.VIRTUAL_DATACENTER_GET_IPS_PATH)
@Produces(IpsPoolManagementDto.MEDIA_TYPE)
public IpsPoolManagementDto getIPsByVirtualDatacenter(
@PathParam(VIRTUAL_DATACENTER) final Integer id,
@QueryParam(START_WITH) @Min(0) final Integer startwith,
@QueryParam(BY) @DefaultValue("ip") final String orderBy,
@QueryParam(FILTER) @DefaultValue("") final String filter,
@QueryParam(LIMIT) @DefaultValue(DEFAULT_PAGE_LENGTH_STRING) @Min(1) final Integer limit,
@QueryParam(ASC) @DefaultValue("true") final Boolean desc_or_asc,
@QueryParam(TYPE) final String type,
@QueryParam(ALL) @DefaultValue("false") final Boolean allIps,
@Context final IRESTBuilder restBuilder) throws Exception
{
List<IpPoolManagement> all =
netService.getListIpPoolManagementByVdc(id, startwith, limit, filter, orderBy,
desc_or_asc, type, allIps);
/*
* if (all == null || all.isEmpty()) { throw new
* ConflictException(APIError.VIRTUAL_DATACENTER_INVALID_NETWORKS); }
*/
IpsPoolManagementDto ips = new IpsPoolManagementDto();
for (IpPoolManagement ip : all)
{
ips.add(IpAddressesResource.createTransferObject(ip, restBuilder));
}
ips.setTotalSize(((PagedList) all).getTotalResults());
ips.setLinks(restBuilder.buildPaggingLinks(uriInfo.getAbsolutePath().toString(),
(PagedList) all));
return ips;
}
/**
* Returns the DHCP info from virtual datacenter.
*
* @title Retrieve the DHCP info
* @param id identifier of the virtual datacenter
* @param restBuilder a Context-injected object to create the links of the Dto
* @return a {String} object with the DHCP info
* @throws Exception
*/
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path(VirtualDatacenterResource.VIRTUAL_DATACENTER_DHCP_INFO_PATH)
public String getDHCPInfoByVirtualDatacenter(@PathParam(VIRTUAL_DATACENTER) final Integer id,
@Context final IRESTBuilder restBuilder) throws Exception
{
List<IpPoolManagement> all =
netService.getListIpPoolManagementByVdc(id, 0, DEFAULT_PAGE_LENGTH, "", "ip", true,
null, true);
StringBuilder formattedData = new StringBuilder();
formattedData.append("## AbiCloud DHCP configuration for network "
+ service.getVirtualDatacenter(id).getNetwork().getUuid() + "\n");
formattedData
.append("## Please copy and paste the following lines into your DHCP server\n");
for (IpPoolManagement ipPool : all)
{
formattedData.append("host " + ipPool.getName() + " {\n");
// VirtualBox mac format
if (!ipPool.getMac().contains(":"))
{
String unformattedMA = ipPool.getMac();
StringBuilder formattedMA = new StringBuilder(unformattedMA.substring(0, 2) + ":");
formattedMA.append(unformattedMA.substring(2, 4) + ":");
formattedMA.append(unformattedMA.substring(4, 6) + ":");
formattedMA.append(unformattedMA.substring(6, 8) + ":");
formattedMA.append(unformattedMA.substring(8, 10) + ":");
formattedMA.append(unformattedMA.substring(10, 12));
formattedData.append("\thardware ethernet " + formattedMA + ";\n");
}
else
{
formattedData.append("\thardware ethernet " + ipPool.getMac() + ";\n");
}
formattedData.append("\tfixed-address " + ipPool.getIp() + ";\n");
formattedData.append("}\n\n");
}
return formattedData.toString();
}
// ALERT! this method is @override in enterprise version, any change here
// should be also changed in enterprise version.
/**
* Returns the default vlan from a virtual datacenter.
*
* @title Retrieve the default vlan
* @wiki In the external networks resource you can set the default VLAN behavior by virtual
* datacenter. This means that if you perform the get default VLAN request after you have
* created the virtual datacenter, you will see the Enterprise-default VLAN.
* @param id identifier of the virtual datacenter
* @param restBuilder a Context-injected object to create the links of the Dto
* @return a {VLANNetworkDto} object with the default vlan of the virtual datacenter
* @throws Exception
*/
@GET
@Path(VirtualDatacenterResource.DEFAULT_VLAN_PATH)
@Produces(VLANNetworkDto.MEDIA_TYPE)
public VLANNetworkDto getDefaultVlan(
@PathParam(VIRTUAL_DATACENTER) @NotNull @Min(1) final Integer id,
@Context final IRESTBuilder restBuilder) throws Exception
{
VLANNetwork vlan = netService.getDefaultNetworkForVirtualDatacenter(id);
return PrivateNetworkResource.createTransferObject(vlan, id, restBuilder);
}
// ALERT! this method is @override in enterprise version, any change here
// should be also changed in enterprise version.
/**
* Changes the default vlan for a virtual datacenter
*
* @title Changes the default vlan for a virtual datacenter
* @param id identifier of the virtual datacenter
* @param links link from new default vlan
* @param restBuilder a Context-injected object to create the links of the Dto
* @throws Exception
*/
@PUT
@Path(VirtualDatacenterResource.DEFAULT_VLAN_PATH)
@Consumes(LinksDto.MEDIA_TYPE)
public void setDefaultVlan(@PathParam(VIRTUAL_DATACENTER) @NotNull @Min(1) final Integer id,
@NotNull final LinksDto links, @Context final IRESTBuilder restBuilder) throws Exception
{
RESTLink privateLink = links.searchLink("internalnetwork");
if (privateLink == null)
{
throw new BadRequestException(APIError.INVALID_LINK);
}
// Parse the URI with the expected parameters and extract the identifier values.
String buildPath =
buildPath(VirtualDatacentersResource.VIRTUAL_DATACENTERS_PATH,
VirtualDatacenterResource.VIRTUAL_DATACENTER_PARAM,
PrivateNetworksResource.PRIVATE_NETWORKS_PATH,
PrivateNetworkResource.PRIVATE_NETWORK_PARAM);
MultivaluedMap<String, String> ipsValues =
URIResolver.resolveFromURI(buildPath, privateLink.getHref());
// Private IP must belong to the same Virtual Datacenter where the Virtual Machine
// belongs to.
Integer vdcId =
Integer.parseInt(ipsValues.getFirst(VirtualDatacenterResource.VIRTUAL_DATACENTER));
if (!vdcId.equals(id))
{
throw new BadRequestException(APIError.VLANS_IP_LINK_INVALID_VDC);
}
// Extract the vlanId and ipId values to execute the association.
Integer vlanId =
Integer.parseInt(ipsValues.getFirst(PrivateNetworkResource.PRIVATE_NETWORK));
netService.setInternalNetworkAsDefaultInVirtualDatacenter(vdcId, vlanId);
}
public static VirtualDatacenterDto createTransferObject(final VirtualDatacenter vdc,
final IRESTBuilder builder) throws Exception
{
VirtualDatacenterDto response = createTransferObject(vdc);
VLANNetworkDto vlan =
PrivateNetworkResource.createTransferObject(vdc.getDefaultVlan(), vdc.getId(), builder);
response.setVlan(vlan);
response.setLinks(builder.buildVirtualDatacenterLinks(vdc, vdc.getDatacenter().getId(), vdc
.getEnterprise().getId()));
return response;
}
public static VirtualDatacenterDto createTransferObject(final VirtualDatacenter vdc)
{
VirtualDatacenterDto response = new VirtualDatacenterDto();
response.setId(vdc.getId());
response.setHypervisorType(vdc.getHypervisorType());
response.setName(vdc.getName());
response.setCpuCountLimits(vdc.getCpuCountSoftLimit().intValue(), vdc
.getCpuCountHardLimit().intValue());
response.setHdLimitsInMb(vdc.getHdSoftLimitInMb(), vdc.getHdHardLimitInMb());
response.setRamLimitsInMb(vdc.getRamSoftLimitInMb().intValue(), vdc.getRamHardLimitInMb()
.intValue());
response.setStorageLimits(vdc.getStorageSoft(), vdc.getStorageHard());
response.setVlansLimits(vdc.getVlanSoft(), vdc.getVlanHard());
response.setPublicIPLimits(vdc.getPublicIpsSoft(), vdc.getPublicIpsHard());
return response;
}
public static VirtualDatacenterWithDatacenterDto createTransferObjectWithDatacenter(
final VirtualDatacenter vdc) throws Exception
{
VirtualDatacenterWithDatacenterDto dto = new VirtualDatacenterWithDatacenterDto();
dto.setId(vdc.getId());
dto.setName(vdc.getName());
dto.setHypervisorType(vdc.getHypervisorType());
DatacenterDto vdcDto = new DatacenterDto();
Datacenter datacenter = vdc.getDatacenter();
vdcDto.setId(datacenter.getId());
vdcDto.setName(datacenter.getName());
vdcDto.setLocation(datacenter.getLocation());
dto.setDatacenter(vdcDto);
return dto;
}
}