Improved ComputeService and delegate virtual datacenter election to TemplateBuilder

Made a few changes to adapt the Abiquo compute service
implementation to the most common use cases:

* Do not attempt to create a VDC. Regualr users may not have
  permissions to create VDCs, so don't try to create them. A
  VDC compatible with teh template being deployed must exist.
* Configure nodes with one public ip by default, and if no
  public ip is available, assign one from the default private
  VLAN for the selected virtual datacenter.

Also fixed some concept mappings between Abiquo and jclouds:

Virtual datacenter (zone) election should be performed by the
TemplateBuilder and not by the ComputeServiceAdapter. This commit
refactors the current adapter to implement the right behavior.

The two main concepts in this refactor are about locations. Now,
physical datacenters will be scoped to Region locations, and virtual
datacenters to Zones.

Images in Abiquo are scoped to Regions (each physical datacenter has a
set of available images), and hardware profiles will be used to scope
images to a particular virtual datacenter. Since a virtual datacenter in
Abiquo is just a container that provides compute resources in a specific
virtualization technology, each image will have one hardware profile
scoped to each compatible virtual datacenter (zone).

This way, the virtual datacenter election will be made using the
TemplateBuilder, by selecting the desired hardware profile.
This commit is contained in:
Ignasi Barrera 2012-10-07 13:25:18 +02:00
parent 38d3b7d76c
commit 26f801058d
27 changed files with 1010 additions and 859 deletions

View File

