Implementing BaseImageToHardware and CleanupServer functions.
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/172d6f34 Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/172d6f34 Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/172d6f34 Branch: refs/heads/master Commit: 172d6f34960dd1389ded5884922f81dfc494f96e Parents: 2b8bfcb Author: Trevor Flanagan <[email protected]> Authored: Mon Dec 4 16:13:15 2017 +0000 Committer: Ignasi Barrera <[email protected]> Committed: Tue Dec 5 09:18:00 2017 +0100 ---------------------------------------------------------------------- .../compute/functions/BaseImageToHardware.java | 65 ++++++ .../compute/functions/CleanupServer.java | 189 +++++++++++++++ .../cloudcontrol/domain/FirewallRule.java | 6 +- .../cloudcontrol/domain/NatRule.java | 6 +- .../cloudcontrol/domain/PublicIpBlock.java | 6 +- .../cloudcontrol/domain/State.java | 4 + .../functions/BaseImageToHardwareTest.java | 113 +++++++++ .../compute/functions/CleanupServerTest.java | 234 +++++++++++++++++++ .../parse/FirewallRulesParseTest.java | 3 +- .../cloudcontrol/parse/NatRulesParseTest.java | 5 +- .../parse/PublicIpBlocksParseTest.java | 3 +- 11 files changed, 621 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/172d6f34/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/BaseImageToHardware.java ---------------------------------------------------------------------- diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/BaseImageToHardware.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/BaseImageToHardware.java new file mode 100644 index 0000000..15d8468 --- /dev/null +++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/BaseImageToHardware.java @@ -0,0 +1,65 @@ +/* + * 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.dimensiondata.cloudcontrol.compute.functions; + +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.VolumeBuilder; +import org.jclouds.dimensiondata.cloudcontrol.domain.BaseImage; +import org.jclouds.dimensiondata.cloudcontrol.domain.CPU; +import org.jclouds.dimensiondata.cloudcontrol.domain.CpuSpeed; +import org.jclouds.dimensiondata.cloudcontrol.domain.Disk; + +import javax.inject.Singleton; +import java.util.ArrayList; +import java.util.List; + +@Singleton +public class BaseImageToHardware implements Function<BaseImage, Hardware> { + + private static final int GB_TO_MB_MULTIPLIER = 1024; + + @Override + public Hardware apply(final BaseImage from) { + HardwareBuilder builder = new HardwareBuilder().ids(from.id()).name(from.name()).hypervisor("vmx") + .processors(buildProcessorList(from.cpu())).ram(from.memoryGb() * GB_TO_MB_MULTIPLIER); + + if (from.disks() != null) { + builder.volumes(FluentIterable.from(from.disks()).transform(new Function<Disk, Volume>() { + @Override + public Volume apply(final Disk disk) { + return new VolumeBuilder().id(disk.id()).device(String.valueOf(disk.scsiId())) + .size(Float.valueOf(disk.sizeGb())).type(Volume.Type.LOCAL).build(); + } + }).toSet()); + } + return builder.build(); + } + + private List<Processor> buildProcessorList(final CPU cpu) { + final List<Processor> processorList = new ArrayList<Processor>(); + final double speed = CpuSpeed.fromDimensionDataSpeed(cpu.speed()).getSpeed(); + for (int count = 0; count < cpu.count(); count++) { + processorList.add(new Processor(cpu.coresPerSocket(), speed)); + } + return processorList; + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/172d6f34/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/CleanupServer.java ---------------------------------------------------------------------- diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/CleanupServer.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/CleanupServer.java new file mode 100644 index 0000000..cb1f724 --- /dev/null +++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/CleanupServer.java @@ -0,0 +1,189 @@ +/* + * 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.dimensiondata.cloudcontrol.compute.functions; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; +import org.jclouds.dimensiondata.cloudcontrol.DimensionDataCloudControlApi; +import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRule; +import org.jclouds.dimensiondata.cloudcontrol.domain.NatRule; +import org.jclouds.dimensiondata.cloudcontrol.domain.PublicIpBlock; +import org.jclouds.dimensiondata.cloudcontrol.domain.Server; +import org.jclouds.dimensiondata.cloudcontrol.domain.State; +import org.jclouds.dimensiondata.cloudcontrol.features.NetworkApi; +import org.jclouds.dimensiondata.cloudcontrol.features.ServerApi; +import org.jclouds.dimensiondata.cloudcontrol.utils.DimensionDataCloudControlResponseUtils; +import org.jclouds.logging.Logger; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; +import java.util.List; + +import static java.lang.String.format; +import static org.jclouds.dimensiondata.cloudcontrol.utils.DimensionDataCloudControlResponseUtils.generateFirewallRuleName; +import static org.jclouds.dimensiondata.cloudcontrol.utils.DimensionDataCloudControlResponseUtils.waitForServerState; + +@Singleton +public class CleanupServer implements Function<String, Boolean> { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final DimensionDataCloudControlApi api; + private final Timeouts timeouts; + + @Inject + CleanupServer(final DimensionDataCloudControlApi api, final Timeouts timeouts) { + this.api = api; + this.timeouts = timeouts; + } + + @Override + public Boolean apply(final String serverId) { + final ServerApi serverApi = api.getServerApi(); + Server server = serverApi.getServer(serverId); + + if (server == null) { + return true; + } + + if (server.state().isFailed()) { + rollbackOperation(format("Server(%s) not deleted as it is in state(%s).", serverId, server.state())); + } + + if (!server.state().isNormal()) { + return false; + } + + String networkDomainId = server.networkInfo().networkDomainId(); + final String internalIp = server.networkInfo().primaryNic().privateIpv4(); + + // delete nat rules associated to the server, if any + final NetworkApi networkApi = api.getNetworkApi(); + List<NatRule> natRulesToBeDeleted = networkApi.listNatRules(networkDomainId).concat() + .filter(new Predicate<NatRule>() { + @Override + public boolean apply(NatRule natRule) { + return natRule.internalIp().equals(internalIp); + } + }).toList(); + + for (final NatRule natRule : natRulesToBeDeleted) { + + attemptDeleteNatRule(serverId, networkApi, natRule); + + Optional<PublicIpBlock> optionalPublicIpBlock = networkApi.listPublicIPv4AddressBlocks(networkDomainId) + .concat().firstMatch(new Predicate<PublicIpBlock>() { + @Override + public boolean apply(PublicIpBlock input) { + return input.baseIp().equals(natRule.externalIp()); + } + }); + if (optionalPublicIpBlock.isPresent()) { + attemptDeletePublicIpBlock(serverId, networkApi, optionalPublicIpBlock.get()); + } + } + + List<FirewallRule> firewallRulesToBeDeleted = networkApi.listFirewallRules(networkDomainId).concat() + .filter(new Predicate<FirewallRule>() { + @Override + public boolean apply(FirewallRule firewallRule) { + return firewallRule.name().equals(generateFirewallRuleName(serverId)); + } + }).toList(); + + for (FirewallRule firewallRule : firewallRulesToBeDeleted) { + attemptDeleteFirewallRule(serverId, networkApi, firewallRule); + } + + serverApi.powerOffServer(serverId); + String message = format("Server(%s) not terminated within %d ms.", serverId, timeouts.nodeTerminated); + DimensionDataCloudControlResponseUtils + .waitForServerStatus(serverApi, serverId, false, true, timeouts.nodeTerminated, message); + serverApi.deleteServer(serverId); + String deleteFailureMessage = format("Server(%s) not deleted within %d ms.", serverId, timeouts.nodeTerminated); + waitForServerState(serverApi, serverId, State.DELETED, timeouts.nodeTerminated, deleteFailureMessage); + return true; + } + + private void attemptDeleteFirewallRule(final String serverId, final NetworkApi networkApi, + final FirewallRule firewallRule) { + try { + if (firewallRule.state().isNormal()) { + networkApi.deleteFirewallRule(firewallRule.id()); + if (firewallRule.destination() != null && firewallRule.destination().portList() != null) { + try { + networkApi.deletePortList(firewallRule.destination().portList().id()); + } catch (Throwable t) { + logger.warn(t, format( + "Failed to delete PortList(%s) associated with FirewallRule(%s) and with Server(%s). Due to - (%s)", + firewallRule.destination().portList().id(), firewallRule.id(), serverId, t.getMessage())); + } + } + } else { + logger.warn( + format("Server(%s) has an associated FirewallRule(%s) that was not deleted as it is in state(%s).", + serverId, firewallRule.id(), firewallRule.state())); + } + } catch (Throwable t) { + logger.warn(t, + format("Failed to delete FirewallRule(%s) associated with Server(%s). Due to - (%s)", firewallRule.id(), + serverId, t.getMessage())); + } + } + + private void attemptDeletePublicIpBlock(final String serverId, final NetworkApi networkApi, + final PublicIpBlock publicIpBlock) { + try { + if (publicIpBlock.state().isNormal()) { + networkApi.removePublicIpBlock(publicIpBlock.id()); + } else { + logger.warn(format("Server(%s) has an associated IpBlock(%s) that was not deleted as it was in state(%s).", + serverId, publicIpBlock.id(), publicIpBlock.state())); + } + } catch (Throwable t) { + logger.warn(t, + format("Failed to delete IpBlock(%s) associated with Server(%s). Due to - (%s)", publicIpBlock.id(), + serverId, t.getMessage())); + } + } + + private void attemptDeleteNatRule(final String serverId, final NetworkApi networkApi, final NatRule natRule) { + try { + if (natRule.state().isNormal()) { + networkApi.deleteNatRule(natRule.id()); + } else { + logger.warn(format("Server(%s) has an associated NatRule(%s) that was not deleted as it was in state(%s).", + serverId, natRule.id(), natRule.state())); + } + } catch (Throwable t) { + logger.warn(t, + format("Failed to delete NatRule(%s) associated with Server(%s). Due to - (%s)", natRule.id(), serverId, + t.getMessage())); + } + } + + private void rollbackOperation(final String message) { + throw new IllegalStateException(message); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/172d6f34/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/FirewallRule.java ---------------------------------------------------------------------- diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/FirewallRule.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/FirewallRule.java index 70dc884..7ef48e2 100644 --- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/FirewallRule.java +++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/FirewallRule.java @@ -38,7 +38,7 @@ public abstract class FirewallRule { public abstract String networkDomainId(); - public abstract String state(); + public abstract State state(); public abstract String action(); @@ -59,7 +59,7 @@ public abstract class FirewallRule { @SerializedNames({ "id", "name", "ruleType", "networkDomainId", "state", "action", "ipVersion", "protocol", "datacenterId", "source", "destination", "enabled", "placement" }) - public static FirewallRule create(String id, String name, String ruleType, String networkDomainId, String state, + public static FirewallRule create(String id, String name, String ruleType, String networkDomainId, State state, String action, String ipVersion, String protocol, String datacenterId, FirewallRuleTarget source, FirewallRuleTarget destination, Boolean enabled, Placement placement) { return builder().id(id).name(name).ruleType(ruleType).networkDomainId(networkDomainId).state(state).action(action) @@ -79,7 +79,7 @@ public abstract class FirewallRule { public abstract Builder networkDomainId(String networkDomainId); - public abstract Builder state(String state); + public abstract Builder state(State state); public abstract Builder action(String action); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/172d6f34/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/NatRule.java ---------------------------------------------------------------------- diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/NatRule.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/NatRule.java index b1cafb1..4143713 100644 --- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/NatRule.java +++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/NatRule.java @@ -35,7 +35,7 @@ public abstract class NatRule { public abstract String datacenterId(); - public abstract String state(); + public abstract State state(); public abstract Date createTime(); @@ -46,7 +46,7 @@ public abstract class NatRule { public abstract String networkDomainId(); @SerializedNames({ "id", "datacenterId", "state", "createTime", "externalIp", "internalIp", "networkDomainId" }) - public static NatRule create(String id, String datacenterId, String state, Date createTime, String externalIp, + public static NatRule create(String id, String datacenterId, State state, Date createTime, String externalIp, String internalIp, String networkDomainId) { return builder().id(id).datacenterId(datacenterId).datacenterId(datacenterId).state(state).createTime(createTime) .externalIp(externalIp).internalIp(internalIp).networkDomainId(networkDomainId).build(); @@ -60,7 +60,7 @@ public abstract class NatRule { public abstract Builder datacenterId(String datacenterId); - public abstract Builder state(String state); + public abstract Builder state(State state); public abstract Builder createTime(Date createTime); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/172d6f34/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/PublicIpBlock.java ---------------------------------------------------------------------- diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/PublicIpBlock.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/PublicIpBlock.java index 2ee9c78..5c4c613 100644 --- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/PublicIpBlock.java +++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/PublicIpBlock.java @@ -35,7 +35,7 @@ public abstract class PublicIpBlock { public abstract String datacenterId(); - public abstract String state(); + public abstract State state(); public abstract Date createTime(); @@ -46,7 +46,7 @@ public abstract class PublicIpBlock { public abstract String networkDomainId(); @SerializedNames({ "id", "datacenterId", "state", "createTime", "baseIp", "size", "networkDomainId" }) - public static PublicIpBlock create(String id, String datacenterId, String state, Date createTime, String baseIp, + public static PublicIpBlock create(String id, String datacenterId, State state, Date createTime, String baseIp, int size, String networkDomainId) { return builder().id(id).datacenterId(datacenterId).state(state).createTime(createTime).baseIp(baseIp).size(size) .networkDomainId(networkDomainId).build(); @@ -60,7 +60,7 @@ public abstract class PublicIpBlock { public abstract Builder datacenterId(String datacenterId); - public abstract Builder state(String state); + public abstract Builder state(State state); public abstract Builder createTime(Date createTime); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/172d6f34/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/State.java ---------------------------------------------------------------------- diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/State.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/State.java index 37ff17d..cece134 100644 --- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/State.java +++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/State.java @@ -40,4 +40,8 @@ public enum State { public boolean isFailed() { return this == FAILED_ADD || this == FAILED_CHANGE || this == FAILED_DELETE; } + + public boolean isNormal() { + return this == NORMAL; + } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/172d6f34/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/BaseImageToHardwareTest.java ---------------------------------------------------------------------- diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/BaseImageToHardwareTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/BaseImageToHardwareTest.java new file mode 100644 index 0000000..bc09d1c --- /dev/null +++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/BaseImageToHardwareTest.java @@ -0,0 +1,113 @@ +/* + * 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.dimensiondata.cloudcontrol.compute.functions; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Volume; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.dimensiondata.cloudcontrol.domain.BaseImage; +import org.jclouds.dimensiondata.cloudcontrol.domain.CPU; +import org.jclouds.dimensiondata.cloudcontrol.domain.Cluster; +import org.jclouds.dimensiondata.cloudcontrol.domain.CpuSpeed; +import org.jclouds.dimensiondata.cloudcontrol.domain.CustomerImage; +import org.jclouds.dimensiondata.cloudcontrol.domain.Disk; +import org.jclouds.dimensiondata.cloudcontrol.domain.Guest; +import org.jclouds.dimensiondata.cloudcontrol.domain.ImageNic; +import org.jclouds.dimensiondata.cloudcontrol.domain.OperatingSystem; +import org.jclouds.dimensiondata.cloudcontrol.domain.OsImage; +import org.jclouds.dimensiondata.cloudcontrol.domain.VirtualHardware; +import org.jclouds.dimensiondata.cloudcontrol.domain.VmTools; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import javax.xml.bind.DatatypeConverter; + +import static org.testng.AssertJUnit.assertEquals; + +@Test(groups = "unit", testName = "ImageDescriptionToOsFamilyTest") +public class BaseImageToHardwareTest { + + private BaseImageToHardware baseImageToHardware; + + @BeforeMethod + public void setUp() throws Exception { + baseImageToHardware = new BaseImageToHardware(); + } + + @Test + public void testApply_OsImage() throws Exception { + final OsImage osImage = OsImage.builder().id("12ea8472-6e4e-4068-b2cb-f04ecacd3962").name("CentOS 5 64-bit") + .description("DRaaS CentOS Release 5.9 64-bit").guest(Guest.builder().osCustomization(false) + .operatingSystem( + OperatingSystem.builder().id("CENTOS564").displayName("CENTOS5/64").family("UNIX").build()) + .build()).cpu(CPU.builder().count(1).speed("STANDARD").coresPerSocket(1).build()).memoryGb(4) + .nics(ImmutableList.of(ImageNic.builder().networkAdapter("E1000").key(4040).build())).disks(ImmutableList + .of(Disk.builder().id("98299851-37a3-4ebe-9cf1-090da9ae42a0").scsiId(0).sizeGb(20).speed("STANDARD") + .build())).softwareLabels(Lists.<String>newArrayList()).osImageKey("T-CENT-5-64-2-4-10") + .createTime(DatatypeConverter.parseDateTime("2016-06-09T17:36:31.000Z").getTime()).datacenterId("EU6") + .cluster(Cluster.builder().id("EU6-01").name("my cluster name").build()).build(); + applyAndAssert(osImage); + + } + + private void applyAndAssert(BaseImage baseImage) { + final Hardware hardware = baseImageToHardware.apply(baseImage); + assertEquals(baseImage.memoryGb() * 1024, hardware.getRam()); + assertEquals("vmx", hardware.getHypervisor()); + assertEquals(baseImage.id(), hardware.getId()); + assertEquals(baseImage.id(), hardware.getProviderId()); + assertEquals(baseImage.name(), hardware.getName()); + assertEquals(baseImage.disks().size(), hardware.getVolumes().size()); + assertEquals(Float.valueOf(baseImage.disks().get(0).sizeGb()), hardware.getVolumes().get(0).getSize()); + assertEquals(Volume.Type.LOCAL, hardware.getVolumes().get(0).getType()); + assertEquals(baseImage.disks().get(0).id(), hardware.getVolumes().get(0).getId()); + assertEquals(baseImage.disks().get(0).scsiId().toString(), hardware.getVolumes().get(0).getDevice()); + assertEquals(baseImage.cpu().count(), hardware.getProcessors().size()); + assertEquals(Double.valueOf(baseImage.cpu().coresPerSocket()), hardware.getProcessors().get(0).getCores()); + assertEquals(CpuSpeed.STANDARD.getSpeed(), hardware.getProcessors().get(0).getSpeed()); + } + + @Test + public void testApply_CustomerImage() throws Exception { + CustomerImage customerImage = CustomerImage.builder().id("f27b7ead-9cdc-4cee-be50-8f8e6cec8534") + .name("CloneForDrs").cluster(Cluster.builder().id("QA1_N2_VMWARE_1-01").name("QA1_N2_VMWARE_1-01").build()) + .cpu(CPU.builder().count(1).speed("STANDARD").coresPerSocket(1).build()).memoryGb(4).disks(ImmutableList + .of(Disk.builder().id("1bddd4ed-67dc-4e5e-a0d5-b5a6c012ec14").scsiId(0).sizeGb(50) + .speed("HIGHPERFORMANCE").build())) + .createTime(new SimpleDateFormatDateService().iso8601DateParse("2016-07-17T23:53:48.000Z")) + .datacenterId("QA1_N2_VMWARE_1").state("FAILED_ADD").guest(Guest.builder().operatingSystem( + OperatingSystem.builder().id("WIN2012DC64").displayName("WIN2012DC/64").family("WINDOWS").build()) + .vmTools(VmTools.builder().versionStatus(VmTools.VersionStatus.CURRENT) + .runningStatus(VmTools.RunningStatus.NOT_RUNNING).apiVersion(9354) + .type(VmTools.Type.VMWARE_TOOLS).build()).osCustomization(true).build()) + .virtualHardware(VirtualHardware.builder().version("vmx-08").upToDate(false).build()).tags(ImmutableList + .of(CustomerImage.TagWithIdAndName.builder().tagKeyName("DdTest3") + .tagKeyId("ee58176e-305b-4ec2-85e0-330a33729a94").build(), + CustomerImage.TagWithIdAndName.builder().tagKeyName("Lukas11") + .tagKeyId("c5480364-d3cd-4391-9536-5c1af683a8f1").value("j").build(), + CustomerImage.TagWithIdAndName.builder().tagKeyName("Lukas5") + .tagKeyId("a3e869df-6427-404f-99c2-b50f526369aa").build())) + .softwareLabels(ImmutableList.<String>of()).nics(ImmutableList.<ImageNic>of()).source( + CustomerImage.Source.builder().artifacts(ImmutableList + .of(CustomerImage.Artifact.builder().value("cb4b8674-09a4-4194-9593-9cdc81489de1") + .type(CustomerImage.Artifact.Type.SERVER_ID).build())) + .type(CustomerImage.Source.Type.CLONE).build()).build(); + applyAndAssert(customerImage); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/172d6f34/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/CleanupServerTest.java ---------------------------------------------------------------------- diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/CleanupServerTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/CleanupServerTest.java new file mode 100644 index 0000000..582628f --- /dev/null +++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/compute/functions/CleanupServerTest.java @@ -0,0 +1,234 @@ +/* + * 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.dimensiondata.cloudcontrol.compute.functions; + +import com.google.common.collect.Lists; +import org.easymock.EasyMock; +import org.easymock.EasyMockSupport; +import org.jclouds.collect.IterableWithMarkers; +import org.jclouds.collect.PagedIterables; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.dimensiondata.cloudcontrol.DimensionDataCloudControlApi; +import org.jclouds.dimensiondata.cloudcontrol.domain.CPU; +import org.jclouds.dimensiondata.cloudcontrol.domain.CpuSpeed; +import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRule; +import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRuleTarget; +import org.jclouds.dimensiondata.cloudcontrol.domain.Guest; +import org.jclouds.dimensiondata.cloudcontrol.domain.NIC; +import org.jclouds.dimensiondata.cloudcontrol.domain.NatRule; +import org.jclouds.dimensiondata.cloudcontrol.domain.NetworkInfo; +import org.jclouds.dimensiondata.cloudcontrol.domain.OperatingSystem; +import org.jclouds.dimensiondata.cloudcontrol.domain.PublicIpBlock; +import org.jclouds.dimensiondata.cloudcontrol.domain.Server; +import org.jclouds.dimensiondata.cloudcontrol.domain.State; +import org.jclouds.dimensiondata.cloudcontrol.domain.VmTools; +import org.jclouds.dimensiondata.cloudcontrol.features.NetworkApi; +import org.jclouds.dimensiondata.cloudcontrol.features.ServerApi; +import org.jclouds.dimensiondata.cloudcontrol.utils.DimensionDataCloudControlResponseUtils; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.util.Date; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; + +@Test(groups = "unit", testName = "CleanupServerTest") +public class CleanupServerTest { + + private CleanupServer cleanupServer; + private DimensionDataCloudControlApi api; + private ServerApi serverApi; + private NetworkApi networkApi; + private final String serverId = "serverId"; + private final String jcloudsNetworkDomainId = "jcloudsNetworkDomainId"; + private Server.Builder serverBuilder; + private String internalIp; + private NatRule.Builder natRuleBuilder; + private PublicIpBlock.Builder publicIpBlockBuilder; + private FirewallRule.Builder firewallRuleBuilder; + + @BeforeMethod + public void setUp() throws Exception { + serverApi = EasyMock.createMock(ServerApi.class); + networkApi = EasyMock.createMock(NetworkApi.class); + api = EasyMock.createMock(DimensionDataCloudControlApi.class); + + internalIp = "172.0.0.1"; + final String datacenterId = "EU10"; + serverBuilder = Server.builder().id(serverId).name("jclouds server").memoryGb(10) + .cpu(CPU.builder().count(1).coresPerSocket(2).speed(CpuSpeed.STANDARD.getDimensionDataSpeed()).build()) + .datacenterId(datacenterId).deployed(true).started(true).description("jclouds server") + .sourceImageId("sourceImageId").createTime(new Date()).guest(Guest.builder().operatingSystem( + OperatingSystem.builder().id("WIN2012DC64").displayName("WIN2012DC/64").family("WINDOWS").build()) + .vmTools(VmTools.builder().versionStatus(VmTools.VersionStatus.CURRENT) + .runningStatus(VmTools.RunningStatus.NOT_RUNNING).apiVersion(9354) + .type(VmTools.Type.VMWARE_TOOLS).build()).osCustomization(true).build()).networkInfo( + NetworkInfo.builder().networkDomainId(jcloudsNetworkDomainId) + .primaryNic(NIC.builder().vlanId("vlanId").privateIpv4(internalIp).build()) + .additionalNic(Lists.<NIC>newArrayList()).build()); + + final String externalIp = "externalIp"; + natRuleBuilder = NatRule.builder().id("natRuleId").internalIp(internalIp).networkDomainId(jcloudsNetworkDomainId) + .datacenterId(datacenterId).createTime(new Date()).externalIp(externalIp); + publicIpBlockBuilder = PublicIpBlock.builder().id("publicIpBlockId").baseIp(externalIp).datacenterId(datacenterId) + .networkDomainId(jcloudsNetworkDomainId).createTime(new Date()).size(2); + firewallRuleBuilder = FirewallRule.builder().id("firewallRuleId").networkDomainId(jcloudsNetworkDomainId) + .datacenterId(datacenterId).ruleType("ruleType").action("action").ipVersion("ipVersion") + .source(FirewallRuleTarget.builder().build()).enabled(false) + .name(DimensionDataCloudControlResponseUtils.generateFirewallRuleName(serverId)).protocol("protocol"); + + EasyMockSupport.injectMocks(api); + EasyMockSupport.injectMocks(serverApi); + EasyMockSupport.injectMocks(networkApi); + } + + @Test + public void testApply_ServerAndNetworkingDeleted() throws Exception { + final Server server = serverBuilder.state(State.NORMAL).build(); + loadServerExpectations(server); + networkApiExpectations(); + natRuleExpectations(); + publicIpBlockExpectations(); + firewallRuleAndPortListExpectations(); + powerOffAndDeleteServerExpectations(); + applyAndAssertDeleted(); + } + + private void powerOffAndDeleteServerExpectations() { + serverApi.powerOffServer(serverId); + expectLastCall(); + final Server poweredOffServer = serverBuilder.state(State.NORMAL).started(false).build(); + expect(serverApi.getServer(serverId)).andReturn(poweredOffServer); + serverApi.deleteServer(serverId); + expectLastCall(); + expect(serverApi.getServer(serverId)).andReturn(null); + } + + private void applyAndAssertDeleted() { + replay(serverApi, networkApi, api); + cleanupServer = new CleanupServer(api, new ComputeServiceConstants.Timeouts()); + assertTrue(cleanupServer.apply(serverId)); + } + + @Test(dependsOnMethods = "testApply_ServerAndNetworkingDeleted") + public void testApply_ServerNotInNormalState() throws Exception { + final Server server = serverBuilder.state(State.FAILED_ADD).build(); + loadServerExpectations(server); + replay(api, serverApi, networkApi); + cleanupServer = new CleanupServer(api, new ComputeServiceConstants.Timeouts()); + applyWithExpectedErrorMessage("Server(serverId) not deleted as it is in state(FailedAdd)."); + } + + @Test(dependsOnMethods = "testApply_ServerNotInNormalState") + public void testApply_NatRuleNotInNormalState() throws Exception { + final Server server = serverBuilder.state(State.NORMAL).build(); + loadServerExpectations(server); + networkApiExpectations(); + + final NatRule natRule = natRuleBuilder.state(State.FAILED_ADD).build(); + expect(networkApi.listNatRules(jcloudsNetworkDomainId)) + .andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.newArrayList(natRule)))); + + publicIpBlockExpectations(); + firewallRuleAndPortListExpectations(); + powerOffAndDeleteServerExpectations(); + applyAndAssertDeleted(); + } + + @Test(dependsOnMethods = "testApply_NatRuleNotInNormalState") + public void testApply_PublicIpBlockNotInNormalState() throws Exception { + final Server server = serverBuilder.state(State.NORMAL).build(); + loadServerExpectations(server); + networkApiExpectations(); + natRuleExpectations(); + + final PublicIpBlock publicIpBlock = publicIpBlockBuilder.state(State.FAILED_CHANGE).build(); + expect(networkApi.listPublicIPv4AddressBlocks(jcloudsNetworkDomainId)) + .andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.newArrayList(publicIpBlock)))); + + firewallRuleAndPortListExpectations(); + powerOffAndDeleteServerExpectations(); + applyAndAssertDeleted(); + } + + @Test(dependsOnMethods = "testApply_PublicIpBlockNotInNormalState") + public void testApply_FirewallRuleNotInNormalState() throws Exception { + final Server server = serverBuilder.state(State.NORMAL).build(); + loadServerExpectations(server); + networkApiExpectations(); + natRuleExpectations(); + publicIpBlockExpectations(); + + final FirewallRule firewallRule = firewallRuleBuilder.state(State.FAILED_CHANGE).destination( + FirewallRuleTarget.builder() + .portList(FirewallRuleTarget.PortList.create("portListId", null, null, null, null)).build()).build(); + expect(networkApi.listFirewallRules(jcloudsNetworkDomainId)) + .andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.newArrayList(firewallRule)))); + + powerOffAndDeleteServerExpectations(); + applyAndAssertDeleted(); + } + + private void firewallRuleAndPortListExpectations() { + final FirewallRule firewallRule = firewallRuleBuilder.state(State.NORMAL).destination(FirewallRuleTarget.builder() + .portList(FirewallRuleTarget.PortList.create("portListId", null, null, null, null)).build()).build(); + expect(networkApi.listFirewallRules(jcloudsNetworkDomainId)) + .andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.newArrayList(firewallRule)))); + networkApi.deleteFirewallRule(firewallRule.id()); + expectLastCall(); + networkApi.deletePortList(firewallRule.destination().portList().id()); + expectLastCall(); + } + + private void publicIpBlockExpectations() { + final PublicIpBlock publicIpBlock = publicIpBlockBuilder.state(State.NORMAL).build(); + expect(networkApi.listPublicIPv4AddressBlocks(jcloudsNetworkDomainId)) + .andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.newArrayList(publicIpBlock)))); + networkApi.removePublicIpBlock(publicIpBlock.id()); + expectLastCall(); + } + + private void natRuleExpectations() { + final NatRule natRule = natRuleBuilder.state(State.NORMAL).build(); + expect(networkApi.listNatRules(jcloudsNetworkDomainId)) + .andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.newArrayList(natRule)))); + networkApi.deleteNatRule(natRule.id()); + expectLastCall(); + } + + private void loadServerExpectations(Server server) { + expect(api.getServerApi()).andReturn(serverApi); + expect(serverApi.getServer(serverId)).andReturn(server); + } + + private void applyWithExpectedErrorMessage(String expectedErrorMessage) { + try { + cleanupServer.apply(serverId); + } catch (IllegalStateException e) { + assertEquals(expectedErrorMessage, e.getMessage()); + } + } + + private void networkApiExpectations() { + expect(api.getNetworkApi()).andReturn(networkApi); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/172d6f34/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/FirewallRulesParseTest.java ---------------------------------------------------------------------- diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/FirewallRulesParseTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/FirewallRulesParseTest.java index 2fe920c..71b62bb 100644 --- a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/FirewallRulesParseTest.java +++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/FirewallRulesParseTest.java @@ -21,6 +21,7 @@ import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRule; import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRuleTarget; import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRules; import org.jclouds.dimensiondata.cloudcontrol.domain.IpRange; +import org.jclouds.dimensiondata.cloudcontrol.domain.State; import org.jclouds.dimensiondata.cloudcontrol.internal.BaseDimensionDataCloudControlParseTest; import org.testng.annotations.Test; @@ -41,7 +42,7 @@ public class FirewallRulesParseTest extends BaseDimensionDataCloudControlParseTe public FirewallRules expected() { List<FirewallRule> firewallRules = ImmutableList .of(FirewallRule.builder().id("1aa3d0ce-d95d-4296-8338-9717e0d37ff9") - .name("CCDEFAULT.BlockOutboundMailIPv6Secure").state("NORMAL").action("DROP").ipVersion("IPV6") + .name("CCDEFAULT.BlockOutboundMailIPv6Secure").state(State.NORMAL).action("DROP").ipVersion("IPV6") .protocol("TCP").source(FirewallRuleTarget.builder().ip(IpRange.create("ANY", null)).build()) .destination(FirewallRuleTarget.builder().ip(IpRange.create("ANY", null)) .port(FirewallRuleTarget.Port.create(587, null)).build()).ruleType("DEFAULT_RULE") http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/172d6f34/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/NatRulesParseTest.java ---------------------------------------------------------------------- diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/NatRulesParseTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/NatRulesParseTest.java index 7858a0e..ac611dc 100644 --- a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/NatRulesParseTest.java +++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/NatRulesParseTest.java @@ -19,6 +19,7 @@ package org.jclouds.dimensiondata.cloudcontrol.parse; import com.google.common.collect.ImmutableList; import org.jclouds.dimensiondata.cloudcontrol.domain.NatRule; import org.jclouds.dimensiondata.cloudcontrol.domain.NatRules; +import org.jclouds.dimensiondata.cloudcontrol.domain.State; import org.jclouds.dimensiondata.cloudcontrol.internal.BaseDimensionDataCloudControlParseTest; import org.testng.annotations.Test; @@ -38,10 +39,10 @@ public class NatRulesParseTest extends BaseDimensionDataCloudControlParseTest<Na @Consumes(MediaType.APPLICATION_JSON) public NatRules expected() { List<NatRule> natRules = ImmutableList.of(NatRule.builder().id("2187a636-7ebb-49a1-a2ff-5d617f496dce") - .createTime(parseDate("2015-03-06T13:43:45.000Z")).state("NORMAL").externalIp("165.180.12.18") + .createTime(parseDate("2015-03-06T13:43:45.000Z")).state(State.NORMAL).externalIp("165.180.12.18") .internalIp("10.0.0.15").networkDomainId("484174a2-ae74-4658-9e56-50fc90e086cf").datacenterId("NA9") .build(), NatRule.builder().id("2169a38e-5692-497e-a22a-701a838a6539") - .createTime(parseDate("2015-03-06T13:45:10.000Z")).state("NORMAL").externalIp("165.180.12.19") + .createTime(parseDate("2015-03-06T13:45:10.000Z")).state(State.NORMAL).externalIp("165.180.12.19") .internalIp("10.0.0.16").networkDomainId("484174a2-ae74-4658-9e56-50fc90e086cf").datacenterId("NA9") .build()); return new NatRules(natRules, 1, 2, 2, 250); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/172d6f34/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/PublicIpBlocksParseTest.java ---------------------------------------------------------------------- diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/PublicIpBlocksParseTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/PublicIpBlocksParseTest.java index 97c9512..5a9e5a9 100644 --- a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/PublicIpBlocksParseTest.java +++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/PublicIpBlocksParseTest.java @@ -19,6 +19,7 @@ package org.jclouds.dimensiondata.cloudcontrol.parse; import com.google.common.collect.ImmutableList; import org.jclouds.dimensiondata.cloudcontrol.domain.PublicIpBlock; import org.jclouds.dimensiondata.cloudcontrol.domain.PublicIpBlocks; +import org.jclouds.dimensiondata.cloudcontrol.domain.State; import org.jclouds.dimensiondata.cloudcontrol.internal.BaseDimensionDataCloudControlParseTest; import org.testng.annotations.Test; @@ -40,7 +41,7 @@ public class PublicIpBlocksParseTest extends BaseDimensionDataCloudControlParseT List<PublicIpBlock> publicIpBlocks = ImmutableList .of(PublicIpBlock.builder().networkDomainId("690de302-bb80-49c6-b401-8c02bbefb945") .id("9993e5fc-bdce-11e4-8c14-b8ca3a5d9ef8").createTime(parseDate("2016-03-14T11:49:33.000Z")) - .state("NORMAL").datacenterId("NA9").size(2).baseIp("168.128.6.216").build()); + .state(State.NORMAL).datacenterId("NA9").size(2).baseIp("168.128.6.216").build()); return new PublicIpBlocks(publicIpBlocks, 1, 5, 5, 250); } }
