Issue 282: added suspend/resume

This commit is contained in:
Adrian Cole 2010-10-30 21:53:32 -07:00
parent 3321d8bcf6
commit a45532f05c
12 changed files with 742 additions and 0 deletions

View File

@ -0,0 +1,57 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.aws.ec2.compute.strategy;
import static org.jclouds.aws.ec2.util.EC2Utils.parseHandle;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.services.InstanceClient;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
/**
*
* @author Adrian Cole
*/
@Singleton
public class EC2ResumeNodeStrategy implements ResumeNodeStrategy {
private final InstanceClient client;
private final GetNodeMetadataStrategy getNode;
@Inject
protected EC2ResumeNodeStrategy(EC2Client client, GetNodeMetadataStrategy getNode) {
this.client = client.getInstanceServices();
this.getNode = getNode;
}
@Override
public NodeMetadata resumeNode(String id) {
String[] parts = parseHandle(id);
String region = parts[0];
String instanceId = parts[1];
client.startInstancesInRegion(region, instanceId);
return getNode.getNode(id);
}
}

View File

@ -0,0 +1,57 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.aws.ec2.compute.strategy;
import static org.jclouds.aws.ec2.util.EC2Utils.parseHandle;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.services.InstanceClient;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
/**
*
* @author Adrian Cole
*/
@Singleton
public class EC2SuspendNodeStrategy implements SuspendNodeStrategy {
private final InstanceClient client;
private final GetNodeMetadataStrategy getNode;
@Inject
protected EC2SuspendNodeStrategy(EC2Client client, GetNodeMetadataStrategy getNode) {
this.client = client.getInstanceServices();
this.getNode = getNode;
}
@Override
public NodeMetadata suspendNode(String id) {
String[] parts = parseHandle(id);
String region = parts[0];
String instanceId = parts[1];
client.stopInstancesInRegion(region, true, instanceId);
return getNode.getNode(id);
}
}

View File

@ -0,0 +1,70 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.compute.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.inject.Inject;
/**
*
* Tests to see if a node is active.
*
* @author Adrian Cole
*/
@Singleton
public class NodePresentAndInIntendedState implements Predicate<NodeMetadata> {
private final ComputeService client;
private final NodeState intended;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public NodePresentAndInIntendedState(NodeState intended, ComputeService client) {
this.intended = intended;
this.client = client;
}
public boolean apply(NodeMetadata node) {
logger.trace("looking for state on node %s", checkNotNull(node, "node"));
node = refresh(node);
if (node == null)
return false;
logger.trace("%s: looking for node state %s: currently: %s", node.getId(), intended, node.getState());
if (node.getState() == NodeState.ERROR)
throw new IllegalStateException("node " + node.getId() + " in location " + node.getLocation()
+ " is in error state");
return node.getState() == intended;
}
private NodeMetadata refresh(NodeMetadata node) {
return client.getNodeMetadata(node.getId());
}
}

View File

@ -0,0 +1,42 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.compute.predicates;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.NodeState;
import com.google.inject.Inject;
/**
*
* Tests to see if a node is suspended.
*
* @author Adrian Cole
*/
@Singleton
public class NodeSuspended extends NodePresentAndInIntendedState {
@Inject
public NodeSuspended(ComputeService client) {
super(NodeState.SUSPENDED, client);
}
}

View File

@ -0,0 +1,33 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.compute.strategy;
import org.jclouds.compute.domain.NodeMetadata;
/**
* Resumes a node from the state {@link org.jclouds.compute.domain.NodeState#SUSPENDED suspended}
*
* @author Adrian Cole
*/
public interface ResumeNodeStrategy {
NodeMetadata resumeNode(String id);
}

View File

@ -0,0 +1,33 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.compute.strategy;
import org.jclouds.compute.domain.NodeMetadata;
/**
* Reboots a node unless it is in the state {@link org.jclouds.compute.domain.NodeState#SUSPENDED suspended}
*
* @author Adrian Cole
*/
public interface SuspendNodeStrategy {
NodeMetadata suspendNode(String id);
}

View File

