/**
* Copyright (C) 2008 Abiquo Holdings S.L.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.abiquo.apiclient;
import static com.abiquo.apiclient.domain.ApiPath.DATACENTERS_URL;
import static com.abiquo.apiclient.domain.ApiPath.HYPERVISORTYPES_URL;
import static com.abiquo.apiclient.domain.ApiPath.LOADLEVELRULES_URL;
import static com.abiquo.apiclient.domain.ApiPath.PUBLIC_CLOUD_REGIONS_URL;
import static com.abiquo.apiclient.domain.ApiPath.REMOTE_SERVICES_URL;
import static com.abiquo.apiclient.domain.Links.create;
import static com.abiquo.apiclient.domain.Links.editOrSelf;
import static com.abiquo.apiclient.domain.Links.withRel;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.tryFind;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.abiquo.apiclient.domain.options.DatacenterListOptions;
import com.abiquo.apiclient.domain.options.PublicCloudRegionListOptions;
import com.abiquo.model.enumerator.NetworkType;
import com.abiquo.model.rest.RESTLink;
import com.abiquo.server.core.cloud.DeviceDto;
import com.abiquo.server.core.enterprise.DatacenterLimitsDto;
import com.abiquo.server.core.enterprise.DatacentersLimitsDto;
import com.abiquo.server.core.enterprise.EnterpriseDto;
import com.abiquo.server.core.infrastructure.DatacenterDto;
import com.abiquo.server.core.infrastructure.DatacentersDto;
import com.abiquo.server.core.infrastructure.LocationDto;
import com.abiquo.server.core.infrastructure.MachineDto;
import com.abiquo.server.core.infrastructure.MachinesDto;
import com.abiquo.server.core.infrastructure.PublicCloudRegionDto;
import com.abiquo.server.core.infrastructure.PublicCloudRegionsDto;
import com.abiquo.server.core.infrastructure.RackDto;
import com.abiquo.server.core.infrastructure.RacksDto;
import com.abiquo.server.core.infrastructure.RemoteServiceDto;
import com.abiquo.server.core.infrastructure.RemoteServicesDto;
import com.abiquo.server.core.infrastructure.network.NetworkServiceTypeDto;
import com.abiquo.server.core.infrastructure.network.NetworkServiceTypesDto;
import com.abiquo.server.core.infrastructure.network.VLANNetworkDto;
import com.abiquo.server.core.infrastructure.network.VLANNetworksDto;
import com.abiquo.server.core.infrastructure.storage.StorageDeviceDto;
import com.abiquo.server.core.infrastructure.storage.StorageDevicesDto;
import com.abiquo.server.core.infrastructure.storage.StoragePoolDto;
import com.abiquo.server.core.infrastructure.storage.StoragePoolsDto;
import com.abiquo.server.core.infrastructure.storage.TierDto;
import com.abiquo.server.core.infrastructure.storage.TiersDto;
import com.abiquo.server.core.scheduler.MachineLoadRuleDto;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
public class InfrastructureApi
{
private final RestClient client;
// Package private constructor to be used only by the ApiClient
InfrastructureApi(final RestClient client)
{
this.client = checkNotNull(client, "client cannot be null");
}
public Iterable<DatacenterDto> listDatacenters()
{
return client.list(DATACENTERS_URL, DatacentersDto.MEDIA_TYPE, DatacentersDto.class);
}
public Iterable<DatacenterDto> listDatacenters(final DatacenterListOptions options)
{
return client.list(DATACENTERS_URL, options.queryParams(), DatacentersDto.MEDIA_TYPE,
DatacentersDto.class);
}
public Iterable<RackDto> listRacks(final DatacenterDto datacenter)
{
return client.list(datacenter.searchLink("racks").getHref(), RacksDto.MEDIA_TYPE,
RacksDto.class);
}
public Iterable<DatacenterLimitsDto> listLimits(final EnterpriseDto enterprise)
{
return client.list(enterprise.searchLink("limits"), DatacentersLimitsDto.class);
}
public DatacenterLimitsDto getEnterpriseLimitsForDatacenter(final EnterpriseDto enterprise,
final DatacenterDto datacenter)
{
Map<String, Object> params = new HashMap<String, Object>();
params.put("datacenter", datacenter.getId());
return client
.get(enterprise.searchLink("limits").getHref(), params,
DatacentersLimitsDto.MEDIA_TYPE, DatacentersLimitsDto.class).getCollection().get(0);
}
public Iterable<VLANNetworkDto> listExternalNetworks(final DatacenterLimitsDto limits)
{
return client.list(limits.searchLink("externalnetworks").getHref(),
VLANNetworksDto.MEDIA_TYPE, VLANNetworksDto.class);
}
/**
* Creates a new datacenter using new remote services. If any remote service in remoteServices
* exists, it is reused for the new datacenter.
*
* @param name The new datacenter name
* @param location The new datacenter location
* @param remoteServices The remote services the new datacenter needs
* @return The new datacenter dto
*/
public DatacenterDto createDatacenter(final String name, final String location,
final List<RemoteServiceDto> remoteServices)
{
DatacenterDto datacenter = new DatacenterDto();
Iterable<RemoteServiceDto> existentRSs = listRemoteServices();
RemoteServicesDto remoteServicesDto = new RemoteServicesDto();
remoteServicesDto.addAll(remoteServices);
for (final RemoteServiceDto rs : remoteServices)
{
Optional<RemoteServiceDto> exRS =
tryFind(existentRSs, new Predicate<RemoteServiceDto>()
{
@Override
public boolean apply(final RemoteServiceDto input)
{
return input.getType().equals(rs.getType()) && input.getType().isReusable();
}
});
if (exRS.isPresent())
{
datacenter.addLink(withRel("remoteservice", editOrSelf(exRS.get())));
remoteServicesDto.getCollection().remove(rs);
}
}
datacenter.setName(name);
datacenter.setLocation(location);
datacenter.setRemoteServices(remoteServicesDto);
return client.post(DATACENTERS_URL, DatacenterDto.MEDIA_TYPE, DatacenterDto.MEDIA_TYPE,
datacenter, DatacenterDto.class);
}
/**
* Creates a new public cloud region. If any remote service in remoteServices exists, it is
* reused for the new public cloud region.
*
* @param name The new public cloud region name
* @param region The new public cloud region provider's region
* @param type The new public cloud region type
* @param remoteServices The remote services the new public cloud region needs
* @return The new public cloud region dto
*/
public PublicCloudRegionDto createPublicCloudRegion(final String name, final String region,
final String type, final List<RemoteServiceDto> remoteServices)
{
PublicCloudRegionDto publicCloudRegion = new PublicCloudRegionDto();
Iterable<RemoteServiceDto> existentRSs = listRemoteServices();
RemoteServicesDto remoteServicesDto = new RemoteServicesDto();
remoteServicesDto.addAll(remoteServices);
for (final RemoteServiceDto rs : remoteServices)
{
Optional<RemoteServiceDto> exRS =
Iterables.tryFind(existentRSs, new Predicate<RemoteServiceDto>()
{
@Override
public boolean apply(final RemoteServiceDto input)
{
return input.getType().equals(rs.getType());
}
});
if (exRS.isPresent())
{
publicCloudRegion.addLink(withRel("remoteservice", editOrSelf(exRS.get())));
remoteServicesDto.getCollection().remove(rs);
}
}
publicCloudRegion.setName(name);
publicCloudRegion.setRemoteServices(remoteServicesDto);
publicCloudRegion.addLink(new RESTLink("region", String.format("%s/%s/regions/%s",
HYPERVISORTYPES_URL, type, region)));
return client.post(PUBLIC_CLOUD_REGIONS_URL, PublicCloudRegionDto.MEDIA_TYPE,
PublicCloudRegionDto.MEDIA_TYPE, publicCloudRegion, PublicCloudRegionDto.class);
}
public Iterable<RemoteServiceDto> listRemoteServices(final DatacenterDto datacenter)
{
return client.list(datacenter.searchLink("remoteservices"), RemoteServicesDto.class);
}
public Iterable<RemoteServiceDto> listRemoteServices()
{
return client.list(REMOTE_SERVICES_URL, RemoteServicesDto.MEDIA_TYPE,
RemoteServicesDto.class);
}
public RackDto createRack(final DatacenterDto datacenter, final String name)
{
RackDto rack = new RackDto();
rack.setName(name);
return client.post(datacenter.searchLink("racks").getHref(), RackDto.MEDIA_TYPE,
RackDto.MEDIA_TYPE, rack, RackDto.class);
}
/** addLocationToEnterprise */
@Deprecated
public void addDatacenterToEnterprise(final EnterpriseDto enterprise,
final DatacenterDto datacenter)
{
addLocationToEnterprise(enterprise, datacenter);
}
/** addLocationToEnterprise */
@Deprecated
public void addPublicCloudRegionToEnterprise(final EnterpriseDto enterprise,
final PublicCloudRegionDto pcr)
{
addLocationToEnterprise(enterprise, pcr);
}
public DatacenterLimitsDto addLocationToEnterprise(final EnterpriseDto enterprise,
final LocationDto location)
{
RESTLink editlink = location.getEditLink();
DatacenterLimitsDto limits = new DatacenterLimitsDto();
limits.addLink(create("location", editlink.getHref(), editlink.getType()));
return client.post(enterprise.searchLink("limits").getHref(),
DatacenterLimitsDto.MEDIA_TYPE, DatacenterLimitsDto.MEDIA_TYPE, limits,
DatacenterLimitsDto.class);
}
public MachinesDto discoverMachines(final DatacenterDto datacenter, final String type,
final String ip, final String user, final String password)
{
Map<String, Object> queryParams = new HashMap<String, Object>();
queryParams.put("hypervisor", type);
queryParams.put("ip", ip);
queryParams.put("user", user);
queryParams.put("password", password);
return client.get(datacenter.searchLink("discover").getHref(), queryParams,
MachinesDto.MEDIA_TYPE, MachinesDto.class);
}
public MachinesDto discoverManagedMachines(final DatacenterDto datacenter, final String type,
final String ip, final String managerIp, final String managerUser,
final String managerPassword)
{
Map<String, Object> queryParams = new HashMap<String, Object>();
queryParams.put("hypervisor", type);
queryParams.put("ip", ip);
queryParams.put("managerip", managerIp);
queryParams.put("manageruser", managerUser);
queryParams.put("managerpassword", managerPassword);
return client.get(datacenter.searchLink("discover").getHref(), queryParams,
MachinesDto.MEDIA_TYPE, MachinesDto.class);
}
public MachineDto createMachine(final RackDto rack, final MachineDto machine)
{
return client.post(rack.searchLink("machines").getHref(), MachineDto.MEDIA_TYPE,
MachineDto.MEDIA_TYPE, machine, MachineDto.class);
}
public Iterable<NetworkServiceTypeDto> listNetworkServiceTypes(final DatacenterDto datacenter)
{
return client.list(datacenter.searchLink("networkservicetypes").getHref(),
NetworkServiceTypesDto.MEDIA_TYPE, NetworkServiceTypesDto.class);
}
public MachineLoadRuleDto createDatacenterLoadLevelRule(final DatacenterDto datacenter,
final int cpuLoadPercentage, final int ramLoadPercentage)
{
return createLoadLevelRule(
create("datacenter", datacenter.getEditLink().getHref(), datacenter.getEditLink()
.getType()), cpuLoadPercentage, ramLoadPercentage);
}
public MachineLoadRuleDto createRackLoadLevelRule(final RackDto rack,
final int cpuLoadPercentage, final int ramLoadPercentage)
{
return createLoadLevelRule(
create("rack", rack.getEditLink().getHref(), rack.getEditLink().getType()),
cpuLoadPercentage, ramLoadPercentage);
}
public MachineLoadRuleDto createMachineLoadLevelRule(final MachineDto machine,
final int cpuLoadPercentage, final int ramLoadPercentage)
{
return createLoadLevelRule(
create("machine", machine.getEditLink().getHref(), machine.getEditLink().getType()),
cpuLoadPercentage, ramLoadPercentage);
}
private MachineLoadRuleDto createLoadLevelRule(final RESTLink targetLink,
final int cpuLoadPercentage, final int ramLoadPercentage)
{
MachineLoadRuleDto rule = new MachineLoadRuleDto();
rule.setCpuLoadPercentage(cpuLoadPercentage);
rule.setRamLoadPercentage(ramLoadPercentage);
rule.addLink(targetLink);
return client.post(LOADLEVELRULES_URL, MachineLoadRuleDto.MEDIA_TYPE,
MachineLoadRuleDto.MEDIA_TYPE, rule, MachineLoadRuleDto.class);
}
public Iterable<StorageDeviceDto> listDevices(final DatacenterDto datacenter)
{
return client.list(datacenter.searchLink("devices").getHref(),
StorageDevicesDto.MEDIA_TYPE, StorageDevicesDto.class);
}
public Iterable<StoragePoolDto> listPools(final StorageDeviceDto device)
{
return client.list(device.searchLink("pools").getHref(), StoragePoolsDto.MEDIA_TYPE,
StoragePoolsDto.class);
}
public Iterable<StoragePoolDto> listRemotePools(final StorageDeviceDto device)
{
Map<String, Object> queryParams = new HashMap<String, Object>();
queryParams.put("sync", true);
return client.list(device.searchLink("pools").getHref(), queryParams,
StoragePoolsDto.MEDIA_TYPE, StoragePoolsDto.class);
}
public StorageDeviceDto createDevice(final DatacenterDto datacenter, final String name,
final String technology, final String managementIp, final int managementPort,
final String serviceIp, final int servicePort, final String username, final String password)
{
StorageDeviceDto device = new StorageDeviceDto();
device.addLink(create("datacenter", datacenter.getEditLink().getHref(), datacenter
.getEditLink().getType()));
device.setName(name);
device.setStorageTechnology(technology);
device.setManagementIp(managementIp);
device.setManagementPort(managementPort);
device.setServiceIp(serviceIp);
device.setServicePort(servicePort);
device.setUsername(username);
device.setPassword(password);
return client.post(datacenter.searchLink("devices").getHref(), StorageDeviceDto.MEDIA_TYPE,
StorageDeviceDto.MEDIA_TYPE, device, StorageDeviceDto.class);
}
public StoragePoolDto createPool(final DatacenterDto datacenter,
final StorageDeviceDto storageDevice, final String pool, final String tierName)
{
StoragePoolDto storagePool =
find(listRemotePools(storageDevice), new Predicate<StoragePoolDto>()
{
@Override
public boolean apply(final StoragePoolDto input)
{
return input.getName().equals(pool);
}
});
TierDto tier = find(listTiers(datacenter), new Predicate<TierDto>()
{
@Override
public boolean apply(final TierDto input)
{
return input.getName().equals(tierName);
}
});
storagePool.setEnabled(true);
storagePool.addLink(create("tier", tier.getEditLink().getHref(), tier.getEditLink()
.getType()));
return client.post(storageDevice.searchLink("pools").getHref(), StoragePoolDto.MEDIA_TYPE,
StoragePoolDto.MEDIA_TYPE, storagePool, StoragePoolDto.class);
}
public VLANNetworkDto createExternalNetwork(final DatacenterDto datacenter,
final NetworkServiceTypeDto nst, final EnterpriseDto enterprise, final String name,
final String address, final String gateway, final int mask, final int tag,
final Optional<DeviceDto> optDevice)
{
VLANNetworkDto vlan = new VLANNetworkDto();
vlan.addLink(create("enterprise", enterprise.getEditLink().getHref(), enterprise
.getEditLink().getType()));
vlan.addLink(create("networkservicetype", nst.getEditLink().getHref(), nst.getEditLink()
.getType()));
vlan.setAddress(address);
vlan.setName(name);
vlan.setType(NetworkType.EXTERNAL);
vlan.setMask(mask);
vlan.setTag(tag);
vlan.setGateway(gateway);
String url;
if (optDevice.isPresent())
{
url = optDevice.get().searchLink("networks").getHref();
}
else
{
url = datacenter.searchLink("network").getHref();
}
return client.post(url, VLANNetworkDto.MEDIA_TYPE,
VLANNetworkDto.MEDIA_TYPE, vlan, VLANNetworkDto.class);
}
public Iterable<TierDto> listTiers(final DatacenterDto datacenter)
{
return client.list(datacenter.searchLink("tiers").getHref(), TiersDto.MEDIA_TYPE,
TiersDto.class);
}
public Iterable<PublicCloudRegionDto> listPublicCloudRegions(
final PublicCloudRegionListOptions options)
{
return client.list(PUBLIC_CLOUD_REGIONS_URL, options.queryParams(),
PublicCloudRegionsDto.MEDIA_TYPE, PublicCloudRegionsDto.class);
}
public Iterable<PublicCloudRegionDto> listPublicCloudRegions()
{
return client.list(PUBLIC_CLOUD_REGIONS_URL, PublicCloudRegionsDto.MEDIA_TYPE,
PublicCloudRegionsDto.class);
}
}