| /** |
| * 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.whirr; |
| |
| import static org.apache.whirr.service.ClusterActionHandler.BOOTSTRAP_ACTION; |
| import static org.apache.whirr.service.ClusterActionHandler.CONFIGURE_ACTION; |
| import static org.apache.whirr.service.ClusterActionHandler.DESTROY_ACTION; |
| |
| import java.io.IOException; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.whirr.Cluster.Instance; |
| import org.apache.whirr.actions.ByonClusterAction; |
| import org.apache.whirr.service.ClusterActionHandler; |
| import org.apache.whirr.state.ClusterStateStoreFactory; |
| import org.jclouds.compute.ComputeService; |
| import org.jclouds.compute.ComputeServiceContext; |
| import org.jclouds.compute.RunScriptOnNodesException; |
| import org.jclouds.compute.domain.ExecResponse; |
| import org.jclouds.compute.domain.NodeMetadata; |
| import org.jclouds.compute.options.RunScriptOptions; |
| import org.jclouds.scriptbuilder.domain.Statement; |
| |
| import com.google.common.base.Function; |
| import com.google.common.base.Predicate; |
| import com.google.common.base.Predicates; |
| import com.google.common.cache.LoadingCache; |
| import com.google.common.collect.Collections2; |
| |
| /** |
| * Equivalent of {@link ClusterController}, but for execution in BYON mode |
| * ("bring your own nodes"). |
| */ |
| public class ByonClusterController extends ClusterController { |
| |
| public ByonClusterController() { |
| super(); |
| } |
| |
| public ByonClusterController(Function<ClusterSpec, ComputeServiceContext> getCompute, ClusterStateStoreFactory stateStoreFactory) { |
| super(getCompute, stateStoreFactory); |
| } |
| |
| @Override |
| public String getName() { |
| return "byon"; |
| } |
| |
| /** |
| * Destroys a whirr BYON cluster. |
| * Because this is a BYON cluster it also stops the services. |
| */ |
| @Override |
| public void destroyCluster(ClusterSpec clusterSpec) throws IOException, |
| InterruptedException { |
| stopServices(clusterSpec); // for BYON only |
| LoadingCache<String, ClusterActionHandler> handlerMap = handlerMapFactory |
| .create(); |
| ClusterAction destroyer = new ByonClusterAction(DESTROY_ACTION, |
| getCompute(), handlerMap); |
| destroyer.execute(clusterSpec, null); |
| } |
| |
| /** |
| * Provisions the hardware for a BYON cluster. |
| */ |
| @Override |
| public Cluster bootstrapCluster(ClusterSpec clusterSpec) throws IOException, |
| InterruptedException { |
| LoadingCache<String, ClusterActionHandler> handlerMap = handlerMapFactory |
| .create(); |
| ClusterAction bootstrapper = new ByonClusterAction(BOOTSTRAP_ACTION, |
| getCompute(), handlerMap); |
| Cluster cluster = bootstrapper.execute(clusterSpec, null); |
| getClusterStateStore(clusterSpec).save(cluster); |
| return cluster; |
| } |
| |
| /** |
| * Configures cluster services for a BYON cluster. |
| */ |
| @Override |
| public Cluster configureServices(ClusterSpec clusterSpec, Cluster cluster, |
| Set<String> targetRoles, Set<String> targetInstanceIds) |
| throws IOException, InterruptedException { |
| LoadingCache<String, ClusterActionHandler> handlerMap = handlerMapFactory |
| .create(); |
| ClusterAction configurer = new ByonClusterAction(CONFIGURE_ACTION, |
| getCompute(), handlerMap); |
| cluster = configurer.execute(clusterSpec, cluster); |
| getClusterStateStore(clusterSpec).save(cluster); |
| return cluster; |
| } |
| |
| public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(final ClusterSpec spec, |
| Predicate<NodeMetadata> condition, final Statement statement) throws IOException, RunScriptOnNodesException { |
| |
| ComputeServiceContext computeServiceContext = getCompute().apply(spec); |
| ComputeService computeService = computeServiceContext.getComputeService(); |
| Cluster cluster = getClusterStateStore(spec).load(); |
| |
| RunScriptOptions options = RunScriptOptions.Builder.runAsRoot(false).wrapInInitScript(false); |
| return computeService.runScriptOnNodesMatching(Predicates.<NodeMetadata>and(condition, runningIn(cluster)), statement, options); |
| } |
| |
| private Predicate<NodeMetadata> runningIn(Cluster cluster) { |
| final Set<String> instanceIds = new HashSet<String>(Collections2.transform(cluster.getInstances(), new Function<Instance, String>() { |
| @Override |
| public String apply(Instance instance) { |
| return instance.getId(); |
| } |
| })); |
| return new Predicate<NodeMetadata>() { |
| @Override |
| public boolean apply(final NodeMetadata nodeMetadata) { |
| return instanceIds.contains(nodeMetadata.getId()) && nodeMetadata.getStatus().equals(NodeMetadata.Status.RUNNING); |
| } |
| }; |
| } |
| |
| @Override |
| public void destroyInstance(ClusterSpec clusterSpec, String instanceId) |
| throws IOException { |
| // TODO |
| } |
| |
| @Override |
| public Set<? extends NodeMetadata> getNodes(ClusterSpec clusterSpec) |
| throws IOException, InterruptedException { |
| ComputeServiceContext computeServiceContext = getCompute().apply(clusterSpec); |
| ComputeService computeService = computeServiceContext.getComputeService(); |
| return computeService.listNodesDetailsMatching(Predicates.in(computeService.listNodes())); |
| } |
| } |