@ -0,0 +1,88 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.gogrid.compute.strategy;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.gogrid.GoGridClient;
import org.jclouds.gogrid.domain.PowerCommand;
import org.jclouds.gogrid.domain.Server;
import org.jclouds.gogrid.predicates.ServerLatestJobCompleted;
import org.jclouds.predicates.RetryablePredicate;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*/
@Singleton
public class GoGridLifeCycleStrategy implements RebootNodeStrategy, ResumeNodeStrategy, SuspendNodeStrategy {
private final GoGridClient client;
private final RetryablePredicate<Server> serverLatestJobCompleted;
private final RetryablePredicate<Server> serverLatestJobCompletedShort;
private final GetNodeMetadataStrategy getNode;
@Inject
protected GoGridLifeCycleStrategy(GoGridClient client, GetNodeMetadataStrategy getNode, Timeouts timeouts) {
this.client = client;
this.serverLatestJobCompleted = new RetryablePredicate<Server>(new ServerLatestJobCompleted(client
.getJobServices()), timeouts.nodeRunning * 9l / 10l);
this.serverLatestJobCompletedShort = new RetryablePredicate<Server>(new ServerLatestJobCompleted(client
.getJobServices()), timeouts.nodeRunning * 1l / 10l);
this.getNode = getNode;
}
@Override
public NodeMetadata rebootNode(String id) {
executeCommandOnServer(PowerCommand.RESTART, id);
Server server = Iterables.getOnlyElement(client.getServerServices().getServersById(new Long(id)));
client.getServerServices().power(server.getName(), PowerCommand.START);
serverLatestJobCompletedShort.apply(server);
return getNode.getNode(id);
}
@Override
public NodeMetadata resumeNode(String id) {
executeCommandOnServer(PowerCommand.START, id);
return getNode.getNode(id);
}
@Override
public NodeMetadata suspendNode(String id) {
executeCommandOnServer(PowerCommand.STOP, id);
return getNode.getNode(id);
}
private boolean executeCommandOnServer(PowerCommand command, String id) {
Server server = Iterables.getOnlyElement(client.getServerServices().getServersById(new Long(id)));
client.getServerServices().power(server.getName(), command);
return serverLatestJobCompleted.apply(server);
}
}

View File

@ -0,0 +1,65 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.rackspace.cloudservers.compute.strategy;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.rackspace.cloudservers.CloudServersClient;
import org.jclouds.rackspace.cloudservers.domain.RebootType;
/**
* @author Adrian Cole
*/
@Singleton
public class CloudServersLifeCycleStrategy implements RebootNodeStrategy, SuspendNodeStrategy, ResumeNodeStrategy {
private final CloudServersClient client;
private final GetNodeMetadataStrategy getNode;
@Inject
protected CloudServersLifeCycleStrategy(CloudServersClient client, GetNodeMetadataStrategy getNode) {
this.client = client;
this.getNode = getNode;
}
@Override
public NodeMetadata rebootNode(String id) {
int serverId = Integer.parseInt(id);
// if false server wasn't around in the first place
client.rebootServer(serverId, RebootType.HARD);
return getNode.getNode(id);
}
@Override
public NodeMetadata suspendNode(String id) {
throw new UnsupportedOperationException("suspend not supported");
}
@Override
public NodeMetadata resumeNode(String id) {
throw new UnsupportedOperationException("resume not supported");
}
}

View File

@ -0,0 +1,65 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.rimuhosting.miro.compute.strategy;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.rimuhosting.miro.RimuHostingClient;
/**
*
* @author Adrian Cole
*/
@Singleton
public class RimuHostingLifeCycleStrategy implements RebootNodeStrategy, SuspendNodeStrategy, ResumeNodeStrategy {
private final RimuHostingClient client;
private final GetNodeMetadataStrategy getNode;
@Inject
protected RimuHostingLifeCycleStrategy(RimuHostingClient client, GetNodeMetadataStrategy getNode) {
this.client = client;
this.getNode = getNode;
}
@Override
public NodeMetadata rebootNode(String id) {
Long serverId = Long.parseLong(id);
// if false server wasn't around in the first place
client.restartServer(serverId).getState();
return getNode.getNode(id);
}
@Override
public NodeMetadata suspendNode(String id) {
throw new UnsupportedOperationException("suspend not supported");
}
@Override
public NodeMetadata resumeNode(String id) {
throw new UnsupportedOperationException("resume not supported");
}
}

