Skip to content
Permalink
Browse files
Implementing BaseImageToHardware and CleanupServer functions.
  • Loading branch information
trevorflanagan authored and nacx committed Dec 5, 2017
1 parent 2b8bfcb commit 172d6f34960dd1389ded5884922f81dfc494f96e
Showing 11 changed files with 621 additions and 13 deletions.
@@ -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;
}
}
@@ -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);
}
}
@@ -38,7 +38,7 @@ public static Builder builder() {

public abstract String networkDomainId();

public abstract String state();
public abstract State state();

public abstract String action();

@@ -59,7 +59,7 @@ public static Builder builder() {

@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 static class Builder {

public abstract Builder networkDomainId(String networkDomainId);

public abstract Builder state(String state);
public abstract Builder state(State state);

public abstract Builder action(String action);

@@ -35,7 +35,7 @@ public static Builder builder() {

public abstract String datacenterId();

public abstract String state();
public abstract State state();

public abstract Date createTime();

@@ -46,7 +46,7 @@ public static Builder builder() {
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 static class Builder {

public abstract Builder datacenterId(String datacenterId);

public abstract Builder state(String state);
public abstract Builder state(State state);

public abstract Builder createTime(Date createTime);

@@ -35,7 +35,7 @@ public static Builder builder() {

public abstract String datacenterId();

public abstract String state();
public abstract State state();

public abstract Date createTime();

@@ -46,7 +46,7 @@ public static Builder builder() {
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 static class Builder {

public abstract Builder datacenterId(String datacenterId);

public abstract Builder state(String state);
public abstract Builder state(State state);

public abstract Builder createTime(Date createTime);

@@ -40,4 +40,8 @@ public static State fromValue(String state) {
public boolean isFailed() {
return this == FAILED_ADD || this == FAILED_CHANGE || this == FAILED_DELETE;
}

public boolean isNormal() {
return this == NORMAL;
}
}

0 comments on commit 172d6f3

Please sign in to comment.