@ -3,19 +3,8 @@ Jclouds Abiquo Provider
This is the jclouds Abiquo provider. It enables compute features for the Abiquo cloud platform.
Documentation
-------------
Detailed information about the Abiquo REST API can be found in the
[Abiquo documentation page](http://community.abiquo.com).
All information about building and using the **jclouds-abiquo** provider in your own project
can be found in the [Project Wiki](https://github.com/abiquo/jclouds-abiquo/wiki).
Issue Tracking
--------------
If you find any issue in the provider api, please submit it to the [Bug tracking system](http://jira.abiquo.com/browse/ABIQUOJC)
and we will do our best to fix it.
If you find any issue in the provider api, please submit it to the [Bug tracking system](http://jira.abiquo.com/browse/ABIQUOJC) and we will do our best to fix it.

View File

@ -20,13 +20,16 @@
package org.jclouds.abiquo.compute.config;
import org.jclouds.abiquo.compute.functions.DatacenterToLocation;
import org.jclouds.abiquo.compute.functions.VirtualMachineTemplateToHardware;
import org.jclouds.abiquo.compute.functions.VirtualDatacenterToLocation;
import org.jclouds.abiquo.compute.functions.VirtualMachineTemplateToImage;
import org.jclouds.abiquo.compute.functions.VirtualMachineTemplateWithZoneToHardware;
import org.jclouds.abiquo.compute.functions.VirtualMachineToNodeMetadata;
import org.jclouds.abiquo.compute.options.AbiquoTemplateOptions;
import org.jclouds.abiquo.compute.strategy.AbiquoComputeServiceAdapter;
import org.jclouds.abiquo.domain.cloud.VirtualDatacenter;
import org.jclouds.abiquo.domain.cloud.VirtualMachine;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplateWithZone;
import org.jclouds.abiquo.domain.infrastructure.Datacenter;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
@ -49,7 +52,7 @@ import com.google.inject.TypeLiteral;
*/
public class AbiquoComputeServiceContextModule
extends
ComputeServiceAdapterContextModule<VirtualMachine, VirtualMachineTemplate, VirtualMachineTemplate, Datacenter>
ComputeServiceAdapterContextModule<VirtualMachine, VirtualMachineTemplateWithZone, VirtualMachineTemplate, VirtualDatacenter>
{
@Override
@ -57,7 +60,7 @@ public class AbiquoComputeServiceContextModule
{
super.configure();
bind(
new TypeLiteral<ComputeServiceAdapter<VirtualMachine, VirtualMachineTemplate, VirtualMachineTemplate, Datacenter>>()
new TypeLiteral<ComputeServiceAdapter<VirtualMachine, VirtualMachineTemplateWithZone, VirtualMachineTemplate, VirtualDatacenter>>()
{
}).to(AbiquoComputeServiceAdapter.class);
bind(new TypeLiteral<Function<VirtualMachine, NodeMetadata>>()
@ -66,15 +69,18 @@ public class AbiquoComputeServiceContextModule
bind(new TypeLiteral<Function<VirtualMachineTemplate, Image>>()
{
}).to(VirtualMachineTemplateToImage.class);
bind(new TypeLiteral<Function<VirtualMachineTemplate, Hardware>>()
bind(new TypeLiteral<Function<VirtualMachineTemplateWithZone, Hardware>>()
{
}).to(VirtualMachineTemplateToHardware.class);
}).to(VirtualMachineTemplateWithZoneToHardware.class);
bind(new TypeLiteral<Function<Datacenter, Location>>()
{
}).to(DatacenterToLocation.class);
bind(new TypeLiteral<Function<VirtualDatacenter, Location>>()
{
}).to(VirtualDatacenterToLocation.class);
bind(ImplicitLocationSupplier.class).to(OnlyLocationOrFirstZone.class).in(Scopes.SINGLETON);
bind(TemplateOptions.class).to(AbiquoTemplateOptions.class);
install(new LocationsFromComputeServiceAdapterModule<VirtualMachine, VirtualMachineTemplate, VirtualMachineTemplate, Datacenter>()
install(new LocationsFromComputeServiceAdapterModule<VirtualMachine, VirtualMachineTemplateWithZone, VirtualMachineTemplate, VirtualDatacenter>()
{
});
}

View File

@ -32,6 +32,8 @@ import com.google.common.collect.ImmutableSet;
/**
* Converts a {@link Datacenter} to a {@link Location} one.
* <p>
* Physical datacenters will be considered regions.
*
* @author Ignasi Barrera
*/
@ -46,8 +48,7 @@ public class DatacenterToLocation implements Function<Datacenter, Location>
builder.id(datacenter.getId().toString());
builder.description(datacenter.getName() + " [" + datacenter.getLocation() + "]");
builder.metadata(ImmutableMap.<String, Object> of());
builder.scope(LocationScope.ZONE);
// TODO: Convert to ISO3166 code?
builder.scope(LocationScope.REGION);
builder.iso3166Codes(ImmutableSet.<String> of());
builder.parent(new LocationBuilder().scope(LocationScope.PROVIDER).id("abiquo")

View File

@ -0,0 +1,81 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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 org.jclouds.abiquo.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.abiquo.domain.cloud.VirtualDatacenter;
import org.jclouds.abiquo.domain.infrastructure.Datacenter;
import org.jclouds.abiquo.reference.rest.ParentLinkName;
import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
/**
* Converts a {@link VirtualDatacenter} to a {@link Location} one.
* <p>
* Virtual datacenters will be considered zones, since images will be deployed in a virtual
* datacenter. Each zone will be scoped into a physical datacenter (region).
*
* @author Ignasi Barrera
*/
@Singleton
public class VirtualDatacenterToLocation implements Function<VirtualDatacenter, Location>
{
private final Function<Datacenter, Location> datacenterToLocation;
private final Supplier<Map<Integer, Datacenter>> regionMap;
@Inject
public VirtualDatacenterToLocation(final Function<Datacenter, Location> datacenterToLocation,
@Memoized final Supplier<Map<Integer, Datacenter>> regionMap)
{
this.datacenterToLocation = checkNotNull(datacenterToLocation, "datacenterToLocation");
this.regionMap = checkNotNull(regionMap, "regionMap");
}
@Override
public Location apply(final VirtualDatacenter vdc)
{
LocationBuilder builder = new LocationBuilder();
builder.id(vdc.getId().toString());
builder.description(vdc.getName());
builder.metadata(ImmutableMap.<String, Object> of());
builder.scope(LocationScope.ZONE);
builder.iso3166Codes(ImmutableSet.<String> of());
Datacenter parent =
regionMap.get().get(vdc.unwrap().getIdFromLink(ParentLinkName.DATACENTER));
builder.parent(datacenterToLocation.apply(parent));
return builder.build();
}
}

View File

@ -43,15 +43,13 @@ public class VirtualMachineStateToNodeState implements Function<VirtualMachineSt
case ALLOCATED:
case LOCKED:
case CONFIGURED:
case NOT_ALLOCATED:
return Status.PENDING;
case ON:
return Status.RUNNING;
case OFF:
case PAUSED:
return Status.SUSPENDED;
case NOT_ALLOCATED:
// TODO: What about nodes created but still not deployed?
return Status.TERMINATED;
case UNKNOWN:
default:
return Status.UNRECOGNIZED;

View File

@ -19,27 +19,49 @@
package org.jclouds.abiquo.compute.functions;
import java.net.URI;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import org.jclouds.abiquo.domain.infrastructure.Datacenter;
import org.jclouds.abiquo.reference.rest.ParentLinkName;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Image.Status;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.domain.Location;
import com.abiquo.model.rest.RESTLink;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
/**
* Transforms a {@link VirtualMachineTemplate} into an {@link Image}.
* <p>
* Images are scoped to a region (physical datacenter).
*
* @author Ignasi Barrera
*/
@Singleton
public class VirtualMachineTemplateToImage implements Function<VirtualMachineTemplate, Image>
{
private final Function<Datacenter, Location> datacenterToLocation;
private final Supplier<Map<Integer, Datacenter>> regionMap;
@Inject
public VirtualMachineTemplateToImage(final Function<Datacenter, Location> datacenterToLocation,
@Memoized final Supplier<Map<Integer, Datacenter>> reginoMap)
{
this.datacenterToLocation = checkNotNull(datacenterToLocation, "datacenterToLocation");
this.regionMap = checkNotNull(reginoMap, "reginoMap");
}
@Override
public Image apply(final VirtualMachineTemplate template)
@ -49,6 +71,11 @@ public class VirtualMachineTemplateToImage implements Function<VirtualMachineTem
builder.name(template.getName());
builder.description(template.getDescription());
// Location information
Datacenter region =
regionMap.get().get(template.unwrap().getIdFromLink(ParentLinkName.DATACENTER));
builder.location(datacenterToLocation.apply(region));
// Only conversions have a status
builder.status(Status.AVAILABLE);
builder.backendStatus(Status.AVAILABLE.name()); // Abiquo images do not have a status
@ -57,9 +84,10 @@ public class VirtualMachineTemplateToImage implements Function<VirtualMachineTem
builder.uri(downloadLink == null ? null : URI.create(downloadLink.getHref()));
// TODO: Operating system not implemented in Abiquo Templates
// TODO: Image credentials still not present in Abiquo template metadata
// Will be added in Abiquo 2.4: http://jira.abiquo.com/browse/ABICLOUDPREMIUM-3647
builder.operatingSystem(OperatingSystem.builder().description(template.getName()).build());
// TODO: image credentials
return builder.build();
}
}

View File

@ -19,41 +19,68 @@
package org.jclouds.abiquo.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.abiquo.domain.cloud.VirtualDatacenter;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplateWithZone;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.VolumeBuilder;
import org.jclouds.compute.predicates.ImagePredicates;
import org.jclouds.domain.Location;
import com.google.common.base.Function;
/**
* Transforms a {@link VirtualMachineTemplate} into an {@link Hardware}.
* <p>
* Each {@link Image} ({@link VirtualMachineTemplate}) will have one {@link Hardware} entity for
* each zone (scoped to a virtualization technology) supported by the image.
*
* @author Ignasi Barrera
*/
@Singleton
public class VirtualMachineTemplateToHardware implements Function<VirtualMachineTemplate, Hardware>
public class VirtualMachineTemplateWithZoneToHardware implements
Function<VirtualMachineTemplateWithZone, Hardware>
{
/** The default core speed, 2.0Ghz. */
public static final double DEFAULT_CORE_SPEED = 2.0;
@Override
public Hardware apply(final VirtualMachineTemplate template)
private final Function<VirtualDatacenter, Location> virtualDatacenterToLocation;
@Inject
public VirtualMachineTemplateWithZoneToHardware(
final Function<VirtualDatacenter, Location> virtualDatacenterToLocation)
{
this.virtualDatacenterToLocation =
checkNotNull(virtualDatacenterToLocation, "virtualDatacenterToLocation");
}
@Override
public Hardware apply(final VirtualMachineTemplateWithZone templateWithZone)
{
VirtualMachineTemplate template = templateWithZone.getTemplate();
VirtualDatacenter zone = templateWithZone.getZone();
HardwareBuilder builder = new HardwareBuilder();
builder.ids(template.getId().toString());
builder.providerId(template.getId().toString());
builder.id(template.getId().toString() + "-" + zone.getId());
builder.uri(template.getURI());
builder.name(template.getName());
builder.processor(new Processor(template.getCpuRequired(), DEFAULT_CORE_SPEED));
builder.ram(template.getRamRequired());
// Currently we consider each template as a hardware profile
// Location information
builder.location(virtualDatacenterToLocation.apply(zone));
builder.hypervisor(zone.getHypervisorType().name());
builder.supportsImage(ImagePredicates.idEquals(template.getId().toString()));
VolumeBuilder volumeBuilder = new VolumeBuilder();

View File

@ -32,7 +32,7 @@ import javax.inject.Singleton;
import org.jclouds.abiquo.domain.cloud.VirtualDatacenter;
import org.jclouds.abiquo.domain.cloud.VirtualMachine;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import org.jclouds.abiquo.domain.infrastructure.Datacenter;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplateWithZone;
import org.jclouds.abiquo.domain.network.Ip;
import org.jclouds.abiquo.domain.network.PrivateIp;
import org.jclouds.compute.domain.Hardware;
@ -41,12 +41,13 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.Processor;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import com.abiquo.server.core.cloud.VirtualMachineState;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
/**
* Links a {@link VirtualMachine} object to a {@link NodeMetadata} one.
@ -61,18 +62,18 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
private final VirtualMachineTemplateToImage virtualMachineTemplateToImage;
private final VirtualMachineTemplateToHardware virtualMachineTemplateToHardware;
private final VirtualMachineTemplateWithZoneToHardware virtualMachineTemplateToHardware;
private final VirtualMachineStateToNodeState virtualMachineStateToNodeState;
private final DatacenterToLocation datacenterToLocation;
private final Function<VirtualDatacenter, Location> virtualDatacenterToLocation;
@Inject
public VirtualMachineToNodeMetadata(
final VirtualMachineTemplateToImage virtualMachineTemplateToImage,
final VirtualMachineTemplateToHardware virtualMachineTemplateToHardware,
final VirtualMachineTemplateWithZoneToHardware virtualMachineTemplateToHardware,
final VirtualMachineStateToNodeState virtualMachineStateToNodeState,
final DatacenterToLocation datacenterToLocation)
final Function<VirtualDatacenter, Location> virtualDatacenterToLocation)
{
this.virtualMachineTemplateToImage =
checkNotNull(virtualMachineTemplateToImage, "virtualMachineTemplateToImage");
@ -80,7 +81,8 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
checkNotNull(virtualMachineTemplateToHardware, "virtualMachineTemplateToHardware");
this.virtualMachineStateToNodeState =
checkNotNull(virtualMachineStateToNodeState, "virtualMachineStateToNodeState");
this.datacenterToLocation = checkNotNull(datacenterToLocation, "datacenterToLocation");
this.virtualDatacenterToLocation =
checkNotNull(virtualDatacenterToLocation, "virtualDatacenterToLocation");
}
@Override
@ -92,19 +94,12 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
builder.name(vm.getNameLabel());
builder.group(vm.getVirtualAppliance().getName());
// TODO: builder.credentials() (http://jira.abiquo.com/browse/ABICLOUDPREMIUM-3647)
VirtualDatacenter vdc = vm.getVirtualDatacenter();
// TODO: Node credentials still not present in Abiquo template metadata
// Will be added in Abiquo 2.4: http://jira.abiquo.com/browse/ABICLOUDPREMIUM-3647
// Location details
try
{
Datacenter datacenter = vdc.getDatacenter();
builder.location(datacenterToLocation.apply(datacenter));
}
catch (AuthorizationException ex)
{
logger.debug("User does not have permissions to see the location of the node");
}
VirtualDatacenter vdc = vm.getVirtualDatacenter();
builder.location(virtualDatacenterToLocation.apply(vdc));
// Image details
VirtualMachineTemplate template = vm.getTemplate();
@ -113,18 +108,19 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
builder.operatingSystem(image.getOperatingSystem());
// Hardware details
Hardware defaultHardware = virtualMachineTemplateToHardware.apply(template);
Hardware defaultHardware =
virtualMachineTemplateToHardware
.apply(new VirtualMachineTemplateWithZone(template, vdc));
Hardware hardware =
new HardwareBuilder() //
.ids(defaultHardware.getId()) //
.uri(defaultHardware.getUri()) //
.name(defaultHardware.getName()) //
.supportsImage(defaultHardware.supportsImage()) //
.ram(vm.getRam()) //
.hypervisor(vdc.getHypervisorType().name()) //
.processor(
new Processor(vm.getCpu(), VirtualMachineTemplateToHardware.DEFAULT_CORE_SPEED)) //
HardwareBuilder
.fromHardware(defaultHardware)
.ram(vm.getRam())
.processors(
Lists.newArrayList(new Processor(vm.getCpu(),
VirtualMachineTemplateWithZoneToHardware.DEFAULT_CORE_SPEED))) //
.build();
builder.hardware(hardware);
// Networking configuration

View File

@ -19,9 +19,6 @@
package org.jclouds.abiquo.compute.options;
import org.jclouds.abiquo.domain.network.Ip;
import org.jclouds.abiquo.domain.network.Network;
import org.jclouds.abiquo.domain.network.UnmanagedNetwork;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.options.TemplateOptions;
@ -43,14 +40,6 @@ public class AbiquoTemplateOptions extends TemplateOptions implements Cloneable
private String vncPassword;
private String virtualDatacenter;
private Ip< ? , ? >[] ips;
private UnmanagedNetwork[] unmanagedIps;
private Network< ? > gatewayNetwork;
@Override
public TemplateOptions clone()
{
@ -69,8 +58,6 @@ public class AbiquoTemplateOptions extends TemplateOptions implements Cloneable
options.overrideCores(overrideCores);
options.overrideRam(overrideRam);
options.vncPassword(vncPassword);
options.virtualDatacenter(virtualDatacenter);
options.ips(ips);
}
}
@ -124,71 +111,6 @@ public class AbiquoTemplateOptions extends TemplateOptions implements Cloneable
return vncPassword;
}
/**
* Set the virtual datacenter where the virtual machine must be deployed.
*
* @return The template options with the virtual machine must be deployed.
*/
public AbiquoTemplateOptions virtualDatacenter(final String virtualDatacenter)
{
this.virtualDatacenter = virtualDatacenter;
return this;
}
public String getVirtualDatacenter()
{
return virtualDatacenter;
}
/**
* Set the ip addresses for the virtual machine.
*
* @return The template options with the ip addresses configuration.
*/
public AbiquoTemplateOptions ips(final Ip< ? , ? >... ips)
{
this.ips = ips;
return this;
}
public Ip< ? , ? >[] getIps()
{
return ips;
}
/**
* Set the ip addresses that must be selected from unmanaged networks.
*
* @return The template options with the ip addresses that must be selected from unmanaged
* networks.
*/
public AbiquoTemplateOptions unmanagedIps(final UnmanagedNetwork... unmanagedIps)
{
this.unmanagedIps = unmanagedIps;
return this;
}
public UnmanagedNetwork[] getUnmanagedIps()
{
return unmanagedIps;
}
/**
* Set the gateway network for the virtual machine.
*
* @return The template options with the gateway network configuration.
*/
public AbiquoTemplateOptions gatewayNetwork(final Network< ? > gatewayNetwork)
{
this.gatewayNetwork = gatewayNetwork;
return this;
}
public Network< ? > getGatewayNetwork()
{
return gatewayNetwork;
}
public static class Builder
{
/**
@ -217,41 +139,5 @@ public class AbiquoTemplateOptions extends TemplateOptions implements Cloneable
AbiquoTemplateOptions options = new AbiquoTemplateOptions();
return options.vncPassword(vncPassword);
}
/**
* @see AbiquoTemplateOptions#virtualDatacenter(String)
*/
public static AbiquoTemplateOptions virtualDatacenter(final String virtualDatacenter)
{
AbiquoTemplateOptions options = new AbiquoTemplateOptions();
return options.virtualDatacenter(virtualDatacenter);
}
/**
* @see AbiquoTemplateOptions#ips(Ip...)
*/
public static AbiquoTemplateOptions ips(final Ip< ? , ? >... ips)
{
AbiquoTemplateOptions options = new AbiquoTemplateOptions();
return options.ips(ips);
}
/**
* @see AbiquoTemplateOptions#unmanagedIps(UnmanagedNetwork...)
*/
public AbiquoTemplateOptions unmanagedIps(final UnmanagedNetwork... unmanagedIps)
{
AbiquoTemplateOptions options = new AbiquoTemplateOptions();
return options.unmanagedIps(unmanagedIps);
}
/**
* @see AbiquoTemplateOptions#gatewayNetwork(Network)
*/
public static AbiquoTemplateOptions gatewayNetwork(final Network< ? > gatewayNetwork)
{
AbiquoTemplateOptions options = new AbiquoTemplateOptions();
return options.gatewayNetwork(gatewayNetwork);
}
}
}

View File

@ -20,11 +20,13 @@
package org.jclouds.abiquo.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.transform;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
@ -35,16 +37,18 @@ import org.jclouds.abiquo.domain.cloud.VirtualAppliance;
import org.jclouds.abiquo.domain.cloud.VirtualDatacenter;
import org.jclouds.abiquo.domain.cloud.VirtualMachine;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplateWithZone;
import org.jclouds.abiquo.domain.enterprise.Enterprise;
import org.jclouds.abiquo.domain.enterprise.User;
import org.jclouds.abiquo.domain.infrastructure.Datacenter;
import org.jclouds.abiquo.domain.network.PublicIp;
import org.jclouds.abiquo.features.services.AdministrationService;
import org.jclouds.abiquo.features.services.CloudService;
import org.jclouds.abiquo.features.services.MonitoringService;
import org.jclouds.abiquo.monitor.VirtualMachineMonitor;
import org.jclouds.abiquo.predicates.cloud.VirtualAppliancePredicates;
import org.jclouds.abiquo.predicates.cloud.VirtualMachineTemplatePredicates;
import org.jclouds.abiquo.predicates.infrastructure.DatacenterPredicates;
import org.jclouds.abiquo.predicates.network.IpPredicates;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Hardware;
@ -55,7 +59,11 @@ import org.jclouds.logging.Logger;
import org.jclouds.rest.RestContext;
import com.abiquo.server.core.cloud.VirtualMachineState;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
/**
* Defines the connection between the {@link AbiquoApi} implementation and the jclouds
@ -66,7 +74,7 @@ import com.google.common.base.Predicate;
@Singleton
public class AbiquoComputeServiceAdapter
implements
ComputeServiceAdapter<VirtualMachine, VirtualMachineTemplate, VirtualMachineTemplate, Datacenter>
ComputeServiceAdapter<VirtualMachine, VirtualMachineTemplateWithZone, VirtualMachineTemplate, VirtualDatacenter>
{
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
@ -80,19 +88,24 @@ public class AbiquoComputeServiceAdapter
private final MonitoringService monitoringService;
private AbiquoComputeServiceHelper helper;
private final FindCompatibleVirtualDatacenters compatibleVirtualDatacenters;
private final Supplier<Map<Integer, Datacenter>> regionMap;
@Inject
public AbiquoComputeServiceAdapter(final RestContext<AbiquoApi, AbiquoAsyncApi> context,
final AdministrationService adminService, final CloudService cloudService,
final MonitoringService monitoringService, final AbiquoComputeServiceHelper helper)
final MonitoringService monitoringService,
final FindCompatibleVirtualDatacenters compatibleVirtualDatacenters,
@Memoized final Supplier<Map<Integer, Datacenter>> regionMap)
{
super();
this.context = checkNotNull(context, "context");
this.adminService = checkNotNull(adminService, "adminService");
this.cloudService = checkNotNull(cloudService, "cloudService");
this.monitoringService = checkNotNull(monitoringService, "monitoringService");
this.helper = checkNotNull(helper, "helper");
this.compatibleVirtualDatacenters =
checkNotNull(compatibleVirtualDatacenters, "compatibleVirtualDatacenters");
this.regionMap = checkNotNull(regionMap, "regionMap");
}
@Override
@ -100,23 +113,23 @@ public class AbiquoComputeServiceAdapter
final String tag, final String name, final Template template)
{
AbiquoTemplateOptions options = template.getOptions().as(AbiquoTemplateOptions.class);
User user = adminService.getCurrentUser();
Enterprise enterprise = adminService.getCurrentEnterprise();
// Get the region where the template is available
Datacenter datacenter =
enterprise.findAllowedDatacenter(DatacenterPredicates.id(Integer.valueOf(template
.getLocation().getId())));
regionMap.get().get(Integer.valueOf(template.getImage().getLocation().getId()));
// Load the template
VirtualMachineTemplate virtualMachineTemplate =
enterprise.getTemplateInRepository(datacenter,
Integer.valueOf(template.getImage().getId()));
// Get the zone where the template will be deployed
VirtualDatacenter vdc =
helper.getOrCreateVirtualDatacenter(user, enterprise, datacenter,
virtualMachineTemplate, options);
cloudService.getVirtualDatacenter(Integer.valueOf(template.getHardware().getLocation()
.getId()));
// Load the virtual appliance or create it
// Load the virtual appliance or create it if it does not exist
VirtualAppliance vapp = vdc.findVirtualAppliance(VirtualAppliancePredicates.name(tag));
if (vapp == null)
{
@ -137,24 +150,51 @@ public class AbiquoComputeServiceAdapter
vm.save();
// Once the virtual machine is created, override the default network settings if needed
helper.configureNetwork(vm, options.getGatewayNetwork(), options.getIps() == null ? null
: Arrays.asList(options.getIps()),
options.getUnmanagedIps() == null ? null : Arrays.asList(options.getUnmanagedIps()));
// If no public ip is available in the virtual datacenter, the virtual machine will be
// assigned by default an ip address in the default private VLAN for the virtual datacenter
PublicIp publicIp = vdc.findPurchasedPublicIp(IpPredicates.<PublicIp> notUsed());
if (publicIp != null)
{
List<PublicIp> ips = Lists.newArrayList();
ips.add(publicIp);
vm.setNics(ips);
}
VirtualMachineMonitor monitor = monitoringService.getVirtualMachineMonitor();
// This is an async operation, but jclouds already waits until the node is RUNNING, so there
// is no need to block here
vm.deploy();
monitor.awaitCompletionDeploy(vm);
return new NodeAndInitialCredentials<VirtualMachine>(vm, vm.getId().toString(), template
.getImage().getDefaultCredentials());
return new NodeAndInitialCredentials<VirtualMachine>(vm, vm.getId().toString(), null);
}
@Override
public Iterable<VirtualMachineTemplate> listHardwareProfiles()
public Iterable<VirtualMachineTemplateWithZone> listHardwareProfiles()
{
// Abiquo does not have the hardwre profiles concept. Users can consume CPU and RAM
// resources limited only by the Enterprise or Virtual datacenter limits.
return listImages();
// In Abiquo, images are scoped to a region (physical datacenter), and hardware profiles are
// scoped to a zone (a virtual datacenter in the region, with a concrete virtualization
// technology)
return concat(transform(listImages(),
new Function<VirtualMachineTemplate, Iterable<VirtualMachineTemplateWithZone>>()
{
@Override
public Iterable<VirtualMachineTemplateWithZone> apply(
final VirtualMachineTemplate template)
{
Iterable<VirtualDatacenter> compatibleZones =
compatibleVirtualDatacenters.execute(template);
return transform(compatibleZones,
new Function<VirtualDatacenter, VirtualMachineTemplateWithZone>()
{
@Override
public VirtualMachineTemplateWithZone apply(final VirtualDatacenter vdc)
{
return new VirtualMachineTemplateWithZone(template, vdc);
}
});
}
}));
}
@Override
@ -172,17 +212,14 @@ public class AbiquoComputeServiceAdapter
}
@Override
public Iterable<Datacenter> listLocations()
public Iterable<VirtualDatacenter> listLocations()
{
Enterprise enterprise = adminService.getCurrentEnterprise();
return enterprise.listAllowedDatacenters();
return cloudService.listVirtualDatacenters();
}
@Override
public VirtualMachine getNode(final String id)
{
// FIXME: Try to avoid calling the cloudService.findVirtualMachine. Navigate the hierarchy
// instead.
return cloudService.findVirtualMachine(vmId(id));
}

View File

@ -1,256 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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 org.jclouds.abiquo.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.getFirst;
import java.util.List;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.abiquo.AbiquoApi;
import org.jclouds.abiquo.AbiquoAsyncApi;
import org.jclouds.abiquo.compute.exception.NotEnoughResourcesException;
import org.jclouds.abiquo.compute.options.AbiquoTemplateOptions;
import org.jclouds.abiquo.domain.cloud.Conversion;
import org.jclouds.abiquo.domain.cloud.VirtualDatacenter;
import org.jclouds.abiquo.domain.cloud.VirtualMachine;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import org.jclouds.abiquo.domain.enterprise.Enterprise;
import org.jclouds.abiquo.domain.enterprise.User;
import org.jclouds.abiquo.domain.exception.AbiquoException;
import org.jclouds.abiquo.domain.infrastructure.Datacenter;
import org.jclouds.abiquo.domain.network.Ip;
import org.jclouds.abiquo.domain.network.Network;
import org.jclouds.abiquo.domain.network.PrivateNetwork;
import org.jclouds.abiquo.domain.network.UnmanagedNetwork;
import org.jclouds.abiquo.features.services.CloudService;
import org.jclouds.abiquo.predicates.cloud.VirtualDatacenterPredicates;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.logging.Logger;
import org.jclouds.rest.RestContext;
import com.abiquo.model.enumerator.ConversionState;
import com.abiquo.model.enumerator.HypervisorType;
import com.google.common.base.Predicate;
/**
* Helper methods to perform {@link AbiquoComputeServiceAdapter} operations.
*
* @author Ignasi Barrera
*/
@Singleton
public class AbiquoComputeServiceHelper
{
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private RestContext<AbiquoApi, AbiquoAsyncApi> context;
private CloudService cloudService;
@Inject
public AbiquoComputeServiceHelper(final RestContext<AbiquoApi, AbiquoAsyncApi> context,
final CloudService cloudService)
{
super();
this.context = checkNotNull(context, "context");
this.cloudService = checkNotNull(cloudService, "cloudService");
}
/**
* Gets a virtual datacenter where the given template can be deployed.
* <p>
* If no compatible virtual datacenter is found, one will be created, if possible.
*
* @param user The current user.
* @param enterprise The enterprise of the current user.
* @param datacenter The datacenter of the template.
* @param template The template to deploy.
* @param options The template options
* @return The virtual datacenter to be used to deploy the template or <code>null</code> if none
* was found and a compatible one could not be created.
*/
public VirtualDatacenter getOrCreateVirtualDatacenter(final User user,
final Enterprise enterprise, final Datacenter datacenter,
final VirtualMachineTemplate template, final AbiquoTemplateOptions options)
{
Iterable<VirtualDatacenter> compatibles =
findCompatibleVirtualDatacenters(datacenter, template);
VirtualDatacenter vdc =
options.getVirtualDatacenter() == null ? getFirst(compatibles, null) : find(
compatibles, VirtualDatacenterPredicates.name(options.getVirtualDatacenter()));
if (vdc == null)
{
vdc =
createCompatibleVirtualDatacenter(user, enterprise, datacenter, template,
options.getVirtualDatacenter());
if (vdc == null)
{
throw new NotEnoughResourcesException("There are not resources to deploy the given template");
}
}
return vdc;
}
/**
* Find the virtual datacenters compatible with the given template.
*
* @param datacenter The datacenter of the template.
* @param template The template to deploy.
* @return The virtual datacenters compatible with the given template.
*/
public Iterable<VirtualDatacenter> findCompatibleVirtualDatacenters(
final Datacenter datacenter, final VirtualMachineTemplate template)
{
Iterable<VirtualDatacenter> vdcs =
cloudService.listVirtualDatacenters(VirtualDatacenterPredicates.datacenter(datacenter));
return filter(vdcs, new Predicate<VirtualDatacenter>()
{
@Override
public boolean apply(final VirtualDatacenter vdc)
{
return isTemplateCompatibleWithHypervisor(template, vdc.getHypervisorType());
}
});
}
/**
* Configure networking resources for the given virtual machine.
*
* @param vm The virtual machine to configure.
* @param gatewayNetwork The network to be used as a gateway.
* @param ips The ips to attach to the virtual machine.
*/
public void configureNetwork(final VirtualMachine vm,
@Nullable final Network< ? > gatewayNetwork,
@Nullable final List<Ip< ? , ? extends Network< ? >>> ips,
@Nullable final List<UnmanagedNetwork> unmanagedIps)
{
if (ips != null)
{
// TODO: External ips don't have the right link
// (http://jira.abiquo.com/browse/ABICLOUDPREMIUM-3650)
if (gatewayNetwork == null)
{
// By default the network of the first ip will be used as a gateway
vm.setNics(ips, unmanagedIps);
}
else
{
vm.setNics(gatewayNetwork, ips, unmanagedIps);
}
}
}
/**
* Create a new virtual datacenter compatible with the given template.
*
* @param user The current user.
* @param enterprise The enterprise of the current user.
* @param datacenter The datacenter of the template.
* @param template The template to deploy.
* @return
*/
private VirtualDatacenter createCompatibleVirtualDatacenter(final User user,
final Enterprise enterprise, final Datacenter datacenter,
final VirtualMachineTemplate template, final String name)
{
PrivateNetwork defaultNetwork =
PrivateNetwork.builder(context).name("DefaultNetwork").gateway("192.168.1.1")
.address("192.168.1.0").mask(24).build();
VirtualDatacenter vdc =
VirtualDatacenter.builder(context, datacenter, enterprise).network(defaultNetwork)
.build();
// Find the first hypervisor in the datacenter compatible with the template
for (HypervisorType type : HypervisorType.values())
{
if (isTemplateCompatibleWithHypervisor(template, type))
{
try
{
logger.info("Trying to create a virtual datacenter of type %s", type.name());
vdc.setName(name != null ? name : "JC-" + type.name());
vdc.setHypervisorType(type);
vdc.save();
logger.info("Virtual datacenter created");
return vdc;
}
catch (AbiquoException ex)
{
// Just catch the error thrown when no hypervisors of the given type are
// available in the datacenter
if (ex.hasError("VDC-1"))
{
continue;
}
else
{
throw ex;
}
}
}
}
logger.warn("Could not create a compatible virtual datacenter for template of type %s",
template.getDiskFormatType().name());
return null;
}
/**
* Check if the given template type is compatible with the given hypervisor type.
*
* @param template The template to check.
* @param type The type of the hypervisor.
* @return Boolean indicating if the given template type is compatible with the given hypervisor
* type.
*/
private static boolean isTemplateCompatibleWithHypervisor(
final VirtualMachineTemplate template, final HypervisorType type)
{
boolean compatible = type.isCompatible(template.getDiskFormatType());
if (!compatible)
{
List<Conversion> compatibleConversions =
template.listConversions(type, ConversionState.FINISHED);
compatible = compatibleConversions != null && !compatibleConversions.isEmpty();
}
return compatible;
}
}

View File

@ -17,37 +17,21 @@
* under the License.
*/
package org.jclouds.abiquo.compute.exception;
package org.jclouds.abiquo.compute.strategy;
import org.jclouds.abiquo.compute.strategy.internal.FindCompatibleVirtualDatacentersForImageAndConversions;
import org.jclouds.abiquo.domain.cloud.VirtualDatacenter;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import com.google.inject.ImplementedBy;
/**
* Exception thrown when there are not enough resources in the infrastructure to deploy the desired
* template.
* Finds all virtual datacenters where the given {@link VirtualMachineTemplate} can be deployed.
*
* @author Ignasi Barrera
*/
public class NotEnoughResourcesException extends RuntimeException
@ImplementedBy(FindCompatibleVirtualDatacentersForImageAndConversions.class)
public interface FindCompatibleVirtualDatacenters
{
/** Serial UID. */
private static final long serialVersionUID = 1L;
public NotEnoughResourcesException()
{
super();
}
public NotEnoughResourcesException(final String arg0, final Throwable arg1)
{
super(arg0, arg1);
}
public NotEnoughResourcesException(final String arg0)
{
super(arg0);
}
public NotEnoughResourcesException(final Throwable arg0)
{
super(arg0);
}
Iterable<VirtualDatacenter> execute(VirtualMachineTemplate template);
}

View File

@ -0,0 +1,82 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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 org.jclouds.abiquo.compute.strategy.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.abiquo.domain.DomainWrapper.wrap;
import static org.jclouds.abiquo.predicates.cloud.VirtualDatacenterPredicates.compatibleWithTemplateOrConversions;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.abiquo.AbiquoApi;
import org.jclouds.abiquo.AbiquoAsyncApi;
import org.jclouds.abiquo.compute.strategy.FindCompatibleVirtualDatacenters;
import org.jclouds.abiquo.domain.cloud.VirtualDatacenter;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import org.jclouds.abiquo.domain.infrastructure.Datacenter;
import org.jclouds.abiquo.features.services.CloudService;
import org.jclouds.abiquo.predicates.cloud.VirtualDatacenterPredicates;
import org.jclouds.abiquo.reference.rest.ParentLinkName;
import org.jclouds.rest.RestContext;
import com.abiquo.server.core.infrastructure.DatacenterDto;
/**
* Default implementation for the {@link FindCompatibleVirtualDatacenters} strategy.
* <p>
* This strategy assumes that the datacenter will have different hypervisor technologies, and images
* will have conversions to each of them.
*
* @author Ignasi Barrera
*/
@Singleton
public class FindCompatibleVirtualDatacentersForImageAndConversions implements
FindCompatibleVirtualDatacenters
{
private final RestContext<AbiquoApi, AbiquoAsyncApi> context;
private final CloudService cloudService;
@Inject
public FindCompatibleVirtualDatacentersForImageAndConversions(
final RestContext<AbiquoApi, AbiquoAsyncApi> context, final CloudService cloudService)
{
this.context = checkNotNull(context, "context");
this.cloudService = checkNotNull(cloudService, "cloudService");
}
@Override
public Iterable<VirtualDatacenter> execute(final VirtualMachineTemplate template)
{
// Build the transport object with the available information to avoid making an unnecessary
// call to the target API (we only need the id of the datacenter, and it is present in the
// link).
DatacenterDto datacenterDto = new DatacenterDto();
datacenterDto.setId(template.unwrap().getIdFromLink(ParentLinkName.DATACENTER_REPOSITORY));
Datacenter datacenter = wrap(context, Datacenter.class, datacenterDto);
Iterable<VirtualDatacenter> vdcs =
cloudService.listVirtualDatacenters(VirtualDatacenterPredicates.datacenter(datacenter));
return filter(vdcs, compatibleWithTemplateOrConversions(template));
}
}

View File

@ -0,0 +1,94 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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 org.jclouds.abiquo.compute.strategy.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.abiquo.domain.DomainWrapper.wrap;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.abiquo.AbiquoApi;
import org.jclouds.abiquo.AbiquoAsyncApi;
import org.jclouds.abiquo.compute.strategy.FindCompatibleVirtualDatacenters;
import org.jclouds.abiquo.domain.cloud.VirtualDatacenter;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import org.jclouds.abiquo.domain.infrastructure.Datacenter;
import org.jclouds.abiquo.features.services.CloudService;
import org.jclouds.abiquo.predicates.cloud.VirtualDatacenterPredicates;
import org.jclouds.abiquo.reference.rest.ParentLinkName;
import org.jclouds.rest.RestContext;
import com.abiquo.model.enumerator.HypervisorType;
import com.abiquo.server.core.infrastructure.DatacenterDto;
import com.google.common.base.Predicate;
/**
* Implementation for the {@link FindCompatibleVirtualDatacenters} strategy to be used in
* homogeneous datacenters.
* <p>
* For providers that only have one hypervisor technology in the physical datacenter and use
* compatible images, there is no need to check if the images have conversions to other formats.
* <p>
* This strategy will only consider the base disk format of the image.
*
* @author Ignasi Barrera
*/
@Singleton
public class FindCompatibleVirtualDatacentersForImageBaseFormat implements
FindCompatibleVirtualDatacenters
{
private final RestContext<AbiquoApi, AbiquoAsyncApi> context;
private final CloudService cloudService;
@Inject
public FindCompatibleVirtualDatacentersForImageBaseFormat(
final RestContext<AbiquoApi, AbiquoAsyncApi> context, final CloudService cloudService)
{
this.context = checkNotNull(context, "context");
this.cloudService = checkNotNull(cloudService, "cloudService");
}
@Override
public Iterable<VirtualDatacenter> execute(final VirtualMachineTemplate template)
{
// Build the transport object with the available information to avoid making an unnecessary
// call to the target API (we only need the id of the datacenter, and it is present in the
// link).
DatacenterDto datacenterDto = new DatacenterDto();
datacenterDto.setId(template.unwrap().getIdFromLink(ParentLinkName.DATACENTER_REPOSITORY));
Datacenter datacenter = wrap(context, Datacenter.class, datacenterDto);
Iterable<VirtualDatacenter> vdcs =
cloudService.listVirtualDatacenters(VirtualDatacenterPredicates.datacenter(datacenter));
return filter(vdcs, new Predicate<VirtualDatacenter>()
{
@Override
public boolean apply(final VirtualDatacenter vdc)
{
HypervisorType type = vdc.getHypervisorType();
return type.isCompatible(template.getDiskFormatType());
}
});
}
}

View File

@ -20,18 +20,20 @@
package org.jclouds.abiquo.config;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.abiquo.domain.DomainWrapper.wrap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.abiquo.AbiquoApi;
import org.jclouds.abiquo.AbiquoAsyncApi;
import org.jclouds.abiquo.domain.enterprise.Enterprise;
import org.jclouds.abiquo.domain.enterprise.User;
import org.jclouds.abiquo.domain.infrastructure.Datacenter;
import org.jclouds.abiquo.features.AdminApi;
import org.jclouds.abiquo.features.AdminAsyncApi;
import org.jclouds.abiquo.features.CloudApi;
@ -54,8 +56,6 @@ import org.jclouds.abiquo.handlers.AbiquoErrorHandler;
import org.jclouds.abiquo.rest.internal.AbiquoHttpAsyncClient;
import org.jclouds.abiquo.rest.internal.AbiquoHttpClient;
import org.jclouds.abiquo.rest.internal.ExtendedUtils;
import org.jclouds.abiquo.suppliers.GetCurrentEnterprise;
import org.jclouds.abiquo.suppliers.GetCurrentUser;
import org.jclouds.collect.Memoized;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.annotation.ClientError;
@ -63,14 +63,19 @@ import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.Utils;
import org.jclouds.rest.config.BinderUtils;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
import org.jclouds.util.Suppliers2;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.inject.Provides;
import com.google.inject.Singleton;
/**
* Configures the Abiquo connection.
@ -134,10 +139,19 @@ public class AbiquoRestClientModule extends RestClientModule<AbiquoApi, AbiquoAs
@Memoized
public Supplier<User> getCurrentUser(
final AtomicReference<AuthorizationException> authException,
@Named(PROPERTY_SESSION_INTERVAL) final long seconds, final GetCurrentUser getCurrentUser)
@Named(PROPERTY_SESSION_INTERVAL) final long seconds,
final RestContext<AbiquoApi, AbiquoAsyncApi> context)
{
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
getCurrentUser, seconds, TimeUnit.SECONDS);
new Supplier<User>()
{
@Override
public User get()
{
return wrap(context, User.class, context.getApi().getAdminApi()
.getCurrentUser());
}
}, seconds, TimeUnit.SECONDS);
}
@Provides
@ -146,10 +160,54 @@ public class AbiquoRestClientModule extends RestClientModule<AbiquoApi, AbiquoAs
public Supplier<Enterprise> getCurrentEnterprise(
final AtomicReference<AuthorizationException> authException,
@Named(PROPERTY_SESSION_INTERVAL) final long seconds,
final GetCurrentEnterprise getCurrentEnterprise)
final @Memoized Supplier<User> currentUser)
{
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
getCurrentEnterprise, seconds, TimeUnit.SECONDS);
new Supplier<Enterprise>()
{
@Override
public Enterprise get()
{
return currentUser.get().getEnterprise();
}
}, seconds, TimeUnit.SECONDS);
}
@Provides
@Singleton
@Memoized
public Supplier<Map<Integer, Datacenter>> getAvailableRegionsIndexedById(
final AtomicReference<AuthorizationException> authException,
@Named(PROPERTY_SESSION_INTERVAL) final long seconds,
@Memoized final Supplier<Enterprise> currentEnterprise)
{
Supplier<Map<Integer, Datacenter>> availableRegionsMapSupplier =
Suppliers2.compose(new Function<List<Datacenter>, Map<Integer, Datacenter>>()
{
@Override
public Map<Integer, Datacenter> apply(final List<Datacenter> datacenters)
{
// Index available regions by id
return Maps.uniqueIndex(datacenters, new Function<Datacenter, Integer>()
{
@Override
public Integer apply(final Datacenter input)
{
return input.getId();
}
});
}
}, new Supplier<List<Datacenter>>()
{
@Override
public List<Datacenter> get()
{
// Get the list of regions available for the user's tenant
return currentEnterprise.get().listAllowedDatacenters();
}
});
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
availableRegionsMapSupplier, seconds, TimeUnit.SECONDS);
}
}

View File

@ -35,6 +35,8 @@ import org.jclouds.abiquo.domain.network.Network;
import org.jclouds.abiquo.domain.network.UnmanagedNetwork;
import org.jclouds.abiquo.domain.task.AsyncTask;
import org.jclouds.abiquo.domain.util.LinkUtils;
import org.jclouds.abiquo.features.services.MonitoringService;
import org.jclouds.abiquo.monitor.VirtualMachineMonitor;
import org.jclouds.abiquo.predicates.LinkPredicates;
import org.jclouds.abiquo.reference.ValidationErrors;
import org.jclouds.abiquo.reference.rest.ParentLinkName;
@ -55,6 +57,8 @@ import com.abiquo.server.core.cloud.VirtualMachineTaskDto;
import com.abiquo.server.core.cloud.VirtualMachineWithNodeExtendedDto;
import com.abiquo.server.core.enterprise.EnterpriseDto;
import com.abiquo.server.core.infrastructure.network.UnmanagedIpDto;
import com.abiquo.server.core.infrastructure.network.VMNetworkConfigurationDto;
import com.abiquo.server.core.infrastructure.network.VMNetworkConfigurationsDto;
import com.abiquo.server.core.infrastructure.storage.DiskManagementDto;
import com.abiquo.server.core.infrastructure.storage.DisksManagementDto;
import com.abiquo.server.core.infrastructure.storage.DvdManagementDto;
@ -492,13 +496,13 @@ public class VirtualMachine extends DomainWithTasksWrapper<VirtualMachineWithNod
return setVolumes(true, volumes);
}
public AsyncTask setNics(final List<Ip< ? , ? >> ips)
public AsyncTask setNics(final List< ? extends Ip< ? , ? >> ips)
{
// By default the network of the first ip will be used as a gateway
return setNics(ips != null && !ips.isEmpty() ? ips.get(0).getNetwork() : null, ips, null);
}
public AsyncTask setNics(final List<Ip< ? , ? >> ips,
public AsyncTask setNics(final List< ? extends Ip< ? , ? >> ips,
final List<UnmanagedNetwork> unmanagetNetworks)
{
// By default the network of the first ip will be used as a gateway
@ -515,18 +519,15 @@ public class VirtualMachine extends DomainWithTasksWrapper<VirtualMachineWithNod
return setNics(gateway, ips, unmanagetNetworks);
}
public AsyncTask setNics(final Network< ? > gatewayNetwork, final List<Ip< ? , ? >> ips)
public AsyncTask setNics(final Network< ? > gatewayNetwork,
final List< ? extends Ip< ? , ? >> ips)
{
return setNics(gatewayNetwork, ips, null);
}
public AsyncTask setNics(final Network< ? > gatewayNetwork, final List<Ip< ? , ? >> ips,
final List<UnmanagedNetwork> unmanagetNetworks)
public AsyncTask setNics(final Network< ? > gatewayNetwork,
final List< ? extends Ip< ? , ? >> ips, final List<UnmanagedNetwork> unmanagetNetworks)
{
RESTLink configLink =
checkNotNull(target.searchLink(ParentLinkName.NETWORK_CONFIGURATIONS),
ValidationErrors.MISSING_REQUIRED_LINK + ParentLinkName.NETWORK_CONFIGURATIONS);
// Remove the gateway configuration and the current nics
Iterables.removeIf(
target.getLinks(),
@ -562,11 +563,40 @@ public class VirtualMachine extends DomainWithTasksWrapper<VirtualMachineWithNod
}
}
// Set the new network configuration
if (gatewayNetwork != null)
AsyncTask task = update(true);
if (gatewayNetwork == null)
{
target.addLink(new RESTLink(ParentLinkName.NETWORK_GATEWAY, configLink.getHref() + "/"
+ gatewayNetwork.getId()));
return task;
}
// If there is a gateway network, we have to wait until the network configuration links are
// available
if (task != null)
{
VirtualMachineState originalState = target.getState();
VirtualMachineMonitor monitor =
context.getUtils().getInjector().getInstance(MonitoringService.class)
.getVirtualMachineMonitor();
monitor.awaitState(originalState, this);
}
// Set the new network configuration
// Refresh virtual machine, to get the new configuration links
refresh();
VMNetworkConfigurationsDto configs =
context.getApi().getCloudApi().listNetworkConfigurations(target);
Iterables.removeIf(target.getLinks(), LinkPredicates.rel(ParentLinkName.NETWORK_GATEWAY));
for (VMNetworkConfigurationDto config : configs.getCollection())
{
if (config.getGateway().equalsIgnoreCase(gatewayNetwork.getGateway()))
{
target.addLink(new RESTLink(ParentLinkName.NETWORK_GATEWAY, config.getEditLink()
.getHref()));
break;
}
}
return update(true);

View File

@ -16,35 +16,38 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.abiquo.suppliers;
package org.jclouds.abiquo.domain.cloud;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import org.jclouds.abiquo.domain.enterprise.Enterprise;
import com.google.common.base.Supplier;
/**
* Gets the current enterprise.
* Wrapper to hold the information of a virtual machine template scoped to a concrete hypervisor
* type.
*
* @author Ignasi Barrera
*/
public class GetCurrentEnterprise implements Supplier<Enterprise>
public class VirtualMachineTemplateWithZone
{
private final GetCurrentUser currentUserSupplier;
private VirtualMachineTemplate template;
@Inject
public GetCurrentEnterprise(final GetCurrentUser currentUserSupplier)
private VirtualDatacenter zone;
public VirtualMachineTemplateWithZone(final VirtualMachineTemplate template,
final VirtualDatacenter zone)
{
this.currentUserSupplier = checkNotNull(currentUserSupplier, "currentUserSupplier");
super();
this.template = checkNotNull(template, "template");
this.zone = checkNotNull(zone, "zone");
}
@Override
public Enterprise get()
public VirtualMachineTemplate getTemplate()
{
return currentUserSupplier.get().getEnterprise();
return template;
}
public VirtualDatacenter getZone()
{
return zone;
}
}

View File

@ -25,11 +25,14 @@ import static com.google.common.collect.Iterables.transform;
import java.util.Arrays;
import java.util.List;
import org.jclouds.abiquo.domain.cloud.Conversion;
import org.jclouds.abiquo.domain.cloud.VirtualDatacenter;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import org.jclouds.abiquo.domain.infrastructure.Datacenter;
import org.jclouds.abiquo.reference.ValidationErrors;
import org.jclouds.abiquo.reference.rest.ParentLinkName;
import com.abiquo.model.enumerator.ConversionState;
import com.abiquo.model.enumerator.HypervisorType;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
@ -101,4 +104,33 @@ public class VirtualDatacenterPredicates
}
};
}
/**
* Check if the given template type is compatible with the given virtual datacenter type taking
* into account the conversions of the template.
*
* @param template The template to check.
* @return Predicate to check if the template or its conversions are compatibles with the given
* virtual datacenter.
*/
public static Predicate<VirtualDatacenter> compatibleWithTemplateOrConversions(
final VirtualMachineTemplate template)
{
return new Predicate<VirtualDatacenter>()
{
@Override
public boolean apply(final VirtualDatacenter vdc)
{
HypervisorType type = vdc.getHypervisorType();
boolean compatible = type.isCompatible(template.getDiskFormatType());
if (!compatible)
{
List<Conversion> compatibleConversions =
template.listConversions(type, ConversionState.FINISHED);
compatible = compatibleConversions != null && !compatibleConversions.isEmpty();
}
return compatible;
}
};
}
}

View File

@ -1,57 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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 org.jclouds.abiquo.suppliers;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.abiquo.domain.DomainWrapper.wrap;
import javax.inject.Inject;
import org.jclouds.abiquo.AbiquoAsyncApi;
import org.jclouds.abiquo.AbiquoApi;
import org.jclouds.abiquo.domain.enterprise.User;
import org.jclouds.rest.RestContext;
import com.abiquo.server.core.enterprise.UserDto;
import com.google.common.base.Supplier;
/**
* Gets the current user.
*
* @author Ignasi Barrera
*/
public class GetCurrentUser implements Supplier<User>
{
private RestContext<AbiquoApi, AbiquoAsyncApi> context;
@Inject
public GetCurrentUser(final RestContext<AbiquoApi, AbiquoAsyncApi> context)
{
this.context = checkNotNull(context, "context");
}
@Override
public User get()
{
UserDto user = context.getApi().getAdminApi().getCurrentUser();
return wrap(context, User.class, user);
}
}

View File

@ -49,6 +49,6 @@ public class DatacenterToLocationTest
Location location = function.apply(datacenter);
assertEquals(location.getId(), "5");
assertEquals(location.getScope(), LocationScope.ZONE);
assertEquals(location.getScope(), LocationScope.REGION);
}
}

View File

@ -0,0 +1,105 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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 org.jclouds.abiquo.compute.functions;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.util.Collections;
import java.util.Map;
import org.easymock.EasyMock;
import org.jclouds.abiquo.AbiquoApi;
import org.jclouds.abiquo.AbiquoAsyncApi;
import org.jclouds.abiquo.domain.cloud.VirtualDatacenter;
import org.jclouds.abiquo.domain.enterprise.Enterprise;
import org.jclouds.abiquo.domain.infrastructure.Datacenter;
import org.jclouds.abiquo.domain.network.PrivateNetwork;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.rest.RestContext;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
/**
* Unit tests for the {@link VirtualDatacenterToLocation} function.
*
* @author Ignasi Barrera
*/
@Test(groups = "unit", testName = "VirtualDatacenterToLocationTest")
public class VirtualDatacenterToLocationTest
{
public void testVirtualDatacenterToLocation()
{
Function<Datacenter, Location> dcToLocation = mockDatacenterToLocation();
Supplier<Map<Integer, Datacenter>> regionMap = mockRegionMap();
VirtualDatacenterToLocation function =
new VirtualDatacenterToLocation(dcToLocation, regionMap);
VirtualDatacenter vdc = mockVirtualDatacenter();
Location location = function.apply(vdc);
verify(regionMap);
verify(dcToLocation);
assertEquals(location.getId(), "5");
assertEquals(location.getScope(), LocationScope.ZONE);
}
@SuppressWarnings("unchecked")
private static VirtualDatacenter mockVirtualDatacenter()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
Datacenter datacenter = EasyMock.createMock(Datacenter.class);
Enterprise enterprise = EasyMock.createMock(Enterprise.class);
PrivateNetwork network = EasyMock.createMock(PrivateNetwork.class);
VirtualDatacenter vdc = VirtualDatacenter.builder(context, datacenter, enterprise) //
.network(network) //
.name("mock").build();
vdc.unwrap().setId(5);
return vdc;
}
@SuppressWarnings("unchecked")
private static Function<Datacenter, Location> mockDatacenterToLocation()
{
Function<Datacenter, Location> mock = EasyMock.createMock(Function.class);
expect(mock.apply(anyObject(Datacenter.class))).andReturn(null);
replay(mock);
return mock;
}
@SuppressWarnings("unchecked")
private static Supplier<Map<Integer, Datacenter>> mockRegionMap()
{
Supplier<Map<Integer, Datacenter>> mock = EasyMock.createMock(Supplier.class);
expect(mock.get()).andReturn(Collections.EMPTY_MAP);
replay(mock);
return mock;
}
}