View File

@ -0,0 +1,64 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.slicehost.compute.strategy;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.slicehost.SlicehostClient;
/**
*
* @author Adrian Cole
*/
@Singleton
public class SlicehostLifeCycleStrategy implements RebootNodeStrategy, SuspendNodeStrategy, ResumeNodeStrategy {
private final SlicehostClient client;
private final GetNodeMetadataStrategy getNode;
@Inject
protected SlicehostLifeCycleStrategy(SlicehostClient client, GetNodeMetadataStrategy getNode) {
this.client = client;
this.getNode = getNode;
}
@Override
public NodeMetadata rebootNode(String id) {
int sliceId = Integer.parseInt(id);
client.hardRebootSlice(sliceId);
return getNode.getNode(id);
}
@Override
public NodeMetadata suspendNode(String id) {
throw new UnsupportedOperationException("suspend not supported");
}
@Override
public NodeMetadata resumeNode(String id) {
throw new UnsupportedOperationException("resume not supported");
}
}

View File

@ -0,0 +1,87 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.vcloud.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.VCloudExpressClient;
import org.jclouds.vcloud.domain.Task;
import com.google.common.base.Predicate;
/**
* @author Adrian Cole
*/
@Singleton
public class VCloudExpressLifeCycleStrategy implements RebootNodeStrategy, ResumeNodeStrategy, SuspendNodeStrategy {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final VCloudExpressClient client;
protected final Predicate<URI> taskTester;
protected final GetNodeMetadataStrategy getNode;
@Inject
protected VCloudExpressLifeCycleStrategy(VCloudExpressClient client, Predicate<URI> taskTester,
GetNodeMetadataStrategy getNode) {
this.client = client;
this.taskTester = taskTester;
this.getNode = getNode;
}
@Override
public NodeMetadata rebootNode(String in) {
Task task = client.resetVApp(URI.create(checkNotNull(in, "node.id")));
return returnWhenTaskCompletes(in, task);
}
private NodeMetadata returnWhenTaskCompletes(String in, Task task) {
taskTester.apply(task.getHref());
return getNode.getNode(in);
}
@Override
public NodeMetadata resumeNode(String in) {
Task task = client.powerOnVApp(URI.create(checkNotNull(in, "node.id")));
return returnWhenTaskCompletes(in, task);
}
@Override
public NodeMetadata suspendNode(String in) {
Task task = client.powerOffVApp(URI.create(checkNotNull(in, "node.id")));
return returnWhenTaskCompletes(in, task);
}
}

View File

@ -0,0 +1,81 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.vcloud.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.domain.Task;
import com.google.common.base.Predicate;
/**
* @author Adrian Cole
*/
@Singleton
public class VCloudLifeCycleStrategy implements RebootNodeStrategy, ResumeNodeStrategy, SuspendNodeStrategy {
@Resource
private final VCloudClient client;
protected final Predicate<URI> taskTester;
protected final GetNodeMetadataStrategy getNode;
@Inject
protected VCloudLifeCycleStrategy(VCloudClient client, Predicate<URI> taskTester,
GetNodeMetadataStrategy getNode) {
this.client = client;
this.taskTester = taskTester;
this.getNode = getNode;
}
@Override
public NodeMetadata rebootNode(String in) {
URI id = URI.create(checkNotNull(in, "node.id"));
Task task = client.resetVAppOrVm(id);
return returnWhenTaskCompletes(in, task);
}
private NodeMetadata returnWhenTaskCompletes(String in, Task task) {
taskTester.apply(task.getHref());
return getNode.getNode(in);
}
@Override
public NodeMetadata resumeNode(String in) {
Task task = client.powerOnVAppOrVm(URI.create(checkNotNull(in, "node.id")));
return returnWhenTaskCompletes(in, task);
}
@Override
public NodeMetadata suspendNode(String in) {
Task task = client.powerOffVAppOrVm(URI.create(checkNotNull(in, "node.id")));
return returnWhenTaskCompletes(in, task);
}
}