/**
* 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.apache.camel.component.jclouds;
import java.util.Set;
import com.google.common.base.Predicate;
import org.apache.camel.CamelException;
import org.apache.camel.Exchange;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.domain.LoginCredentials;
public class JcloudsComputeProducer extends JcloudsProducer {
private final ComputeService computeService;
public JcloudsComputeProducer(JcloudsEndpoint endpoint, ComputeService computeService) {
super(endpoint);
this.computeService = computeService;
}
@Override
public JcloudsComputeEndpoint getEndpoint() {
return (JcloudsComputeEndpoint)super.getEndpoint();
}
@Override
public void process(Exchange exchange) throws Exception {
String operation = getOperation(exchange);
if (operation == null) {
throw new CamelException("Operation must be specified in the endpoitn URI or as a property on the exchange.");
}
if (JcloudsConstants.LIST_NODES.equals(operation)) {
listNodes(exchange);
} else if (JcloudsConstants.LIST_IMAGES.equals(operation)) {
listImages(exchange);
} else if (JcloudsConstants.LIST_HARDWARE.equals(operation)) {
listHardware(exchange);
} else if (JcloudsConstants.RUN_SCRIPT.equals(operation)) {
runScriptOnNode(exchange);
} else if (JcloudsConstants.CREATE_NODE.equals(operation)) {
createNode(exchange);
} else if (JcloudsConstants.DESTROY_NODE.equals(operation)) {
destroyNode(exchange);
}
}
/**
* Create a node with the specified group.
*
* @param exchange
* @throws CamelException
*/
protected void createNode(Exchange exchange) throws CamelException {
String group = getGroup(exchange);
String imageId = getImageId(exchange);
String locationId = getLocationId(exchange);
String hardwareId = getHardwareId(exchange);
if (group == null) {
throw new CamelException("Group must be specific in the URI or as exchange property for the destroy node operation.");
}
TemplateBuilder builder = computeService.templateBuilder();
builder.any();
if (locationId != null) {
builder.locationId(locationId);
}
if (imageId != null) {
builder.imageId(imageId);
}
if (hardwareId != null) {
builder.hardwareId(hardwareId);
}
try {
Set<? extends NodeMetadata> nodeMetadatas = computeService.createNodesInGroup(group, 1, builder.build());
exchange.getOut().setBody(nodeMetadatas);
exchange.getOut().setHeaders(exchange.getIn().getHeaders());
} catch (RunNodesException e) {
throw new CamelException("Error creating jclouds node.", e);
}
}
/**
* Runs a script on the target node.
*
* @param exchange
* @throws CamelException
*/
@SuppressWarnings("deprecation")
protected void runScriptOnNode(Exchange exchange) throws CamelException {
String script = exchange.getIn().getBody(String.class);
String nodeId = getNodeId(exchange);
String user = getUser(exchange);
LoginCredentials credentials = null;
if (user != null) {
credentials = LoginCredentials.builder().user(user).build();
}
ExecResponse execResponse = null;
if (credentials == null) {
execResponse = computeService.runScriptOnNode(nodeId, script);
} else {
execResponse = computeService.runScriptOnNode(nodeId, script, RunScriptOptions.Builder.overrideLoginCredentials(credentials).runAsRoot(false));
}
if (execResponse == null) {
throw new CamelException("Failed to receive response for run script operation.");
}
exchange.setProperty(JcloudsConstants.RUN_SCRIPT_ERROR, execResponse.getError());
exchange.setProperty(JcloudsConstants.RUN_SCRIPT_EXIT_CODE, execResponse.getExitCode());
exchange.getOut().setBody(execResponse.getOutput());
}
/**
* Destroys the node with the specified nodeId.
*
* @param exchange
* @throws CamelException
*/
protected void destroyNode(Exchange exchange) throws CamelException {
Predicate<NodeMetadata> predicate = getNodePredicate(exchange);
computeService.destroyNodesMatching(predicate);
}
/**
* Sets the metadata of the available nodes to the out message.
*
* @param exchange
* @throws CamelException
*/
protected void listNodes(Exchange exchange) throws CamelException {
Predicate<ComputeMetadata> predicate = getComputePredicate(exchange);
Set<? extends ComputeMetadata> computeMetadatas = computeService.listNodesDetailsMatching(predicate);
exchange.getOut().setBody(computeMetadatas);
}
/**
* Sets the available images to the out message.
*
* @param exchange
* @throws CamelException
*/
protected void listImages(Exchange exchange) throws CamelException {
Set<? extends Image> images = computeService.listImages();
exchange.getOut().setBody(images);
}
/**
* Sets the available hardware profiles to the out message.
*
* @param exchange
* @throws CamelException
*/
protected void listHardware(Exchange exchange) throws CamelException {
Set<? extends Hardware> hardwareProfiles = computeService.listHardwareProfiles();
exchange.getOut().setBody(hardwareProfiles);
}
/**
* Returns the required {@ComputeMetadata} {@link Predicate} for the Exhcnage.
* The predicate can be used for filtering.
*
* @param exchange
* @return
*/
public Predicate<ComputeMetadata> getComputePredicate(final Exchange exchange) {
final String nodeId = getNodeId(exchange);
Predicate<ComputeMetadata> predicate = new Predicate<ComputeMetadata>() {
public boolean apply(ComputeMetadata metadata) {
if (nodeId != null && !nodeId.equals(metadata.getId())) {
return false;
}
//If NodeMetadata also delegate to Node predicate.
if (metadata instanceof NodeMetadataImpl) {
Predicate<NodeMetadata> nodeMetadataPredicate = getNodePredicate(exchange);
if (!nodeMetadataPredicate.apply((NodeMetadataImpl) metadata)) {
return false;
}
}
return true;
}
};
return predicate;
}
/**
* Returns the required {@ComputeMetadata} {@link Predicate} for the Exhcnage.
* The predicate can be used for filtering.
*
* @param exchange
* @return
*/
public Predicate<NodeMetadata> getNodePredicate(Exchange exchange) {
final String nodeId = getNodeId(exchange);
final String imageId = getImageId(exchange);
final String group = getGroup(exchange);
final NodeState queryState = getNodeState(exchange);
Predicate<NodeMetadata> predicate = new Predicate<NodeMetadata>() {
public boolean apply(NodeMetadata metadata) {
if (nodeId != null && !nodeId.equals(metadata.getId())) {
return false;
}
if (imageId != null && !imageId.equals(metadata.getImageId())) {
return false;
}
if (queryState != null && !queryState.equals(metadata.getState())) {
return false;
}
if (group != null && !group.equals(metadata.getGroup())) {
return false;
}
return true;
}
};
return predicate;
}
/**
* Retrieves the operation from the URI or from the exchange headers. The header will take precedence over the URI.
*
* @param exchange
* @return
*/
public String getOperation(Exchange exchange) {
String operation = getEndpoint().getOperation();
if (exchange.getIn().getHeader(JcloudsConstants.OPERATION) != null) {
operation = (String) exchange.getIn().getHeader(JcloudsConstants.OPERATION);
}
return operation;
}
/**
* Retrieves the node state from the URI or from the exchange headers. The header will take precedence over the URI.
*
* @param exchange
* @return
*/
public NodeState getNodeState(Exchange exchange) {
NodeState nodeState = null;
String state = getEndpoint().getNodeState();
if (state != null) {
nodeState = NodeState.valueOf(state);
}
if (exchange.getIn().getHeader(JcloudsConstants.NODE_STATE) != null) {
Object stateHeader = exchange.getIn().getHeader(JcloudsConstants.NODE_STATE);
if (stateHeader == null) {
nodeState = null;
} else if (stateHeader instanceof NodeState) {
nodeState = (NodeState) stateHeader;
} else {
nodeState = NodeState.valueOf(String.valueOf(stateHeader));
}
}
return nodeState;
}
/**
* Retrieves the image id from the URI or from the exchange properties. The property will take precedence over the URI.
*
* @param exchange
* @return
*/
protected String getImageId(Exchange exchange) {
String imageId = getEndpoint().getImageId();
if (exchange.getIn().getHeader(JcloudsConstants.IMAGE_ID) != null) {
imageId = (String) exchange.getIn().getHeader(JcloudsConstants.IMAGE_ID);
}
return imageId;
}
/**
* Retrieves the hardware id from the URI or from the exchange headers. The header will take precedence over the URI.
*
* @param exchange
* @return
*/
protected String getHardwareId(Exchange exchange) {
String hardwareId = getEndpoint().getHardwareId();
if (exchange.getIn().getHeader(JcloudsConstants.HARDWARE_ID) != null) {
hardwareId = (String) exchange.getIn().getHeader(JcloudsConstants.HARDWARE_ID);
}
return hardwareId;
}
/**
* Retrieves the location id from the URI or from the exchange headers. The header will take precedence over the URI.
*
* @param exchange
* @return
*/
protected String getLocationId(Exchange exchange) {
String locationId = getEndpoint().getLocationId();
if (exchange.getIn().getHeader(JcloudsConstants.LOCATION_ID) != null) {
locationId = (String) exchange.getIn().getHeader(JcloudsConstants.LOCATION_ID);
}
return locationId;
}
/**
* Retrieves the node id from the URI or from the exchange headers. The header will take precedence over the URI.
*
* @param exchange
* @return
*/
protected String getNodeId(Exchange exchange) {
String nodeId = getEndpoint().getNodeId();
if (exchange.getIn().getHeader(JcloudsConstants.NODE_ID) != null) {
nodeId = (String) exchange.getIn().getHeader(JcloudsConstants.NODE_ID);
}
return nodeId;
}
/**
* Retrieves the group from the URI or from the exchange headers. The header will take precedence over the URI.
*
* @param exchange
* @return
*/
protected String getGroup(Exchange exchange) {
String group = getEndpoint().getGroup();
if (exchange.getIn().getHeader(JcloudsConstants.GROUP) != null) {
group = (String) exchange.getIn().getHeader(JcloudsConstants.GROUP);
}
return group;
}
/**
* Retrieves the user from the URI or from the exchange headers. The header will take precedence over the URI.
*
* @param exchange
* @return
*/
protected String getUser(Exchange exchange) {
String user = getEndpoint().getUser();
if (exchange.getIn().getHeader(JcloudsConstants.USER) != null) {
user = (String) exchange.getIn().getHeader(JcloudsConstants.USER);
}
return user;
}
}