/** * 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.CamelExchangeException; import org.apache.camel.Exchange; import org.apache.camel.util.ObjectHelper; 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.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 CamelExchangeException("Operation must be specified in the endpoint URI or as a property on the exchange.", 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); } else if (JcloudsConstants.REBOOT_NODE.equals(operation)) { rebootNode(exchange); } else if (JcloudsConstants.SUSPEND_NODE.equals(operation)) { suspendNode(exchange); } else if (JcloudsConstants.RESUME_NODE.equals(operation)) { resumeNode(exchange); } } /** * Create a node with the specified group. */ protected void createNode(Exchange exchange) throws CamelException { String group = getGroup(exchange); String imageId = getImageId(exchange); String locationId = getLocationId(exchange); String hardwareId = getHardwareId(exchange); if (ObjectHelper.isEmpty(group)) { throw new CamelExchangeException("Group must be specific in the URI or as exchange property for the destroy node operation.", exchange); } TemplateBuilder builder = computeService.templateBuilder(); builder.any(); if (ObjectHelper.isNotEmpty(locationId)) { builder.locationId(locationId); } if (ObjectHelper.isNotEmpty(imageId)) { builder.imageId(imageId); } if (ObjectHelper.isNotEmpty(hardwareId)) { 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 CamelExchangeException("Error creating jclouds node.", exchange, e); } } /** * Runs a script on the target node. */ 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 (ObjectHelper.isNotEmpty(user)) { 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 CamelExchangeException("Failed to receive response for run script operation on node: " + nodeId + " using script: " + script, exchange); } exchange.setProperty(JcloudsConstants.RUN_SCRIPT_ERROR, execResponse.getError()); exchange.setProperty(JcloudsConstants.RUN_SCRIPT_EXIT_CODE, execResponse.getExitStatus()); exchange.getOut().setBody(execResponse.getOutput()); } /** * Destroys the node with the specified nodeId. */ protected void destroyNode(Exchange exchange) { Predicate<NodeMetadata> predicate = getNodePredicate(exchange); computeService.destroyNodesMatching(predicate); } /** * Sets the metadata of the available nodes to the out message. */ protected void listNodes(Exchange exchange) { Predicate<ComputeMetadata> predicate = getComputePredicate(exchange); Set<? extends ComputeMetadata> computeMetadatas = computeService.listNodesDetailsMatching(predicate); exchange.getOut().setBody(computeMetadatas); } /** * Sets the available images to the out message. */ protected void listImages(Exchange exchange) { Set<? extends Image> images = computeService.listImages(); exchange.getOut().setBody(images); } /** * Sets the available hardware profiles to the out message. */ protected void listHardware(Exchange exchange) { Set<? extends Hardware> hardwareProfiles = computeService.listHardwareProfiles(); exchange.getOut().setBody(hardwareProfiles); } /** * Reboot the node with the specified nodeId. */ protected void rebootNode(Exchange exchange) { Predicate<NodeMetadata> predicate = getNodePredicate(exchange); computeService.rebootNodesMatching(predicate); } /** * Suspend the node with the specified nodeId. */ protected void suspendNode(Exchange exchange) { Predicate<NodeMetadata> predicate = getNodePredicate(exchange); computeService.suspendNodesMatching(predicate); } /** * Suspend the node with the specified nodeId. */ protected void resumeNode(Exchange exchange) { Predicate<NodeMetadata> predicate = getNodePredicate(exchange); computeService.resumeNodesMatching(predicate); } /** * Returns the required {@ComputeMetadata} {@link Predicate} for the Exhcnage. * The predicate can be used for filtering. */ 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. */ public Predicate<NodeMetadata> getNodePredicate(Exchange exchange) { final String nodeId = getNodeId(exchange); final String imageId = getImageId(exchange); final String group = getGroup(exchange); final NodeMetadata.Status 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.getStatus())) { 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. */ public String getOperation(Exchange exchange) { String operation = getEndpoint().getOperation(); if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(JcloudsConstants.OPERATION))) { operation = exchange.getIn().getHeader(JcloudsConstants.OPERATION, String.class); } return operation; } /** * Retrieves the node state from the URI or from the exchange headers. The header will take precedence over the URI. */ public NodeMetadata.Status getNodeState(Exchange exchange) { NodeMetadata.Status nodeState = null; String state = getEndpoint().getNodeState(); if (ObjectHelper.isNotEmpty(state)) { nodeState = NodeMetadata.Status.valueOf(state); } if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(JcloudsConstants.NODE_STATE))) { Object stateHeader = exchange.getIn().getHeader(JcloudsConstants.NODE_STATE); if (stateHeader == null) { nodeState = null; } else if (stateHeader instanceof NodeMetadata.Status) { nodeState = (NodeMetadata.Status) stateHeader; } else { nodeState = NodeMetadata.Status.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. */ protected String getImageId(Exchange exchange) { String imageId = getEndpoint().getImageId(); if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(JcloudsConstants.IMAGE_ID))) { imageId = exchange.getIn().getHeader(JcloudsConstants.IMAGE_ID, String.class); } return imageId; } /** * Retrieves the hardware id from the URI or from the exchange headers. The header will take precedence over the URI. */ protected String getHardwareId(Exchange exchange) { String hardwareId = getEndpoint().getHardwareId(); if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(JcloudsConstants.HARDWARE_ID))) { hardwareId = exchange.getIn().getHeader(JcloudsConstants.HARDWARE_ID, String.class); } return hardwareId; } /** * Retrieves the location id from the URI or from the exchange headers. The header will take precedence over the URI. */ protected String getLocationId(Exchange exchange) { String locationId = getEndpoint().getLocationId(); if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(JcloudsConstants.LOCATION_ID))) { locationId = exchange.getIn().getHeader(JcloudsConstants.LOCATION_ID, String.class); } return locationId; } /** * Retrieves the node id from the URI or from the exchange headers. The header will take precedence over the URI. */ protected String getNodeId(Exchange exchange) { String nodeId = getEndpoint().getNodeId(); if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(JcloudsConstants.NODE_ID))) { nodeId = exchange.getIn().getHeader(JcloudsConstants.NODE_ID, String.class); } return nodeId; } /** * Retrieves the group from the URI or from the exchange headers. The header will take precedence over the URI. */ protected String getGroup(Exchange exchange) { String group = getEndpoint().getGroup(); if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(JcloudsConstants.GROUP))) { group = exchange.getIn().getHeader(JcloudsConstants.GROUP, String.class); } return group; } /** * Retrieves the user from the URI or from the exchange headers. The header will take precedence over the URI. */ protected String getUser(Exchange exchange) { String user = getEndpoint().getUser(); if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(JcloudsConstants.USER))) { user = exchange.getIn().getHeader(JcloudsConstants.USER, String.class); } return user; } }