http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/functions/ServerInfoToNodeMetadata.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/functions/ServerInfoToNodeMetadata.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/functions/ServerInfoToNodeMetadata.java new file mode 100644 index 0000000..2cfc1b0 --- /dev/null +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/functions/ServerInfoToNodeMetadata.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cloudsigma2.compute.functions; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; +import org.jclouds.cloudsigma2.CloudSigma2Api; +import org.jclouds.cloudsigma2.domain.ServerDrive; +import org.jclouds.cloudsigma2.domain.ServerInfo; +import org.jclouds.cloudsigma2.domain.ServerStatus; +import org.jclouds.cloudsigma2.domain.Tag; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.functions.GroupNamingConvention; +import org.jclouds.domain.Credentials; +import org.jclouds.domain.LoginCredentials; +import org.jclouds.location.suppliers.all.JustProvider; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.notNull; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.getOnlyElement; +import static com.google.common.collect.Iterables.transform; + +@Singleton +public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetadata> { + + private final ServerDriveToVolume serverDriveToVolume; + private final NICToAddress nicToAddress; + private final Map<ServerStatus, NodeMetadata.Status> serverStatusToNodeStatus; + private final GroupNamingConvention groupNamingConventionWithPrefix; + private final GroupNamingConvention groupNamingConventionWithoutPrefix; + private final Map<String, Credentials> credentialStore; + private final JustProvider locations; + private final CloudSigma2Api api; + + @Inject + public ServerInfoToNodeMetadata(ServerDriveToVolume serverDriveToVolume, NICToAddress nicToAddress, + Map<ServerStatus, NodeMetadata.Status> serverStatusToNodeStatus, + GroupNamingConvention.Factory groupNamingConvention, + Map<String, Credentials> credentialStore, + JustProvider locations, CloudSigma2Api api) { + this.serverDriveToVolume = checkNotNull(serverDriveToVolume, "serverDriveToVolume"); + this.nicToAddress = checkNotNull(nicToAddress, "nicToAddress"); + this.serverStatusToNodeStatus = checkNotNull(serverStatusToNodeStatus, "serverStatusToNodeStatus"); + this.groupNamingConventionWithPrefix = checkNotNull(groupNamingConvention, "groupNamingConvention").create(); + this.groupNamingConventionWithoutPrefix = groupNamingConvention.createWithoutPrefix(); + this.credentialStore = checkNotNull(credentialStore, "credentialStore"); + this.locations = checkNotNull(locations, "locations"); + this.api = checkNotNull(api, "api"); + } + + @Override + public NodeMetadata apply(ServerInfo serverInfo) { + NodeMetadataBuilder builder = new NodeMetadataBuilder(); + + builder.ids(serverInfo.getUuid()); + builder.name(serverInfo.getName()); + builder.group(groupNamingConventionWithoutPrefix.extractGroup(serverInfo.getName())); + builder.location(getOnlyElement(locations.get())); + + builder.hardware(new HardwareBuilder().ids(serverInfo.getUuid()).processor(new Processor(1, serverInfo.getCpu())) + .ram(serverInfo.getMemory().intValue()) + .volumes(Iterables.transform(serverInfo.getDrives(), serverDriveToVolume)).build()); + + builder.tags(readTags(serverInfo)); + builder.userMetadata(serverInfo.getMeta()); + builder.imageId(extractImageId(serverInfo)); + builder.status(serverStatusToNodeStatus.get(serverInfo.getStatus())); + builder.publicAddresses(filter(transform(serverInfo.getNics(), nicToAddress), notNull())); + + // CloudSigma does not provide a way to get the credentials. + // Try to return them from the credential store + Credentials credentials = credentialStore.get("node#" + serverInfo.getUuid()); + if (credentials instanceof LoginCredentials) { + builder.credentials(LoginCredentials.class.cast(credentials)); + } + + return builder.build(); + } + + private static String extractImageId(ServerInfo serverInfo) { + String imageId = serverInfo.getMeta().get("image_id"); + + if (imageId == null) { + ServerDrive serverBootDrive = null; + for (ServerDrive serverDrive : serverInfo.getDrives()) { + if (serverDrive.getBootOrder() != null + && (serverBootDrive == null || serverDrive.getBootOrder() < serverBootDrive.getBootOrder())) { + serverBootDrive = serverDrive; + } + } + if (serverBootDrive != null) { + imageId = serverBootDrive.getDriveUuid(); + } + } + + return imageId; + } + + private Iterable<String> readTags(ServerInfo serverInfo) { + return transform(serverInfo.getTags(), new Function<Tag, String>() { + @Override + public String apply(Tag input) { + Tag tag = api.getTagInfo(input.getUuid()); + if (tag.getName() == null) { + return input.getUuid(); + } + String tagWithoutPrefix = groupNamingConventionWithPrefix.groupInSharedNameOrNull(tag.getName()); + return tagWithoutPrefix != null ? tagWithoutPrefix : tag.getName(); + } + }); + } + +}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/functions/TemplateOptionsToStatementWithoutPublicKey.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/functions/TemplateOptionsToStatementWithoutPublicKey.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/functions/TemplateOptionsToStatementWithoutPublicKey.java new file mode 100644 index 0000000..077917b --- /dev/null +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/functions/TemplateOptionsToStatementWithoutPublicKey.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cloudsigma2.compute.functions; + +import com.google.common.collect.ImmutableList; +import org.jclouds.compute.functions.TemplateOptionsToStatement; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.scriptbuilder.InitScript; +import org.jclouds.scriptbuilder.domain.Statement; +import org.jclouds.scriptbuilder.domain.StatementList; +import org.jclouds.scriptbuilder.statements.ssh.InstallRSAPrivateKey; + +import javax.inject.Singleton; + +/** + * Convert the template options into a statement, but ignoring the public key. + * <p/> + * The {@link org.jclouds.cloudsigma2.compute.strategy.CloudSigma2ComputeServiceAdapter} already takes care of + * installing it using the server metadata. + */ +@Singleton +public class TemplateOptionsToStatementWithoutPublicKey extends TemplateOptionsToStatement { + + @Override + public Statement apply(TemplateOptions options) { + ImmutableList.Builder<Statement> builder = ImmutableList.builder(); + if (options.getRunScript() != null) { + builder.add(options.getRunScript()); + } + if (options.getPrivateKey() != null) { + builder.add(new InstallRSAPrivateKey(options.getPrivateKey())); + } + + ImmutableList<Statement> bootstrap = builder.build(); + if (bootstrap.isEmpty()) { + return null; + } + + if (options.getTaskName() == null && !(options.getRunScript() instanceof InitScript)) { + options.nameTask("bootstrap"); + } + return bootstrap.size() == 1 ? bootstrap.get(0) : new StatementList(bootstrap); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/options/CloudSigma2TemplateOptions.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/options/CloudSigma2TemplateOptions.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/options/CloudSigma2TemplateOptions.java new file mode 100644 index 0000000..db43a7d --- /dev/null +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/options/CloudSigma2TemplateOptions.java @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cloudsigma2.compute.options; + +import com.google.common.base.Objects.ToStringHelper; +import org.jclouds.cloudsigma2.domain.DeviceEmulationType; +import org.jclouds.cloudsigma2.domain.Model; +import org.jclouds.compute.options.TemplateOptions; + +public class CloudSigma2TemplateOptions extends TemplateOptions { + + private DeviceEmulationType deviceEmulationType = DeviceEmulationType.VIRTIO; + private Model nicModel = Model.VIRTIO; + private String vncPassword; + + /** + * Configures the device emulation type. + */ + public CloudSigma2TemplateOptions deviceEmulationType(DeviceEmulationType deviceEmulationType) { + this.deviceEmulationType = deviceEmulationType; + return this; + } + + /** + * Configures the type of NICs to create. + */ + public CloudSigma2TemplateOptions nicModel(Model nicModel) { + this.nicModel = nicModel; + return this; + } + + /** + * Configures the vnc password. + */ + public CloudSigma2TemplateOptions vncPassword(String vncPassword) { + this.vncPassword = vncPassword; + return this; + } + + public DeviceEmulationType getDeviceEmulationType() { + return deviceEmulationType; + } + + public Model getNicModel() { + return nicModel; + } + + public String getVncPassword() { + return vncPassword; + } + + @Override + public TemplateOptions clone() { + CloudSigma2TemplateOptions options = new CloudSigma2TemplateOptions(); + copyTo(options); + return options; + } + + @Override + public void copyTo(TemplateOptions to) { + super.copyTo(to); + if (to instanceof CloudSigma2TemplateOptions) { + CloudSigma2TemplateOptions eTo = CloudSigma2TemplateOptions.class.cast(to); + eTo.deviceEmulationType(deviceEmulationType); + eTo.nicModel(nicModel); + eTo.vncPassword(vncPassword); + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((deviceEmulationType == null) ? 0 : deviceEmulationType.hashCode()); + result = prime * result + ((nicModel == null) ? 0 : nicModel.hashCode()); + result = prime * result + ((vncPassword == null) ? 0 : vncPassword.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + CloudSigma2TemplateOptions other = (CloudSigma2TemplateOptions) obj; + if (deviceEmulationType != other.deviceEmulationType) + return false; + if (nicModel != other.nicModel) + return false; + if (vncPassword == null) { + if (other.vncPassword != null) + return false; + } else if (!vncPassword.equals(other.vncPassword)) + return false; + return true; + } + + @Override + public ToStringHelper string() { + ToStringHelper toString = super.string().omitNullValues(); + toString.add("deviceEmulationType", deviceEmulationType); + toString.add("nicModel", nicModel); + toString.add("vncPassword", vncPassword); + return toString; + } + + public static class Builder { + + /** + * @see CloudSigma2TemplateOptions#deviceEmulationType(DeviceEmulationType) + */ + public CloudSigma2TemplateOptions deviceEmulationType(DeviceEmulationType deviceEmulationType) { + CloudSigma2TemplateOptions options = new CloudSigma2TemplateOptions(); + options.deviceEmulationType(deviceEmulationType); + return options; + } + + /** + * @see CloudSigma2TemplateOptions#nicModel(Model) + */ + public CloudSigma2TemplateOptions nicModel(Model nicModel) { + CloudSigma2TemplateOptions options = new CloudSigma2TemplateOptions(); + options.nicModel(nicModel); + return options; + } + + /** + * @see CloudSigma2TemplateOptions#vncPassword(String) + */ + public CloudSigma2TemplateOptions vncPassword(String vncPassword) { + CloudSigma2TemplateOptions options = new CloudSigma2TemplateOptions(); + options.vncPassword(vncPassword); + return options; + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/strategy/CloudSigma2ComputeServiceAdapter.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/strategy/CloudSigma2ComputeServiceAdapter.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/strategy/CloudSigma2ComputeServiceAdapter.java new file mode 100644 index 0000000..69decb2 --- /dev/null +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/compute/strategy/CloudSigma2ComputeServiceAdapter.java @@ -0,0 +1,407 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cloudsigma2.compute.strategy; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; +import com.google.common.collect.Maps; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.inject.Inject; + +import org.jclouds.Constants; +import org.jclouds.cloudsigma2.CloudSigma2Api; +import org.jclouds.cloudsigma2.compute.options.CloudSigma2TemplateOptions; +import org.jclouds.cloudsigma2.domain.DriveInfo; +import org.jclouds.cloudsigma2.domain.DriveStatus; +import org.jclouds.cloudsigma2.domain.FirewallAction; +import org.jclouds.cloudsigma2.domain.FirewallDirection; +import org.jclouds.cloudsigma2.domain.FirewallIpProtocol; +import org.jclouds.cloudsigma2.domain.FirewallPolicy; +import org.jclouds.cloudsigma2.domain.FirewallRule; +import org.jclouds.cloudsigma2.domain.IPConfiguration; +import org.jclouds.cloudsigma2.domain.IPConfigurationType; +import org.jclouds.cloudsigma2.domain.LibraryDrive; +import org.jclouds.cloudsigma2.domain.MediaType; +import org.jclouds.cloudsigma2.domain.NIC; +import org.jclouds.cloudsigma2.domain.ServerDrive; +import org.jclouds.cloudsigma2.domain.ServerInfo; +import org.jclouds.cloudsigma2.domain.ServerStatus; +import org.jclouds.cloudsigma2.domain.Tag; +import org.jclouds.cloudsigma2.domain.VLANInfo; +import org.jclouds.compute.ComputeServiceAdapter; +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.Template; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.internal.VolumeImpl; +import org.jclouds.compute.functions.GroupNamingConvention; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.domain.Location; +import org.jclouds.domain.LoginCredentials; +import org.jclouds.logging.Logger; + +import javax.annotation.Resource; +import javax.inject.Named; +import javax.inject.Singleton; + +import java.math.BigInteger; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Throwables.propagate; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.Lists.transform; +import static com.google.common.util.concurrent.Futures.allAsList; +import static com.google.common.util.concurrent.Futures.getUnchecked; +import static org.jclouds.cloudsigma2.config.CloudSigma2Properties.PROPERTY_DELETE_DRIVES; +import static org.jclouds.cloudsigma2.config.CloudSigma2Properties.PROPERTY_VNC_PASSWORD; +import static org.jclouds.cloudsigma2.config.CloudSigma2Properties.TIMEOUT_DRIVE_CLONED; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; + +@Singleton +public class CloudSigma2ComputeServiceAdapter implements + ComputeServiceAdapter<ServerInfo, Hardware, LibraryDrive, Location> { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final CloudSigma2Api api; + private final ListeningExecutorService userExecutor; + private final String defaultVncPassword; + private final Predicate<DriveInfo> driveCloned; + private final Predicate<String> serverStopped; + private final boolean destroyDrives; + private final GroupNamingConvention groupNamingConvention; + + @Inject + public CloudSigma2ComputeServiceAdapter(CloudSigma2Api api, + @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService + userExecutor, + @Named(PROPERTY_VNC_PASSWORD) String defaultVncPassword, + @Named(TIMEOUT_DRIVE_CLONED) Predicate<DriveInfo> driveCloned, + @Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> serverStopped, + @Named(PROPERTY_DELETE_DRIVES) boolean destroyDrives, + GroupNamingConvention.Factory groupNamingConvention) { + this.api = checkNotNull(api, "api"); + this.userExecutor = checkNotNull(userExecutor, "userExecutor"); + this.defaultVncPassword = checkNotNull(defaultVncPassword, "defaultVncPassword"); + this.driveCloned = checkNotNull(driveCloned, "driveCloned"); + this.serverStopped = checkNotNull(serverStopped, "serverStopped"); + this.destroyDrives = destroyDrives; + this.groupNamingConvention = checkNotNull(groupNamingConvention, "groupNamingConvention").create(); + } + + @Override + public NodeAndInitialCredentials<ServerInfo> createNodeWithGroupEncodedIntoName(String group, String name, + Template template) { + CloudSigma2TemplateOptions options = template.getOptions().as(CloudSigma2TemplateOptions.class); + Image image = template.getImage(); + Hardware hardware = template.getHardware(); + + DriveInfo drive = api.getLibraryDrive(image.getProviderId()); + + if (!drive.getMedia().equals(MediaType.CDROM)) { + logger.debug(">> cloning library drive %s...", image.getProviderId()); + + drive = api.cloneLibraryDrive(image.getProviderId(), null); + driveCloned.apply(drive); + + // Refresh the drive object and verify the clone operation didn't time out + drive = api.getDriveInfo(drive.getUuid()); + DriveStatus status = drive.getStatus(); + + if (DriveStatus.UNMOUNTED != status) { + if (destroyDrives) { + // Rollback the cloned drive, if needed + logger.error(">> clone operation failed. Rolling back drive (%s)...", drive); + destroyDrives(ImmutableList.of(drive.getUuid())); + } + throw new IllegalStateException("Resource is in invalid status: " + status); + } + + logger.debug(">> drive cloned (%s)...", drive); + } + + ImmutableList.Builder<FirewallRule> firewallRulesBuilder = ImmutableList.builder(); + for (int port : options.getInboundPorts()) { + firewallRulesBuilder.add(new FirewallRule.Builder().action(FirewallAction.ACCEPT) + .ipProtocol(FirewallIpProtocol.TCP).direction(FirewallDirection.IN).destinationPort("" + port).build()); + } + + List<NIC> nics = null; + try { + logger.debug(">> creating firewall policies..."); + FirewallPolicy firewallPolicy = api.createFirewallPolicy(new FirewallPolicy.Builder().rules( + firewallRulesBuilder.build()).build()); + nics = configureNICs(options, firewallPolicy); + } catch (Exception ex) { + if (destroyDrives) { + logger.debug(">> rolling back the cloned drive...", drive.getUuid()); + destroyDrives(ImmutableList.of(drive.getUuid())); + } + throw propagate(ex); + } + + List<Tag> tagIds = configureTags(options); + + // Cloud init images expect the public key in the server metadata + Map<String, String> metadata = Maps.newLinkedHashMap(); + metadata.put("image_id", image.getProviderId()); + if (!Strings.isNullOrEmpty(options.getPublicKey())) { + metadata.put("ssh_public_key", options.getPublicKey()); + } + metadata.putAll(options.getUserMetadata()); + + ServerInfo serverInfo = null; + try { + logger.debug(">> creating server..."); + + serverInfo = api.createServer(new ServerInfo.Builder() + .name(name) + .cpu((int) hardware.getProcessors().get(0).getSpeed()) + .memory(BigInteger.valueOf(hardware.getRam()).multiply(BigInteger.valueOf(1024 * 1024))) + .drives(ImmutableList.of(drive.toServerDrive(1, "0:1", options.getDeviceEmulationType()))) + .nics(nics) + .meta(metadata) + .tags(tagIds) + .vncPassword(Optional.fromNullable(options.getVncPassword()).or(defaultVncPassword)).build()); + + api.startServer(serverInfo.getUuid()); + + return new NodeAndInitialCredentials<ServerInfo>(serverInfo, serverInfo.getUuid(), LoginCredentials.builder() + .build()); + } catch (Exception ex) { + try { + if (serverInfo != null) { + logger.debug(">> rolling back the server..."); + api.deleteServer(serverInfo.getUuid()); + } + } finally { + try { + if (destroyDrives) { + logger.debug(">> rolling back the cloned drive..."); + destroyDrives(ImmutableList.of(drive.getUuid())); + } + } finally { + deleteTags(tagIds); + } + } + throw propagate(ex); + } + } + + @Override + public Iterable<Hardware> listHardwareProfiles() { + // Return a hardcoded list of hardware profiles until + // https://issues.apache.org/jira/browse/JCLOUDS-482 is fixed + Builder<Hardware> hardware = ImmutableSet.builder(); + Builder<Integer> ramSetBuilder = ImmutableSet.builder(); + Builder<Double> cpuSetBuilder = ImmutableSet.builder(); + for (int i = 1; i < 65; i++) { + ramSetBuilder.add(i * 1024); + } + for (int i = 1; i < 41; i++) { + cpuSetBuilder.add((double) i * 1000); + } + for (int ram : ramSetBuilder.build()) { + for (double cpu : cpuSetBuilder.build()) { + hardware.add(new HardwareBuilder().ids(String.format("cpu=%f,ram=%d", cpu, ram)) + .processor(new Processor(1, cpu)).ram(ram) + .volumes(ImmutableList.<Volume>of(new VolumeImpl(null, true, false))).build()); + } + } + return hardware.build(); + } + + @Override + public Iterable<LibraryDrive> listImages() { + return api.listLibraryDrives().concat(); + } + + @Override + public LibraryDrive getImage(String uuid) { + return api.getLibraryDrive(uuid); + } + + @Override + public Iterable<Location> listLocations() { + // Nothing to return here. Each provider will configure the locations + return ImmutableSet.<Location>of(); + } + + @Override + public ServerInfo getNode(String uuid) { + return api.getServerInfo(uuid); + } + + @Override + public void destroyNode(String uuid) { + ServerInfo server = api.getServerInfo(uuid); + + if (ServerStatus.RUNNING == server.getStatus()) { + api.stopServer(uuid); + waitUntilServerIsStopped(uuid); + } + + deleteTags(server.getTags()); + + List<String> driveIds = transform(server.getDrives(), new Function<ServerDrive, String>() { + @Override + public String apply(ServerDrive input) { + return input.getDriveUuid(); + } + }); + + logger.debug(">> deleting server..."); + api.deleteServer(uuid); + + if (destroyDrives) { + logger.debug(">> deleting server drives..."); + destroyDrives(driveIds); + } + } + + @Override + public void rebootNode(String uuid) { + api.stopServer(uuid); + waitUntilServerIsStopped(uuid); + api.startServer(uuid); + } + + @Override + public void resumeNode(String uuid) { + api.startServer(uuid); + } + + @Override + public void suspendNode(String uuid) { + api.stopServer(uuid); + } + + @Override + public Iterable<ServerInfo> listNodes() { + return api.listServersInfo().concat(); + } + + @Override + public Iterable<ServerInfo> listNodesByIds(final Iterable<String> uuids) { + // Only fetch the requested nodes. Do it in parallel. + ListenableFuture<List<ServerInfo>> futures = allAsList(transform(uuids, + new Function<String, ListenableFuture<ServerInfo>>() { + @Override + public ListenableFuture<ServerInfo> apply(final String input) { + return userExecutor.submit(new Callable<ServerInfo>() { + @Override + public ServerInfo call() throws Exception { + return api.getServerInfo(input); + } + }); + } + })); + + return getUnchecked(futures); + } + + private void waitUntilServerIsStopped(String uuid) { + serverStopped.apply(uuid); + ServerInfo server = api.getServerInfo(uuid); + checkState(server.getStatus() == ServerStatus.STOPPED, "Resource is in invalid status: %s", server.getStatus()); + } + + private List<NIC> configureNICs(CloudSigma2TemplateOptions options, FirewallPolicy firewallPolicy) { + ImmutableList.Builder<NIC> nics = ImmutableList.builder(); + for (String network : options.getNetworks()) { + VLANInfo vlan = api.getVLANInfo(network); + checkArgument(vlan != null, "network %s not found", network); + nics.add(new NIC.Builder().vlan(vlan).firewallPolicy(firewallPolicy).model(options.getNicModel()).build()); + } + + // If no network has been specified, assign an IP from the DHCP + if (options.getNetworks().isEmpty()) { + logger.debug(">> no networks configured. Will assign an IP from the DHCP..."); + NIC nic = new NIC.Builder().firewallPolicy(firewallPolicy).model(options.getNicModel()) + .ipV4Configuration(new IPConfiguration.Builder().configurationType(IPConfigurationType.DHCP).build()) + .build(); + nics.add(nic); + } + + return nics.build(); + } + + private List<Tag> configureTags(CloudSigma2TemplateOptions options) { + ImmutableList.Builder<Tag> builder = ImmutableList.builder(); + for (String tagName : options.getTags()) { + String nameWithPrefix = groupNamingConvention.sharedNameForGroup(tagName); + builder.add(new Tag.Builder().name(nameWithPrefix).build()); + } + + List<Tag> tags = builder.build(); + builder = ImmutableList.builder(); + + if (!tags.isEmpty()) { + logger.debug(">> creating tags..."); + builder.addAll(api.createTags(tags)); + } + + return builder.build(); + } + + private void deleteTags(List<Tag> tags) { + logger.debug(">> deleting server tags..."); + Iterable<Tag> customTags = filter(tags, new Predicate<Tag>() { + @Override + public boolean apply(Tag input) { + // Only delete the tags jclouds has set + Tag tag = api.getTagInfo(input.getUuid()); + return groupNamingConvention.groupInSharedNameOrNull(tag.getName()) != null; + } + }); + + for (Tag tag : customTags) { + try { + // Try to delete the tags but don't fail if the can't be deleted + api.deleteTag(tag.getUuid()); + } catch (Exception ex) { + logger.warn(ex, ">> could not delete tag: %s", tag); + } + } + } + + private void destroyDrives(List<String> driveIds) { + try { + // Try to delete the drives but don't fail if the can't be deleted, as the server has been already removed. + api.deleteDrives(driveIds); + } catch (Exception ex) { + logger.warn(ex, ">> could not delete drives: [%s]", Joiner.on(',').join(driveIds)); + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/config/CloudSigma2Properties.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/config/CloudSigma2Properties.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/config/CloudSigma2Properties.java index 66a35a7..b83ae0d 100644 --- a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/config/CloudSigma2Properties.java +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/config/CloudSigma2Properties.java @@ -19,8 +19,19 @@ package org.jclouds.cloudsigma2.config; public class CloudSigma2Properties { /** - * default VNC password used on new machines + * Default VNC password used on new machines */ public static final String PROPERTY_VNC_PASSWORD = "jclouds.cloudsigma.vnc-password"; - + + /** + * Time in milliseconds to wait for a drive to be cloned + * Default: 60000 + */ + public static final String TIMEOUT_DRIVE_CLONED = "jclouds.cloudsigma.timeout.drive-cloned"; + + /** + * Controls if the drives of a server should be destroyed when deleting the server + * Default: true + */ + public static final String PROPERTY_DELETE_DRIVES = "jclouds.cloudsigma.delete-drives"; } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/Drive.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/Drive.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/Drive.java index ec2ff76..14570d4 100644 --- a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/Drive.java +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/Drive.java @@ -166,7 +166,7 @@ public class Drive extends Item { * @param deviceChannel device channel in format {controller:unit} ex. 0:1, 0:2, etc. * @param deviceEmulationType device emulation type */ - public ServerDrive toServerDrive(int bootOrder, String deviceChannel, DeviceEmulationType deviceEmulationType) { + public ServerDrive toServerDrive(Integer bootOrder, String deviceChannel, DeviceEmulationType deviceEmulationType) { return new ServerDrive(bootOrder, deviceChannel, deviceEmulationType, this.uuid); } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/DrivesListRequestFieldsGroup.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/DrivesListRequestFieldsGroup.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/DrivesListRequestFieldsGroup.java index 9100050..56aad17 100644 --- a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/DrivesListRequestFieldsGroup.java +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/DrivesListRequestFieldsGroup.java @@ -16,7 +16,7 @@ */ package org.jclouds.cloudsigma2.domain; -import com.google.common.base.Joiner; +import java.util.Iterator; public class DrivesListRequestFieldsGroup { private final Iterable<String> fields; @@ -31,6 +31,18 @@ public class DrivesListRequestFieldsGroup { @Override public String toString() { - return Joiner.on(',').join(fields); + String returnString = ""; + + Iterator<?> iterator = fields.iterator(); + + while (iterator.hasNext()) { + returnString += iterator.next(); + + if (iterator.hasNext()) { + returnString += ","; + } + } + + return returnString; } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/FirewallPolicy.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/FirewallPolicy.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/FirewallPolicy.java index 50cf8ea..05ba638 100644 --- a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/FirewallPolicy.java +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/FirewallPolicy.java @@ -30,6 +30,7 @@ public class FirewallPolicy extends Item { private Map<String, String> meta; private Owner owner; private List<FirewallRule> rules; + private List<Tag> tags; private List<Server> servers; /** @@ -69,6 +70,15 @@ public class FirewallPolicy extends Item { } /** + * @param tags Many related resources. Can be either a list of URIs or list of individually nested resource data. + * @return + */ + public Builder tags(List<Tag> tags) { + this.tags = ImmutableList.copyOf(tags); + return this; + } + + /** * @param resourceUri Resource URI * @return */ @@ -98,25 +108,37 @@ public class FirewallPolicy extends Item { return this; } + public static Builder fromFirewallPolicy(FirewallPolicy firewallPolicy) { + return new Builder() + .resourceUri(firewallPolicy.getResourceUri()) + .uuid(firewallPolicy.getUuid()) + .rules(firewallPolicy.getRules()) + .name(firewallPolicy.getName()) + .meta(firewallPolicy.getMeta()) + .tags(firewallPolicy.getTags()); + } + public FirewallPolicy build() { - return new FirewallPolicy(meta, name, owner, resourceUri, rules, servers, uuid); + return new FirewallPolicy(meta, name, owner, resourceUri, rules, servers, tags, uuid); } } private final Map<String, String> meta; private final Owner owner; private final List<FirewallRule> rules; + private final List<Tag> tags; private final List<Server> servers; @ConstructorProperties({ - "meta", "name", "owner", "resource_uri", "rules", "servers", "uuid" + "meta", "name", "owner", "resource_uri", "rules", "servers", "tags", "uuid" }) public FirewallPolicy(Map<String, String> meta, String name, Owner owner, URI resourceUri, List<FirewallRule> rules, - List<Server> servers, String uuid) { + List<Server> servers, List<Tag> tags, String uuid) { super(uuid, name, resourceUri); this.meta = meta; this.owner = owner; this.rules = rules == null ? new ArrayList<FirewallRule>() : rules; + this.tags = tags == null ? new ArrayList<Tag>() : tags; this.servers = servers == null ? new ArrayList<Server>() : servers; } @@ -163,6 +185,13 @@ public class FirewallPolicy extends Item { } /** + * @return Related resources URI list. + */ + public List<Tag> getTags() { + return tags; + } + + /** * @return UUID of the policy */ public String getUuid() { @@ -172,7 +201,7 @@ public class FirewallPolicy extends Item { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof FirewallPolicy)) return false; + if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; FirewallPolicy that = (FirewallPolicy) o; @@ -181,6 +210,7 @@ public class FirewallPolicy extends Item { if (owner != null ? !owner.equals(that.owner) : that.owner != null) return false; if (rules != null ? !rules.equals(that.rules) : that.rules != null) return false; if (servers != null ? !servers.equals(that.servers) : that.servers != null) return false; + if (tags != null ? !tags.equals(that.tags) : that.tags != null) return false; return true; } @@ -191,6 +221,7 @@ public class FirewallPolicy extends Item { result = 31 * result + (meta != null ? meta.hashCode() : 0); result = 31 * result + (owner != null ? owner.hashCode() : 0); result = 31 * result + (rules != null ? rules.hashCode() : 0); + result = 31 * result + (tags != null ? tags.hashCode() : 0); result = 31 * result + (servers != null ? servers.hashCode() : 0); return result; } @@ -199,12 +230,10 @@ public class FirewallPolicy extends Item { public String toString() { return "[" + "meta=" + meta + - ", name='" + name + '\'' + ", owner=" + owner + - ", resourceUri='" + resourceUri + '\'' + ", rules=" + rules + + ", tags=" + tags + ", servers=" + servers + - ", uuid='" + uuid + '\'' + "]"; } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/LibraryDrive.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/LibraryDrive.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/LibraryDrive.java index d479867..d7a0ca5 100644 --- a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/LibraryDrive.java +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/LibraryDrive.java @@ -38,6 +38,7 @@ public class LibraryDrive extends DriveInfo { private String os; private boolean isPaid; private String url; + private String version; public Builder arch(String arch) { this.arch = arch; @@ -84,6 +85,11 @@ public class LibraryDrive extends DriveInfo { return this; } + public Builder version(String version) { + this.version = version; + return this; + } + /** * {@inheritDoc} */ @@ -226,7 +232,7 @@ public class LibraryDrive extends DriveInfo { public LibraryDrive build() { return new LibraryDrive(uuid, name, resourceUri, size, owner, status, allowMultimount, affinities, jobs, licenses, media, meta, mountedOn, tags, arch, category, description, isFavorite, imageType, installNotes, - os, isPaid, url); + os, isPaid, url, version); } } @@ -243,18 +249,20 @@ public class LibraryDrive extends DriveInfo { @Named("paid") private final boolean isPaid; private final String url; + private final String version; @ConstructorProperties({ "uuid", "name", "resource_uri", "size", "owner", "status", "allow_multimount", "affinities", "jobs", "licenses", "media", "meta", "mounted_on", "tags", "arch", "category", - "description", "favourite", "image_type", "install_notes", "os", "paid", "url" + "description", "favourite", "image_type", "install_notes", + "os", "paid", "url", "version" }) public LibraryDrive(String uuid, String name, URI resourceUri, BigInteger size, Owner owner, DriveStatus status, boolean allowMultimount, List<String> affinities, List<Job> jobs, List<DriveLicense> licenses, MediaType media, Map<String, String> meta, List<Server> mountedOn, List<String> tags, String arch, List<String> category, String description, boolean favorite, String imageType, - String installNotes, String os, boolean paid, String url) { + String installNotes, String os, boolean paid, String url, String version) { super(uuid, name, resourceUri, size, owner, status, allowMultimount, affinities, jobs, licenses, media, meta, mountedOn, tags); this.arch = arch; @@ -266,6 +274,7 @@ public class LibraryDrive extends DriveInfo { this.os = os; this.isPaid = paid; this.url = url; + this.version = version; } /** @@ -331,10 +340,17 @@ public class LibraryDrive extends DriveInfo { return url; } + /** + * @return Operating system version. + */ + public String getVersion() { + return version; + } + @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof LibraryDrive)) return false; + if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; LibraryDrive that = (LibraryDrive) o; @@ -348,6 +364,7 @@ public class LibraryDrive extends DriveInfo { if (installNotes != null ? !installNotes.equals(that.installNotes) : that.installNotes != null) return false; if (os != null ? !os.equals(that.os) : that.os != null) return false; if (url != null ? !url.equals(that.url) : that.url != null) return false; + if (version != null ? !version.equals(that.version) : that.version != null) return false; return true; } @@ -364,15 +381,14 @@ public class LibraryDrive extends DriveInfo { result = 31 * result + (os != null ? os.hashCode() : 0); result = 31 * result + (isPaid ? 1 : 0); result = 31 * result + (url != null ? url.hashCode() : 0); + result = 31 * result + (version != null ? version.hashCode() : 0); return result; } @Override public String toString() { - return "[uuid=" + uuid + ", name=" + name + ", size=" + size + ", owner=" + owner + ", status=" + status - + ", affinities=" + affinities + ", jobs=" + jobs + ", licenses=" + licenses + ", media=" + media - + ", meta=" + meta + ", mountedOn=" + mountedOn + ", tags=" + tags + - ", arch='" + arch + '\'' + + return "LibraryDrive{" + + "arch='" + arch + '\'' + ", category=" + category + ", description='" + description + '\'' + ", isFavorite=" + isFavorite + @@ -381,6 +397,7 @@ public class LibraryDrive extends DriveInfo { ", os='" + os + '\'' + ", isPaid=" + isPaid + ", url='" + url + '\'' + - "]"; + ", version='" + version + '\'' + + '}'; } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerAvailabilityGroup.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerAvailabilityGroup.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerAvailabilityGroup.java index 4104f15..855e782 100644 --- a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerAvailabilityGroup.java +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerAvailabilityGroup.java @@ -16,10 +16,9 @@ */ package org.jclouds.cloudsigma2.domain; +import java.util.Iterator; import java.util.List; -import com.google.common.base.Joiner; - public class ServerAvailabilityGroup { private final List<String> uuids; @@ -51,6 +50,18 @@ public class ServerAvailabilityGroup { @Override public String toString() { - return Joiner.on(',').join(uuids); + String returnString = ""; + + Iterator<?> iterator = uuids.iterator(); + + while (iterator.hasNext()) { + returnString += iterator.next(); + + if (iterator.hasNext()) { + returnString += ","; + } + } + + return returnString; } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerDrive.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerDrive.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerDrive.java index 7f69e35..cff05c1 100644 --- a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerDrive.java +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerDrive.java @@ -22,12 +22,12 @@ import java.beans.ConstructorProperties; public class ServerDrive { public static class Builder { - private int bootOrder; + private Integer bootOrder; private String deviceChannel; private DeviceEmulationType deviceEmulationType; private Drive drive; - public Builder bootOrder(int bootOrder) { + public Builder bootOrder(Integer bootOrder) { this.bootOrder = bootOrder; return this; } @@ -53,7 +53,7 @@ public class ServerDrive { } @Named("boot_order") - private final int bootOrder; + private final Integer bootOrder; @Named("dev_channel") private final String deviceChannel; @Named("device") @@ -71,7 +71,7 @@ public class ServerDrive { @ConstructorProperties({ "boot_order", "dev_channel", "device", "drive" }) - public ServerDrive(int bootOrder, String deviceChannel, DeviceEmulationType deviceEmulationType, Drive drive) { + public ServerDrive(Integer bootOrder, String deviceChannel, DeviceEmulationType deviceEmulationType, Drive drive) { this.bootOrder = bootOrder; this.deviceChannel = deviceChannel; this.deviceEmulationType = deviceEmulationType; @@ -96,7 +96,7 @@ public class ServerDrive { /** * @return drive boot order */ - public int getBootOrder() { + public Integer getBootOrder() { return bootOrder; } @@ -131,31 +131,37 @@ public class ServerDrive { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof ServerDrive)) return false; + if (o == null || getClass() != o.getClass()) return false; ServerDrive that = (ServerDrive) o; - if (bootOrder != that.bootOrder) return false; - if (deviceChannel != null ? !deviceChannel.equals(that.deviceChannel) : that.deviceChannel != null) - return false; + if (bootOrder != null ? !bootOrder.equals(that.bootOrder) : that.bootOrder != null) return false; + if (deviceChannel != null ? !deviceChannel.equals(that.deviceChannel) : that.deviceChannel != null) return false; if (deviceEmulationType != that.deviceEmulationType) return false; if (drive != null ? !drive.equals(that.drive) : that.drive != null) return false; + if (driveUuid != null ? !driveUuid.equals(that.driveUuid) : that.driveUuid != null) return false; return true; } @Override public int hashCode() { - int result = bootOrder; + int result = bootOrder != null ? bootOrder.hashCode() : 0; result = 31 * result + (deviceChannel != null ? deviceChannel.hashCode() : 0); result = 31 * result + (deviceEmulationType != null ? deviceEmulationType.hashCode() : 0); result = 31 * result + (drive != null ? drive.hashCode() : 0); + result = 31 * result + (driveUuid != null ? driveUuid.hashCode() : 0); return result; } @Override public String toString() { - return "[bootOrder=" + bootOrder + ", deviceChannel=" + deviceChannel - + ", deviceEmulationType=" + deviceEmulationType + ", drive=" + drive + "]"; + return "ServerDrive{" + + "bootOrder=" + bootOrder + + ", deviceChannel='" + deviceChannel + '\'' + + ", deviceEmulationType=" + deviceEmulationType + + ", drive=" + drive + + ", driveUuid='" + driveUuid + '\'' + + '}'; } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerInfo.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerInfo.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerInfo.java index 062eae5..f3e4a00 100644 --- a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerInfo.java +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/domain/ServerInfo.java @@ -39,7 +39,7 @@ public class ServerInfo extends Server { private Map<String, String> meta; private List<NIC> nics; private List<String> requirements; - private List<String> tags; + private List<Tag> tags; private String vncPassword; private int smp; @@ -137,7 +137,7 @@ public class ServerInfo extends Server { * @param tags list of tags this server is associated with * @return ServerInfo Builder */ - public Builder tags(List<String> tags) { + public Builder tags(List<Tag> tags) { this.tags = ImmutableList.copyOf(tags); return this; } @@ -278,7 +278,7 @@ public class ServerInfo extends Server { private final Map<String, String> meta; private final List<NIC> nics; private final List<String> requirements; - private final List<String> tags; + private final List<Tag> tags; @Named("vnc_password") private final String vncPassword; private final int smp; @@ -292,7 +292,7 @@ public class ServerInfo extends Server { public ServerInfo(String uuid, String name, URI resourceUri, Owner owner, ServerStatus status, ServerRuntime runtime, int cpu, boolean cpusInsteadOfCores, List<ServerDrive> drives, boolean enableNuma, boolean hvRelaxed, boolean hvTsc, BigInteger memory, Map<String, String> meta, List<NIC> nics, - List<String> requirements, List<String> tags, String vncPassword, int smp) { + List<String> requirements, List<Tag> tags, String vncPassword, int smp) { super(uuid, name, resourceUri, owner, status, runtime); this.cpu = cpu; this.cpusInsteadOfCores = cpusInsteadOfCores; @@ -382,7 +382,7 @@ public class ServerInfo extends Server { /** * @return list of tags this server is associated with */ - public List<String> getTags() { + public List<Tag> getTags() { return tags; } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/functions/internal/ParseTags.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/functions/internal/ParseTags.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/functions/internal/ParseTags.java index c7427b1..ff6c1a8 100644 --- a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/functions/internal/ParseTags.java +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/functions/internal/ParseTags.java @@ -67,25 +67,4 @@ public class ParseTags extends ParseJson<ParseTags.Tags> { }; } } - - public static class ToPagedIterableInfo extends ArgsToPagedIterable<Tag, ToPagedIterable> { - - private CloudSigma2Api api; - - @Inject - public ToPagedIterableInfo(CloudSigma2Api api) { - this.api = api; - } - - @Override - protected Function<Object, IterableWithMarker<Tag>> markerToNextForArgs(List<Object> args) { - return new Function<Object, IterableWithMarker<Tag>>() { - @Override - public IterableWithMarker<Tag> apply(Object input) { - PaginationOptions paginationOptions = PaginationOptions.class.cast(input); - return api.listTagsInfo(paginationOptions); - } - }; - } - } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/handlers/CloudSigmaErrorHandler.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/handlers/CloudSigmaErrorHandler.java b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/handlers/CloudSigmaErrorHandler.java index a2912e7..f41e865 100644 --- a/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/handlers/CloudSigmaErrorHandler.java +++ b/cloudsigma2/src/main/java/org/jclouds/cloudsigma2/handlers/CloudSigmaErrorHandler.java @@ -16,8 +16,11 @@ */ package org.jclouds.cloudsigma2.handlers; -import com.google.common.base.Throwables; -import com.google.common.io.Closeables; +import java.io.IOException; + +import javax.annotation.Resource; +import javax.inject.Singleton; + import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpResponse; @@ -27,9 +30,8 @@ import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.util.Strings2; -import javax.annotation.Resource; -import javax.inject.Singleton; -import java.io.IOException; +import com.google.common.base.Throwables; +import com.google.common.io.Closeables; /** * This will parse and set an appropriate exception on the command object. http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/CloudSigma2ApiExpectTest.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/CloudSigma2ApiExpectTest.java b/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/CloudSigma2ApiExpectTest.java index e5ff7ad..1395eae 100644 --- a/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/CloudSigma2ApiExpectTest.java +++ b/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/CloudSigma2ApiExpectTest.java @@ -16,8 +16,16 @@ */ package org.jclouds.cloudsigma2; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Maps; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +import java.math.BigInteger; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.MediaType; + import org.jclouds.cloudsigma2.domain.AccountBalance; import org.jclouds.cloudsigma2.domain.CalcSubscription; import org.jclouds.cloudsigma2.domain.CreateSubscriptionRequest; @@ -52,14 +60,8 @@ import org.jclouds.http.HttpResponse; import org.jclouds.rest.internal.BaseRestApiExpectTest; import org.testng.annotations.Test; -import javax.ws.rs.core.MediaType; -import java.math.BigInteger; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Maps; @Test(groups = "unit") public class CloudSigma2ApiExpectTest extends BaseRestApiExpectTest<CloudSigma2Api> { @@ -323,7 +325,7 @@ public class CloudSigma2ApiExpectTest extends BaseRestApiExpectTest<CloudSigma2A @Test public void testCloneDrive() throws Exception { - String uuid = "e96f3c63-6f50-47eb-9401-a56c5ccf6b32"; + String uuid = "92ca1450-417e-4cc1-983b-1015777e2591"; CloudSigma2Api api = requestSendsResponse( postBuilder() .payload(payloadFromResourceWithContentType("/drives-create-request.json", @@ -331,7 +333,7 @@ public class CloudSigma2ApiExpectTest extends BaseRestApiExpectTest<CloudSigma2A .endpoint(endpoint + "drives/" + uuid + "/action/?do=clone") .build(), responseBuilder() - .payload(payloadFromResourceWithContentType("/drives-detail.json", MediaType.APPLICATION_JSON)) + .payload(payloadFromResourceWithContentType("/drive-cloned.json", MediaType.APPLICATION_JSON)) .build()); DriveInfo result = api.cloneDrive(uuid, new DriveInfo.Builder() @@ -404,7 +406,7 @@ public class CloudSigma2ApiExpectTest extends BaseRestApiExpectTest<CloudSigma2A @Test public void testCloneLibraryDrive() throws Exception { - String uuid = "e96f3c63-6f50-47eb-9401-a56c5ccf6b32"; + String uuid = "8c45d8d9-4efd-44ec-9833-8d52004b4298"; CloudSigma2Api api = requestSendsResponse( postBuilder() .payload(payloadFromResourceWithContentType("/libdrives-create-request.json", @@ -412,7 +414,7 @@ public class CloudSigma2ApiExpectTest extends BaseRestApiExpectTest<CloudSigma2A .endpoint(endpoint + "libdrives/" + uuid + "/action/?do=clone") .build(), responseBuilder() - .payload(payloadFromResourceWithContentType("/libdrives-single.json", MediaType.APPLICATION_JSON)) + .payload(payloadFromResourceWithContentType("/libdrives-cloned.json", MediaType.APPLICATION_JSON)) .build()); DriveInfo result = api.cloneLibraryDrive(uuid, new LibraryDrive.Builder() @@ -817,6 +819,27 @@ public class CloudSigma2ApiExpectTest extends BaseRestApiExpectTest<CloudSigma2A } @Test + public void testGetFirewallPolicy() throws Exception { + String uuid = "9001b532-857a-405a-8e50-54e342871e77"; + CloudSigma2Api api = requestsSendResponses( + getBuilder() + .endpoint(endpoint + "fwpolicies/" + uuid + "/") + .build(), + responseBuilder() + .payload(payloadFromResourceWithContentType("/fwpolicies-get-single.json", + MediaType.APPLICATION_JSON)) + .build(), + getBuilder() + .endpoint(endpoint + "fwpolicies/failure") + .build(), + HttpResponse.builder() + .statusCode(404) + .build()); + + assertNotNull(api.getFirewallPolicy(uuid)); + } + + @Test public void testCreateFirewallPolicies() throws Exception { CloudSigma2Api api = requestSendsResponse( postBuilder() @@ -1000,6 +1023,26 @@ public class CloudSigma2ApiExpectTest extends BaseRestApiExpectTest<CloudSigma2A } @Test + public void testDeleteFirewallPolicy() throws Exception { + String uuid = "9001b532-857a-405a-8e50-54e342871e77"; + + CloudSigma2Api api = requestsSendResponses( + deleteBuilder() + .endpoint(endpoint + "fwpolicies/" + uuid + "/") + .build(), + responseBuilder() + .build(), + deleteBuilder() + .endpoint(endpoint + "fwpolicies/failure") + .build(), + HttpResponse.builder() + .statusCode(404) + .build()); + + api.deleteFirewallPolicy(uuid); + } + + @Test public void testGetVLANInfo() throws Exception { String uuid = "96537817-f4b6-496b-a861-e74192d3ccb0"; CloudSigma2Api api = requestSendsResponse( @@ -1276,50 +1319,6 @@ public class CloudSigma2ApiExpectTest extends BaseRestApiExpectTest<CloudSigma2A } @Test - public void testListTagsInfo() throws Exception { - CloudSigma2Api api = requestsSendResponses( - getBuilder() - .endpoint(endpoint + "tags/detail/") - .build(), - responseBuilder() - .payload(payloadFromResourceWithContentType("/tags-detail-first-page.json", - MediaType.APPLICATION_JSON)) - .build(), - getBuilder() - .endpoint(endpoint + "tags/detail/") - .addQueryParam("limit", "1") - .addQueryParam("offset", "1") - .build(), - responseBuilder() - .payload(payloadFromResourceWithContentType("/tags-detail-last-page.json", - MediaType.APPLICATION_JSON)) - .build()); - - - List<Tag> tags = api.listTagsInfo().concat().toList(); - - assertEquals(tags.size(), 2); - assertEquals(tags.get(0).getUuid(), "956e2ca0-dee3-4b3f-a1be-a6e86f90946f"); - assertEquals(tags.get(1).getUuid(), "68bb0cfc-0c76-4f37-847d-7bb705c5ae46"); - } - - - @Test - public void testListTagsInfoPaginatedCollection() throws Exception { - CloudSigma2Api api = requestSendsResponse( - getBuilder() - .endpoint(endpoint + "tags/detail/?limit=2&offset=2") - .build(), - responseBuilder() - .payload(payloadFromResourceWithContentType("/tags-detail.json", MediaType.APPLICATION_JSON)) - .build()); - - for (Tag tag : api.listTagsInfo(new PaginationOptions.Builder().limit(2).offset(2).build())) { - assertNotNull(tag); - } - } - - @Test public void testGetTagInfo() throws Exception { String uuid = "68bb0cfc-0c76-4f37-847d-7bb705c5ae46"; CloudSigma2Api api = requestSendsResponse( http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/CloudSigma2ApiLiveTest.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/CloudSigma2ApiLiveTest.java b/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/CloudSigma2ApiLiveTest.java index 5fcf1bb..751dea8 100644 --- a/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/CloudSigma2ApiLiveTest.java +++ b/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/CloudSigma2ApiLiveTest.java @@ -70,10 +70,13 @@ import com.google.common.collect.Maps; public class CloudSigma2ApiLiveTest extends BaseApiLiveTest<CloudSigma2Api> { private DriveInfo createdDrive; + private DriveInfo clonedDrive; + private LibraryDrive clonedLibraryDrive; private List<DriveInfo> createdDrives; private ServerInfo createdServer; private List<ServerInfo> createdServers; private FirewallPolicy createdFirewallPolicy; + private List<FirewallPolicy> createdFirewallPolicies; private Tag createdTag; private List<Tag> createdTags; @@ -142,11 +145,23 @@ public class CloudSigma2ApiLiveTest extends BaseApiLiveTest<CloudSigma2Api> { checkDrive(editedDrive, api.editDrive(createdDrive.getUuid(), editedDrive)); } + @Test(dependsOnMethods = {"testCreateDrive"}) + public void testCloneDrive() throws Exception { + clonedDrive = api.cloneDrive(createdDrive.getUuid(), null); + checkDrive(createdDrive, clonedDrive); + } + @Test(dependsOnMethods = {"testEditDrive", "testCreateTag", "testEditTag"}) public void testDeleteDrive() throws Exception { String uuid = createdDrive.getUuid(); api.deleteDrive(uuid); assertNull(api.getDriveInfo(uuid)); + String clonedDriveUuid = clonedDrive.getUuid(); + api.deleteDrive(clonedDriveUuid); + assertNull(api.getDriveInfo(clonedDriveUuid)); + String clonedLibraryDriveUuid = clonedLibraryDrive.getUuid(); + api.deleteDrive(clonedLibraryDriveUuid); + assertNull(api.getDriveInfo(clonedLibraryDriveUuid)); } @Test(dependsOnMethods = {"testCreateDrives"}) @@ -175,6 +190,13 @@ public class CloudSigma2ApiLiveTest extends BaseApiLiveTest<CloudSigma2Api> { } } + @Test + public void testCloneLibraryDrive() throws Exception { + LibraryDrive libraryDrive = api.listLibraryDrives().concat().get(0); + clonedLibraryDrive = api.cloneLibraryDrive(libraryDrive.getUuid(), null); + checkLibraryDrive(libraryDrive, clonedLibraryDrive); + } + @Test(dependsOnMethods = {"testCreateServers"}) public void testListServers() throws Exception { assertNotNull(api.listServers()); @@ -273,6 +295,15 @@ public class CloudSigma2ApiLiveTest extends BaseApiLiveTest<CloudSigma2Api> { assertNotNull(api.listFirewallPoliciesInfo()); } + @Test(dependsOnMethods = {"testCreateFirewallPolicies"}) + public void testGetFirewallPolicy() throws Exception { + for (FirewallPolicy firewallPolicy : api.listFirewallPoliciesInfo().concat()) { + FirewallPolicy receivedPolicy = api.getFirewallPolicy(firewallPolicy.getUuid()); + checkFirewallPolicy(firewallPolicy, receivedPolicy); + assertEquals(firewallPolicy.getUuid(), receivedPolicy.getUuid()); + } + } + @Test public void testCreateFirewallPolicies() throws Exception { List<FirewallPolicy> newFirewallPolicies = ImmutableList.of( @@ -329,7 +360,7 @@ public class CloudSigma2ApiLiveTest extends BaseApiLiveTest<CloudSigma2Api> { .build())) .build()); - List<FirewallPolicy> createdFirewallPolicies = api.createFirewallPolicies(newFirewallPolicies); + createdFirewallPolicies = api.createFirewallPolicies(newFirewallPolicies); assertEquals(newFirewallPolicies.size(), createdFirewallPolicies.size()); for (int i = 0; i < newFirewallPolicies.size(); i++) { @@ -403,6 +434,23 @@ public class CloudSigma2ApiLiveTest extends BaseApiLiveTest<CloudSigma2Api> { checkFirewallPolicy(editedPolicy, api.editFirewallPolicy(createdFirewallPolicy.getUuid(), editedPolicy)); } + @Test(dependsOnMethods = {"testEditFirewallPolicy", "testCreateFirewallPolicies"}) + public void deleteFirewallPolicies() throws Exception { + ImmutableList.Builder<String> stringListBuilder = ImmutableList.builder(); + + stringListBuilder.add(createdFirewallPolicy.getUuid()); + api.deleteFirewallPolicy(createdFirewallPolicy.getUuid()); + + for (FirewallPolicy firewallPolicy : createdFirewallPolicies) { + stringListBuilder.add(firewallPolicy.getUuid()); + api.deleteFirewallPolicy(firewallPolicy.getUuid()); + } + + ImmutableList<String> uuids = stringListBuilder.build(); + FluentIterable<FirewallPolicy> servers = api.listFirewallPolicies().concat(); + assertFalse(any(transform(servers, extractUuid()), in(uuids))); + } + @Test public void testListVLANs() throws Exception { assertNotNull(api.listVLANs()); @@ -429,7 +477,7 @@ public class CloudSigma2ApiLiveTest extends BaseApiLiveTest<CloudSigma2Api> { .meta(meta) .build(); - if (!api.listVLANs().isEmpty()) { + if (!api.listVLANs().concat().isEmpty()) { checkVlAN(vlanInfo, api.editVLAN(api.listVLANs().concat().get(0).getUuid(), vlanInfo)); } } @@ -460,7 +508,7 @@ public class CloudSigma2ApiLiveTest extends BaseApiLiveTest<CloudSigma2Api> { .meta(meta) .build(); - if (!api.listIPs().isEmpty()) { + if (!api.listIPs().concat().isEmpty()) { checkIP(ip, api.editIP(api.listIPs().concat().get(0).getUuid(), ip)); } } @@ -471,11 +519,6 @@ public class CloudSigma2ApiLiveTest extends BaseApiLiveTest<CloudSigma2Api> { } @Test(dependsOnMethods = {"testCreateTags"}) - public void testListTagsInfo() throws Exception { - assertNotNull(api.listTagsInfo()); - } - - @Test(dependsOnMethods = {"testCreateTags"}) public void testGetTagInfo() throws Exception { for (Tag tag : api.listTags().concat()) { assertNotNull(api.getTagInfo(tag.getUuid())); @@ -652,6 +695,18 @@ public class CloudSigma2ApiLiveTest extends BaseApiLiveTest<CloudSigma2Api> { assertEquals(newDrive.getMedia(), createdDrive.getMedia()); } + private void checkLibraryDrive(LibraryDrive newDrive, LibraryDrive createdDrive) { + checkDrive(newDrive, createdDrive); + Map<String, String> meta = createdDrive.getMeta(); + + assertEquals(newDrive.getArch() == null ? "None" : newDrive.getArch(), meta.get("arch")); + assertEquals(newDrive.getDescription() == null ? "None" : newDrive.getDescription(), meta.get("description")); + assertEquals(newDrive.getImageType() == null ? "None" : newDrive.getImageType(), meta.get("image_type")); + assertEquals(newDrive.getInstallNotes() == null ? "None" : newDrive.getInstallNotes(), meta.get("install_notes")); + assertEquals(newDrive.getOs() == null ? "None" : newDrive.getOs(), meta.get("os")); + assertEquals(newDrive.getVersion() == null ? "None" : newDrive.getVersion(), meta.get("version")); + } + private void checkServer(ServerInfo newServer, ServerInfo createdServer) { assertEquals(newServer.getName(), createdServer.getName()); assertEquals(newServer.getMemory(), createdServer.getMemory()); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/CloudSigma2ComputeServiceLiveTest.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/CloudSigma2ComputeServiceLiveTest.java b/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/CloudSigma2ComputeServiceLiveTest.java new file mode 100644 index 0000000..d0b5a91 --- /dev/null +++ b/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/CloudSigma2ComputeServiceLiveTest.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cloudsigma2.compute; + +import com.google.inject.Module; +import org.jclouds.compute.domain.ExecResponse; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.internal.BaseComputeServiceLiveTest; +import org.jclouds.sshj.config.SshjSshClientModule; +import org.testng.annotations.Test; + +@Test(groups = "live", testName = "CloudSigma2ComputeServiceLiveTest") +public class CloudSigma2ComputeServiceLiveTest extends BaseComputeServiceLiveTest { + + public CloudSigma2ComputeServiceLiveTest() { + provider = "cloudsigma2"; + + } + + @Override + protected Module getSshModule() { + return new SshjSshClientModule(); + } + + // CloudSigma templates require manual interaction to change the password on the first login. + // The only way to automatically authenticate to a server is to use an image that supports Cloud Init + // and provide the public key + @Override + protected Template buildTemplate(TemplateBuilder templateBuilder) { + Template template = super.buildTemplate(templateBuilder); + template.getOptions().authorizePublicKey(keyPair.get("public")); + return template; + } + + @Override + protected void checkResponseEqualsHostname(ExecResponse execResponse, NodeMetadata node1) { + // CloudSigma does not return the hostname + } + +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/config/DriveClonedPredicateTest.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/config/DriveClonedPredicateTest.java b/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/config/DriveClonedPredicateTest.java new file mode 100644 index 0000000..acabdb3 --- /dev/null +++ b/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/config/DriveClonedPredicateTest.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cloudsigma2.compute.config; + +import org.easymock.EasyMock; +import org.jclouds.cloudsigma2.CloudSigma2Api; +import org.jclouds.cloudsigma2.compute.config.CloudSigma2ComputeServiceContextModule.DriveClonedPredicate; +import org.jclouds.cloudsigma2.domain.DriveInfo; +import org.jclouds.cloudsigma2.domain.DriveStatus; +import org.testng.annotations.Test; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +/** + * Unit tests for the drive cloned predicate + */ +@Test(groups = "unit", testName = "DriveClonedPredicateTest") +public class DriveClonedPredicateTest { + + public void testDriveCloned() { + CloudSigma2Api api = EasyMock.createMock(CloudSigma2Api.class); + + for (DriveStatus status : DriveStatus.values()) { + expect(api.getDriveInfo(status.name())).andReturn(mockDrive(status)); + } + + replay(api); + + DriveClonedPredicate predicate = new DriveClonedPredicate(api); + + assertFalse(predicate.apply(mockDrive(DriveStatus.COPYING))); + assertFalse(predicate.apply(mockDrive(DriveStatus.UNAVAILABLE))); + assertTrue(predicate.apply(mockDrive(DriveStatus.MOUNTED))); + assertTrue(predicate.apply(mockDrive(DriveStatus.UNMOUNTED))); + + verify(api); + } + + private static DriveInfo mockDrive(DriveStatus status) { + return new DriveInfo.Builder().uuid(status.name()).status(status).build(); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/config/ServerStatusPredicatePredicateTest.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/config/ServerStatusPredicatePredicateTest.java b/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/config/ServerStatusPredicatePredicateTest.java new file mode 100644 index 0000000..ea17420 --- /dev/null +++ b/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/config/ServerStatusPredicatePredicateTest.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cloudsigma2.compute.config; + +import org.easymock.EasyMock; +import org.jclouds.cloudsigma2.CloudSigma2Api; +import org.jclouds.cloudsigma2.compute.config.CloudSigma2ComputeServiceContextModule.ServerStatusPredicate; +import org.jclouds.cloudsigma2.domain.ServerInfo; +import org.testng.annotations.Test; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.jclouds.cloudsigma2.domain.ServerStatus.STOPPED; +import static org.jclouds.cloudsigma2.domain.ServerStatus.STOPPING; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +/** + * Unit tests for the server status predicate. + */ +@Test(groups = "unit", testName = "ServerStatusPredicatePredicateTest") +public class ServerStatusPredicatePredicateTest { + + public void testServerStatus() { + CloudSigma2Api api = EasyMock.createMock(CloudSigma2Api.class); + + expect(api.getServerInfo("one")).andReturn(new ServerInfo.Builder().status(STOPPED).build()); + expect(api.getServerInfo("two")).andReturn(new ServerInfo.Builder().status(STOPPING).build()); + + replay(api); + + ServerStatusPredicate predicate = new ServerStatusPredicate(api, STOPPED); + assertTrue(predicate.apply("one")); + assertFalse(predicate.apply("two")); + + verify(api); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a7dd1933/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/functions/LibraryDriveToImageTest.java ---------------------------------------------------------------------- diff --git a/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/functions/LibraryDriveToImageTest.java b/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/functions/LibraryDriveToImageTest.java new file mode 100644 index 0000000..313ea61 --- /dev/null +++ b/cloudsigma2/src/test/java/org/jclouds/cloudsigma2/compute/functions/LibraryDriveToImageTest.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cloudsigma2.compute.functions; + +import com.google.common.collect.ImmutableMap; +import org.jclouds.cloudsigma2.domain.DriveStatus; +import org.jclouds.cloudsigma2.domain.LibraryDrive; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.domain.OsFamily; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import static org.jclouds.cloudsigma2.compute.config.CloudSigma2ComputeServiceContextModule.driveStatusToImageStatus; +import static org.testng.Assert.assertEquals; + +@Test(groups = "unit", testName = "LibraryDriveToImageTest") +public class LibraryDriveToImageTest { + + private LibraryDrive input; + private Image expected; + + @BeforeMethod + public void setUp() throws Exception { + input = new LibraryDrive.Builder() + .uuid("0bc6b02c-7ea2-4c5c-bf07-41c4cec2797d") + .name("Debian 7.3 Server") + .description("Debian 7.3 Server - amd64 Pre-Installed English with Python, SSH and VirtIO support. " + + "Last update 2014/02/15.") + .os("linux") + .arch("64") + .version("7.3") + .status(DriveStatus.UNMOUNTED) + .meta(ImmutableMap.of("test_key", "test_value", + "sample key", "sample value")) + .build(); + + expected = new ImageBuilder() + .ids("0bc6b02c-7ea2-4c5c-bf07-41c4cec2797d") + .userMetadata(ImmutableMap.of("test_key", "test_value", + "sample key", "sample value")) + .name("Debian 7.3 Server") + .description("Debian 7.3 Server - amd64 Pre-Installed English with Python, SSH and VirtIO support. " + + "Last update 2014/02/15.") + .operatingSystem(OperatingSystem.builder() + .name("Debian 7.3 Server") + .arch("64") + .family(OsFamily.LINUX) + .version("7.3") + .is64Bit(true) + .description("Debian 7.3 Server - amd64 Pre-Installed English with Python, SSH and VirtIO support. " + + "Last update 2014/02/15.") + .build()) + .status(Image.Status.UNRECOGNIZED) + .build(); + } + + public void testConvertLibraryDrive() { + LibraryDriveToImage function = new LibraryDriveToImage(driveStatusToImageStatus); + Image converted = function.apply(input); + assertEquals(converted, expected); + assertEquals(converted.getUserMetadata(), expected.getUserMetadata()); + assertEquals(converted.getName(), expected.getName()); + assertEquals(converted.getDescription(), expected.getDescription()); + assertEquals(converted.getStatus(), expected.getStatus()); + assertEquals(converted.getOperatingSystem(), expected.getOperatingSystem()); + } +}