View File

@ -44,7 +44,7 @@ public class VirtualMachineStateToNodeStateTest
assertEquals(function.apply(VirtualMachineState.ON), Status.RUNNING);
assertEquals(function.apply(VirtualMachineState.OFF), Status.SUSPENDED);
assertEquals(function.apply(VirtualMachineState.PAUSED), Status.SUSPENDED);
assertEquals(function.apply(VirtualMachineState.NOT_ALLOCATED), Status.TERMINATED);
assertEquals(function.apply(VirtualMachineState.NOT_ALLOCATED), Status.PENDING);
assertEquals(function.apply(VirtualMachineState.UNKNOWN), Status.UNRECOGNIZED);
}
}

View File

@ -1,173 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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 org.jclouds.abiquo.compute.functions;
import static org.jclouds.abiquo.domain.DomainWrapper.wrap;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import java.net.URI;
import org.easymock.EasyMock;
import org.jclouds.abiquo.AbiquoApi;
import org.jclouds.abiquo.AbiquoAsyncApi;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Volume;
import org.jclouds.rest.RestContext;
import org.testng.annotations.Test;
import com.abiquo.model.rest.RESTLink;
import com.abiquo.server.core.appslibrary.VirtualMachineTemplateDto;
/**
* Unit tests for the {@link VirtualMachineTemplateToHardware} function.
*
* @author Ignasi Barrera
*/
@Test(groups = "unit", testName = "VirtualMachineTemplateToHardwareTest")
public class VirtualMachineTemplateToHardwareTest
{
@SuppressWarnings("unchecked")
public void testVirtualMachineTemplateToHardware()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
VirtualMachineTemplateToHardware function = new VirtualMachineTemplateToHardware();
// VirtualMachineTemplate domain object does not have a builder, it is read only
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
dto.setId(5);
dto.setName("Template");
dto.setDescription("Template description");
dto.setHdRequired(50L * 1024 * 1024 * 1024); // 50 GB
dto.setCpuRequired(5);
dto.setRamRequired(2048);
dto.addLink(new RESTLink("edit", "http://foo/bar"));
Hardware hardware = function.apply(wrap(context, VirtualMachineTemplate.class, dto));
assertEquals(hardware.getId(), dto.getId().toString());
assertEquals(hardware.getName(), dto.getName());
assertEquals(hardware.getUri(), URI.create("http://foo/bar"));
assertEquals(hardware.getRam(), dto.getRamRequired());
assertEquals(hardware.getProcessors().size(), 1);
assertEquals(hardware.getProcessors().get(0).getCores(), (double) dto.getCpuRequired());
assertEquals(hardware.getProcessors().get(0).getSpeed(),
VirtualMachineTemplateToHardware.DEFAULT_CORE_SPEED);
assertEquals(hardware.getVolumes().size(), 1);
assertEquals(hardware.getVolumes().get(0).getSize(), 50F);
assertEquals(hardware.getVolumes().get(0).getType(), Volume.Type.LOCAL);
assertEquals(hardware.getVolumes().get(0).isBootDevice(), true);
assertEquals(hardware.getVolumes().get(0).isDurable(), false);
}
@SuppressWarnings("unchecked")
public void testConvertWithoutEditLink()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
VirtualMachineTemplateToHardware function = new VirtualMachineTemplateToHardware();
// VirtualMachineTemplate domain object does not have a builder, it is read only
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
dto.setId(5);
dto.setName("Template");
dto.setDescription("Template description");
dto.setHdRequired(50L * 1024 * 1024 * 1024); // 50 GB
dto.setCpuRequired(5);
dto.setRamRequired(2048);
Hardware hardware = function.apply(wrap(context, VirtualMachineTemplate.class, dto));
assertNull(hardware.getUri());
}
@SuppressWarnings("unchecked")
@Test(expectedExceptions = NullPointerException.class)
public void testConvertWithoutId()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
VirtualMachineTemplateToHardware function = new VirtualMachineTemplateToHardware();
// VirtualMachineTemplate domain object does not have a builder, it is read only
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
function.apply(wrap(context, VirtualMachineTemplate.class, dto));
}
@SuppressWarnings("unchecked")
public void testConvertWithoutCpu()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
VirtualMachineTemplateToHardware function = new VirtualMachineTemplateToHardware();
// VirtualMachineTemplate domain object does not have a builder, it is read only
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
dto.setId(5);
dto.setName("Template");
dto.setDescription("Template description");
dto.setHdRequired(50L * 1024 * 1024 * 1024); // 50 GB
dto.setRamRequired(2048);
Hardware hardware = function.apply(wrap(context, VirtualMachineTemplate.class, dto));
assertEquals(hardware.getProcessors().size(), 1);
assertEquals(hardware.getProcessors().get(0).getCores(), 0D);
}
@SuppressWarnings("unchecked")
public void testConvertWithoutRam()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
VirtualMachineTemplateToHardware function = new VirtualMachineTemplateToHardware();
// VirtualMachineTemplate domain object does not have a builder, it is read only
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
dto.setId(5);
dto.setName("Template");
dto.setDescription("Template description");
dto.setHdRequired(50L * 1024 * 1024 * 1024); // 50 GB
dto.setCpuRequired(5);
Hardware hardware = function.apply(wrap(context, VirtualMachineTemplate.class, dto));
assertEquals(hardware.getRam(), 0);
}
@SuppressWarnings("unchecked")
public void testConvertWithoutHd()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
VirtualMachineTemplateToHardware function = new VirtualMachineTemplateToHardware();
// VirtualMachineTemplate domain object does not have a builder, it is read only
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
dto.setId(5);
dto.setName("Template");
dto.setDescription("Template description");
dto.setCpuRequired(5);
dto.setRamRequired(2048);
Hardware hardware = function.apply(wrap(context, VirtualMachineTemplate.class, dto));
assertEquals(hardware.getVolumes().size(), 1);
assertEquals(hardware.getVolumes().get(0).getSize(), 0F);
}
}

View File

@ -19,23 +19,33 @@
package org.jclouds.abiquo.compute.functions;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.jclouds.abiquo.domain.DomainWrapper.wrap;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import java.net.URI;
import java.util.Collections;
import java.util.Map;
import org.easymock.EasyMock;
import org.jclouds.abiquo.AbiquoApi;
import org.jclouds.abiquo.AbiquoAsyncApi;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import org.jclouds.abiquo.domain.infrastructure.Datacenter;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.domain.Location;
import org.jclouds.rest.RestContext;
import org.testng.annotations.Test;
import com.abiquo.model.rest.RESTLink;
import com.abiquo.server.core.appslibrary.VirtualMachineTemplateDto;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
/**
* Unit tests for the {@link VirtualMachineTemplateToImage} class.
@ -49,17 +59,23 @@ public class VirtualMachineTemplateToImageTest
public void testVirtualMachineTemplateToImage()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
VirtualMachineTemplateToImage function = new VirtualMachineTemplateToImage();
Function<Datacenter, Location> dcToLocation = mockDatacenterToLocation();
Supplier<Map<Integer, Datacenter>> regionMap = mockRegionMap();
VirtualMachineTemplateToImage function =
new VirtualMachineTemplateToImage(dcToLocation, regionMap);
// VirtualMachineTemplate domain object does not have a builder, it is read only
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
dto.setId(5);
dto.setName("Template");
dto.setDescription("Template description");
dto.addLink(new RESTLink("diskfile", "http://foo/bar"));
dto.addLink(new RESTLink("datacenter", "http://foo/bar/4"));
Image image = function.apply(wrap(context, VirtualMachineTemplate.class, dto));
verify(regionMap);
verify(dcToLocation);
assertEquals(image.getId(), dto.getId().toString());
assertEquals(image.getName(), dto.getName());
assertEquals(image.getDescription(), dto.getDescription());
@ -72,16 +88,22 @@ public class VirtualMachineTemplateToImageTest
public void testConvertWithoutDownloadLink()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
VirtualMachineTemplateToImage function = new VirtualMachineTemplateToImage();
Function<Datacenter, Location> dcToLocation = mockDatacenterToLocation();
Supplier<Map<Integer, Datacenter>> regionMap = mockRegionMap();
VirtualMachineTemplateToImage function =
new VirtualMachineTemplateToImage(dcToLocation, regionMap);
// VirtualMachineTemplate domain object does not have a builder, it is read only
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
dto.setId(5);
dto.setName("Template");
dto.setDescription("Template description");
dto.addLink(new RESTLink("datacenter", "http://foo/bar/4"));
Image image = function.apply(wrap(context, VirtualMachineTemplate.class, dto));
verify(regionMap);
verify(dcToLocation);
assertNull(image.getUri());
}
@ -90,10 +112,30 @@ public class VirtualMachineTemplateToImageTest
public void testConvertWithoutId()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
VirtualMachineTemplateToImage function = new VirtualMachineTemplateToImage();
Function<Datacenter, Location> dcToLocation = mockDatacenterToLocation();
Supplier<Map<Integer, Datacenter>> regionMap = mockRegionMap();
VirtualMachineTemplateToImage function =
new VirtualMachineTemplateToImage(dcToLocation, regionMap);
// VirtualMachineTemplate domain object does not have a builder, it is read only
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
function.apply(wrap(context, VirtualMachineTemplate.class, dto));
}
@SuppressWarnings("unchecked")
private static Function<Datacenter, Location> mockDatacenterToLocation()
{
Function<Datacenter, Location> mock = EasyMock.createMock(Function.class);
expect(mock.apply(anyObject(Datacenter.class))).andReturn(null);
replay(mock);
return mock;
}
@SuppressWarnings("unchecked")
private static Supplier<Map<Integer, Datacenter>> mockRegionMap()
{
Supplier<Map<Integer, Datacenter>> mock = EasyMock.createMock(Supplier.class);
expect(mock.get()).andReturn(Collections.EMPTY_MAP);
replay(mock);
return mock;
}
}

View File

@ -0,0 +1,243 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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 org.jclouds.abiquo.compute.functions;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.jclouds.abiquo.domain.DomainWrapper.wrap;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import java.net.URI;
import org.easymock.EasyMock;
import org.jclouds.abiquo.AbiquoApi;
import org.jclouds.abiquo.AbiquoAsyncApi;
import org.jclouds.abiquo.domain.cloud.VirtualDatacenter;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplateWithZone;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Volume;
import org.jclouds.domain.Location;
import org.jclouds.rest.RestContext;
import org.testng.annotations.Test;
import com.abiquo.model.enumerator.HypervisorType;
import com.abiquo.model.rest.RESTLink;
import com.abiquo.server.core.appslibrary.VirtualMachineTemplateDto;
import com.abiquo.server.core.cloud.VirtualDatacenterDto;
import com.google.common.base.Function;
/**
* Unit tests for the {@link VirtualMachineTemplateWithZoneToHardware} function.
*
* @author Ignasi Barrera
*/
@Test(groups = "unit", testName = "VirtualMachineTemplateToHardwareTest")
public class VirtualMachineTemplateWithZoneToHardwareTest
{
@SuppressWarnings("unchecked")
public void testVirtualMachineTemplateToHardware()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
Function<VirtualDatacenter, Location> vdcToLocation = mockVirtualDatacenterToLocation();
VirtualMachineTemplateWithZoneToHardware function =
new VirtualMachineTemplateWithZoneToHardware(vdcToLocation);
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
dto.setId(5);
dto.setName("Template");
dto.setDescription("Template description");
dto.setHdRequired(50L * 1024 * 1024 * 1024); // 50 GB
dto.setCpuRequired(5);
dto.setRamRequired(2048);
dto.addLink(new RESTLink("edit", "http://foo/bar"));
VirtualMachineTemplate template = wrap(context, VirtualMachineTemplate.class, dto);
VirtualDatacenterDto vdcDto = new VirtualDatacenterDto();
vdcDto.setId(6);
vdcDto.setHypervisorType(HypervisorType.VMX_04);
VirtualDatacenter vdc = wrap(context, VirtualDatacenter.class, vdcDto);
Hardware hardware = function.apply(new VirtualMachineTemplateWithZone(template, vdc));
verify(vdcToLocation);
assertEquals(hardware.getProviderId(), template.getId().toString());
assertEquals(hardware.getId(), template.getId() + "-" + vdc.getId());
assertEquals(hardware.getName(), template.getName());
assertEquals(hardware.getUri(), URI.create("http://foo/bar"));
assertEquals(hardware.getRam(), template.getRamRequired());
assertEquals(hardware.getProcessors().size(), 1);
assertEquals(hardware.getProcessors().get(0).getCores(), (double) template.getCpuRequired());
assertEquals(hardware.getProcessors().get(0).getSpeed(),
VirtualMachineTemplateWithZoneToHardware.DEFAULT_CORE_SPEED);
assertEquals(hardware.getVolumes().size(), 1);
assertEquals(hardware.getVolumes().get(0).getSize(), 50F);
assertEquals(hardware.getVolumes().get(0).getType(), Volume.Type.LOCAL);
assertEquals(hardware.getVolumes().get(0).isBootDevice(), true);
assertEquals(hardware.getVolumes().get(0).isDurable(), false);
}
@SuppressWarnings("unchecked")
public void testConvertWithoutEditLink()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
Function<VirtualDatacenter, Location> vdcToLocation = mockVirtualDatacenterToLocation();
VirtualMachineTemplateWithZoneToHardware function =
new VirtualMachineTemplateWithZoneToHardware(vdcToLocation);
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
dto.setId(5);
dto.setName("Template");
dto.setDescription("Template description");
dto.setHdRequired(50L * 1024 * 1024 * 1024); // 50 GB
dto.setCpuRequired(5);
dto.setRamRequired(2048);
VirtualMachineTemplate template = wrap(context, VirtualMachineTemplate.class, dto);
VirtualDatacenterDto vdcDto = new VirtualDatacenterDto();
vdcDto.setId(6);
vdcDto.setHypervisorType(HypervisorType.VMX_04);
VirtualDatacenter vdc = wrap(context, VirtualDatacenter.class, vdcDto);
Hardware hardware = function.apply(new VirtualMachineTemplateWithZone(template, vdc));
verify(vdcToLocation);
assertNull(hardware.getUri());
}
@SuppressWarnings("unchecked")
@Test(expectedExceptions = NullPointerException.class)
public void testConvertWithoutId()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
Function<VirtualDatacenter, Location> vdcToLocation = mockVirtualDatacenterToLocation();
VirtualMachineTemplateWithZoneToHardware function =
new VirtualMachineTemplateWithZoneToHardware(vdcToLocation);
VirtualMachineTemplate template =
wrap(context, VirtualMachineTemplate.class, new VirtualMachineTemplateDto());
VirtualDatacenter vdc = wrap(context, VirtualDatacenter.class, new VirtualDatacenterDto());
function.apply(new VirtualMachineTemplateWithZone(template, vdc));
}
@SuppressWarnings("unchecked")
public void testConvertWithoutCpu()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
Function<VirtualDatacenter, Location> vdcToLocation = mockVirtualDatacenterToLocation();
VirtualMachineTemplateWithZoneToHardware function =
new VirtualMachineTemplateWithZoneToHardware(vdcToLocation);
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
dto.setId(5);
dto.setName("Template");
dto.setDescription("Template description");
dto.setHdRequired(50L * 1024 * 1024 * 1024); // 50 GB
dto.setRamRequired(2048);
VirtualMachineTemplate template = wrap(context, VirtualMachineTemplate.class, dto);
VirtualDatacenterDto vdcDto = new VirtualDatacenterDto();
vdcDto.setId(6);
vdcDto.setHypervisorType(HypervisorType.VMX_04);
VirtualDatacenter vdc = wrap(context, VirtualDatacenter.class, vdcDto);
Hardware hardware = function.apply(new VirtualMachineTemplateWithZone(template, vdc));
verify(vdcToLocation);
assertEquals(hardware.getProcessors().size(), 1);
assertEquals(hardware.getProcessors().get(0).getCores(), 0D);
}
@SuppressWarnings("unchecked")
public void testConvertWithoutRam()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
Function<VirtualDatacenter, Location> vdcToLocation = mockVirtualDatacenterToLocation();
VirtualMachineTemplateWithZoneToHardware function =
new VirtualMachineTemplateWithZoneToHardware(vdcToLocation);
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
dto.setId(5);
dto.setName("Template");
dto.setDescription("Template description");
dto.setHdRequired(50L * 1024 * 1024 * 1024); // 50 GB
dto.setCpuRequired(5);
VirtualMachineTemplate template = wrap(context, VirtualMachineTemplate.class, dto);
VirtualDatacenterDto vdcDto = new VirtualDatacenterDto();
vdcDto.setId(6);
vdcDto.setHypervisorType(HypervisorType.VMX_04);
VirtualDatacenter vdc = wrap(context, VirtualDatacenter.class, vdcDto);
Hardware hardware = function.apply(new VirtualMachineTemplateWithZone(template, vdc));
verify(vdcToLocation);
assertEquals(hardware.getRam(), 0);
}
@SuppressWarnings("unchecked")
public void testConvertWithoutHd()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
Function<VirtualDatacenter, Location> vdcToLocation = mockVirtualDatacenterToLocation();
VirtualMachineTemplateWithZoneToHardware function =
new VirtualMachineTemplateWithZoneToHardware(vdcToLocation);
// VirtualMachineTemplate domain object does not have a builder, it is read only
VirtualMachineTemplateDto dto = new VirtualMachineTemplateDto();
dto.setId(5);
dto.setName("Template");
dto.setDescription("Template description");
dto.setCpuRequired(5);
dto.setRamRequired(2048);
VirtualMachineTemplate template = wrap(context, VirtualMachineTemplate.class, dto);
VirtualDatacenterDto vdcDto = new VirtualDatacenterDto();
vdcDto.setId(6);
vdcDto.setHypervisorType(HypervisorType.VMX_04);
VirtualDatacenter vdc = wrap(context, VirtualDatacenter.class, vdcDto);
Hardware hardware = function.apply(new VirtualMachineTemplateWithZone(template, vdc));
verify(vdcToLocation);
assertEquals(hardware.getVolumes().size(), 1);
assertEquals(hardware.getVolumes().get(0).getSize(), 0F);
}
@SuppressWarnings("unchecked")
private static Function<VirtualDatacenter, Location> mockVirtualDatacenterToLocation()
{
Function<VirtualDatacenter, Location> mock = EasyMock.createMock(Function.class);
expect(mock.apply(anyObject(VirtualDatacenter.class))).andReturn(null);
replay(mock);
return mock;
}
}

View File

@ -33,7 +33,7 @@ import org.jclouds.abiquo.domain.cloud.VirtualAppliance;
import org.jclouds.abiquo.domain.cloud.VirtualDatacenter;
import org.jclouds.abiquo.domain.cloud.VirtualMachine;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplate;
import org.jclouds.abiquo.domain.infrastructure.Datacenter;
import org.jclouds.abiquo.domain.cloud.VirtualMachineTemplateWithZone;
import org.jclouds.abiquo.domain.network.ExternalIp;
import org.jclouds.abiquo.domain.network.Ip;
import org.jclouds.abiquo.domain.network.PrivateIp;
@ -111,7 +111,7 @@ public class VirtualMachineToNodeMetadataTest
new VirtualMachineToNodeMetadata(templateToImage(),
templateToHardware(),
stateToNodeState(),
datacenterToLocation());
virtualDatacenterToLocation());
}
public void testVirtualMachineToNodeMetadata()
@ -131,8 +131,6 @@ public class VirtualMachineToNodeMetadataTest
assertEquals(node.getLocation().getDescription(), "Mock Location");
assertEquals(node.getImageId(), "1");
assertEquals(node.getHardware().getId(), "1");
assertEquals(node.getHardware().getHypervisor(), HypervisorType.VMX_04.name());
assertEquals(node.getHardware().getId(), "1");
assertEquals(node.getHardware().getRam(), vm.getRam());
assertEquals(node.getHardware().getProcessors().get(0).getCores(), (double) vm.getCpu());
assertEquals(node.getLoginPort(), vm.getVdrpPort());
@ -159,12 +157,13 @@ public class VirtualMachineToNodeMetadataTest
return templateToImage;
}
private VirtualMachineTemplateToHardware templateToHardware()
private VirtualMachineTemplateWithZoneToHardware templateToHardware()
{
VirtualMachineTemplateToHardware virtualMachineTemplateToHardware =
EasyMock.createMock(VirtualMachineTemplateToHardware.class);
VirtualMachineTemplateWithZoneToHardware virtualMachineTemplateToHardware =
EasyMock.createMock(VirtualMachineTemplateWithZoneToHardware.class);
expect(virtualMachineTemplateToHardware.apply(anyObject(VirtualMachineTemplate.class)))
expect(
virtualMachineTemplateToHardware.apply(anyObject(VirtualMachineTemplateWithZone.class)))
.andReturn(hardware);
replay(virtualMachineTemplateToHardware);
@ -172,15 +171,16 @@ public class VirtualMachineToNodeMetadataTest
return virtualMachineTemplateToHardware;
}
private DatacenterToLocation datacenterToLocation()
private VirtualDatacenterToLocation virtualDatacenterToLocation()
{
DatacenterToLocation datacenterToLocation = EasyMock.createMock(DatacenterToLocation.class);
VirtualDatacenterToLocation datacenterToLocation =
EasyMock.createMock(VirtualDatacenterToLocation.class);
Location location = EasyMock.createMock(Location.class);
expect(location.getId()).andReturn("1");
expect(location.getDescription()).andReturn("Mock Location");
expect(datacenterToLocation.apply(anyObject(Datacenter.class))).andReturn(location);
expect(datacenterToLocation.apply(anyObject(VirtualDatacenter.class))).andReturn(location);
replay(location);
replay(datacenterToLocation);

View File

@ -19,25 +19,11 @@
package org.jclouds.abiquo.compute.options;
import static org.jclouds.abiquo.domain.DomainWrapper.wrap;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.easymock.EasyMock;
import org.jclouds.abiquo.AbiquoApi;
import org.jclouds.abiquo.AbiquoAsyncApi;
import org.jclouds.abiquo.domain.network.Ip;
import org.jclouds.abiquo.domain.network.PrivateIp;
import org.jclouds.abiquo.domain.network.PrivateNetwork;
import org.jclouds.abiquo.domain.network.UnmanagedNetwork;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.rest.RestContext;
import org.testng.annotations.Test;
import com.abiquo.model.enumerator.NetworkType;
import com.abiquo.server.core.infrastructure.network.PrivateIpDto;
import com.abiquo.server.core.infrastructure.network.VLANNetworkDto;
/**
* Unit tests for the {@link AbiquoTemplateOptions} class.
*
@ -71,75 +57,4 @@ public class AbiquoTemplateOptionsTest
assertEquals(options.as(AbiquoTemplateOptions.class).getVncPassword(), "foo");
}
public void testVirtualDatacenter()
{
TemplateOptions options = new AbiquoTemplateOptions().virtualDatacenter("foo");
assertEquals(options.as(AbiquoTemplateOptions.class).getVirtualDatacenter(), "foo");
}
@SuppressWarnings("unchecked")
public void testIps()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
PrivateIpDto dto1 = new PrivateIpDto();
dto1.setIp("10.60.0.1");
PrivateIpDto dto2 = new PrivateIpDto();
dto2.setIp("10.60.0.2");
PrivateIp ip1 = wrap(context, PrivateIp.class, dto1);
PrivateIp ip2 = wrap(context, PrivateIp.class, dto2);
TemplateOptions options = new AbiquoTemplateOptions().ips(ip1, ip2);
Ip< ? , ? >[] ips = options.as(AbiquoTemplateOptions.class).getIps();
assertNotNull(ips);
assertEquals(ips[0].getIp(), "10.60.0.1");
assertEquals(ips[1].getIp(), "10.60.0.2");
}
@SuppressWarnings("unchecked")
public void testGatewayNetwork()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
VLANNetworkDto dto = new VLANNetworkDto();
dto.setAddress("10.0.0.0");
dto.setMask(24);
dto.setGateway("10.0.0.1");
dto.setType(NetworkType.INTERNAL);
PrivateNetwork gateway = wrap(context, PrivateNetwork.class, dto);
TemplateOptions options = new AbiquoTemplateOptions().gatewayNetwork(gateway);
assertEquals(options.as(AbiquoTemplateOptions.class).getGatewayNetwork(), gateway);
}
@SuppressWarnings("unchecked")
public void testUnmanagedIps()
{
RestContext<AbiquoApi, AbiquoAsyncApi> context = EasyMock.createMock(RestContext.class);
VLANNetworkDto dto1 = new VLANNetworkDto();
dto1.setAddress("10.0.0.0");
dto1.setMask(24);
dto1.setGateway("10.0.0.1");
dto1.setType(NetworkType.UNMANAGED);
VLANNetworkDto dto2 = new VLANNetworkDto();
dto2.setAddress("10.1.0.0");
dto2.setMask(24);
dto2.setGateway("10.1.0.1");
dto2.setType(NetworkType.UNMANAGED);
UnmanagedNetwork net1 = wrap(context, UnmanagedNetwork.class, dto1);
UnmanagedNetwork net2 = wrap(context, UnmanagedNetwork.class, dto2);
TemplateOptions options = new AbiquoTemplateOptions().unmanagedIps(net1, net2);
UnmanagedNetwork[] nets = options.as(AbiquoTemplateOptions.class).getUnmanagedIps();
assertNotNull(nets);
assertEquals(nets[0].getAddress(), "10.0.0.0");
assertEquals(nets[1].getAddress(), "10.1.0.0");
}
}