mirror of https://github.com/apache/jclouds.git
base implemenation of nodepool
This commit is contained in:
parent
94edcbf00d
commit
e4abeecc4d
|
@ -0,0 +1,93 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<artifactId>jclouds-project</artifactId>
|
||||||
|
<groupId>org.jclouds</groupId>
|
||||||
|
<version>1.5.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../../project/pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<groupId>org.jclouds.labs</groupId>
|
||||||
|
<artifactId>nodepool</artifactId>
|
||||||
|
<name>jclouds nodepool</name>
|
||||||
|
<packaging>bundle</packaging>
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<jsch.version>0.1.46</jsch.version>
|
||||||
|
<test.aws-ec2.identity>${test.aws.identity}</test.aws-ec2.identity>
|
||||||
|
<test.aws-ec2.credential>${test.aws.credential}</test.aws-ec2.credential>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds</groupId>
|
||||||
|
<artifactId>jclouds-compute</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds</groupId>
|
||||||
|
<artifactId>jclouds-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds</groupId>
|
||||||
|
<artifactId>jclouds-compute</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds.provider</groupId>
|
||||||
|
<artifactId>aws-ec2</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds.driver</groupId>
|
||||||
|
<artifactId>jclouds-enterprise</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds.driver</groupId>
|
||||||
|
<artifactId>jclouds-sshj</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds</groupId>
|
||||||
|
<artifactId>jclouds-scriptbuilder</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds.driver</groupId>
|
||||||
|
<artifactId>jclouds-jsch</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.jcraft</groupId>
|
||||||
|
<artifactId>jsch</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<instructions>
|
||||||
|
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
|
||||||
|
<Export-Package>org.jclouds.nodepool*;version="${project.version}"</Export-Package>
|
||||||
|
<Import-Package>org.jclouds*;version="${project.version}",*</Import-Package>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds 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.nodepool;
|
||||||
|
|
||||||
|
import org.jclouds.compute.ComputeService;
|
||||||
|
import org.jclouds.compute.RunNodesException;
|
||||||
|
|
||||||
|
public interface PooledComputeService extends ComputeService {
|
||||||
|
|
||||||
|
void startPool() throws RunNodesException;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,265 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds 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.nodepool.internal;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.compute.ComputeService;
|
||||||
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
|
import org.jclouds.compute.RunNodesException;
|
||||||
|
import org.jclouds.compute.RunScriptOnNodesException;
|
||||||
|
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.NodeMetadataBuilder;
|
||||||
|
import org.jclouds.compute.domain.Template;
|
||||||
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
|
import org.jclouds.compute.options.RunScriptOptions;
|
||||||
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
|
import org.jclouds.compute.predicates.NodePredicates;
|
||||||
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.nodepool.PooledComputeService;
|
||||||
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
public class BasePooledComputeService implements PooledComputeService {
|
||||||
|
|
||||||
|
private final ComputeService backingComputeService;
|
||||||
|
private final String backingGroup;
|
||||||
|
private final Template backingTemplate;
|
||||||
|
private final int minPoolSize;
|
||||||
|
private Map<NodeMetadata, String> groupMapping;
|
||||||
|
|
||||||
|
public BasePooledComputeService(ComputeService backingComputeService, String backingGroup, Template backingTemplate, int minPoolSize) {
|
||||||
|
this.backingComputeService = backingComputeService;
|
||||||
|
this.backingGroup = backingGroup;
|
||||||
|
this.backingTemplate = backingTemplate;
|
||||||
|
this.minPoolSize = minPoolSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startPool() throws RunNodesException {
|
||||||
|
Set<? extends NodeMetadata> backingNodes =
|
||||||
|
backingComputeService.createNodesInGroup(backingGroup, minPoolSize, backingTemplate);
|
||||||
|
groupMapping = Maps.newHashMap();
|
||||||
|
for (NodeMetadata node : backingNodes) {
|
||||||
|
groupMapping.put(node, "unassigned");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComputeServiceContext getContext() {
|
||||||
|
return backingComputeService.getContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TemplateBuilder templateBuilder() {
|
||||||
|
return backingComputeService.templateBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TemplateOptions templateOptions() {
|
||||||
|
return backingComputeService.templateOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<? extends Hardware> listHardwareProfiles() {
|
||||||
|
return ImmutableSet.<Hardware>of(backingTemplate.getHardware());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<? extends Image> listImages() {
|
||||||
|
return ImmutableSet.<Image>of(backingTemplate.getImage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<? extends ComputeMetadata> listNodes() {
|
||||||
|
Set<NodeMetadata> allocatedNodes = Sets.newLinkedHashSet();
|
||||||
|
for (ComputeMetadata node : backingComputeService.listNodes()) {
|
||||||
|
NodeMetadata metadata = backingComputeService.getNodeMetadata(node.getId());
|
||||||
|
String group = groupMapping.get(node);
|
||||||
|
if ("unassigned".equals(group))
|
||||||
|
continue;
|
||||||
|
NodeMetadata nodeWithUpdatedGroup =
|
||||||
|
NodeMetadataBuilder.fromNodeMetadata(metadata).group(group).build();
|
||||||
|
allocatedNodes.add(nodeWithUpdatedGroup);
|
||||||
|
}
|
||||||
|
return allocatedNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<? extends Location> listAssignableLocations() {
|
||||||
|
return ImmutableSet.<Location>of(backingTemplate.getLocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<? extends NodeMetadata> createNodesInGroup(String group,
|
||||||
|
int count, Template template) throws RunNodesException {
|
||||||
|
throw new RuntimeException("not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<? extends NodeMetadata> createNodesInGroup(String group,
|
||||||
|
int count, TemplateOptions templateOptions)
|
||||||
|
throws RunNodesException {
|
||||||
|
throw new RuntimeException("not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<? extends NodeMetadata> createNodesInGroup(String group,
|
||||||
|
int count) throws RunNodesException {
|
||||||
|
int allocatedCount = 0;
|
||||||
|
Set<NodeMetadata> allocatedNodes = Sets.newLinkedHashSet();
|
||||||
|
for (NodeMetadata metadata : groupMapping.keySet()) {
|
||||||
|
if (groupMapping.get(metadata).equals("unassigned")) {
|
||||||
|
groupMapping.put(metadata, "group");
|
||||||
|
NodeMetadata nodeWithUpdatedGroup =
|
||||||
|
NodeMetadataBuilder.fromNodeMetadata(metadata).group(group).build();
|
||||||
|
allocatedNodes.add(nodeWithUpdatedGroup);
|
||||||
|
allocatedCount += 1;
|
||||||
|
if (allocatedCount == count) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allocatedNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resumeNode(String id) {
|
||||||
|
backingComputeService.resumeNode(id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resumeNodesMatching(Predicate<NodeMetadata> filter) {
|
||||||
|
backingComputeService.resumeNodesMatching(filter);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void suspendNode(String id) {
|
||||||
|
backingComputeService.suspendNode(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void suspendNodesMatching(Predicate<NodeMetadata> filter) {
|
||||||
|
backingComputeService.suspendNodesMatching(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyNode(String id) {
|
||||||
|
|
||||||
|
backingComputeService.destroyNode(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<? extends NodeMetadata> destroyNodesMatching(
|
||||||
|
Predicate<NodeMetadata> filter) {
|
||||||
|
return backingComputeService.destroyNodesMatching(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void rebootNode(String id) {
|
||||||
|
backingComputeService.rebootNode(id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void rebootNodesMatching(Predicate<NodeMetadata> filter) {
|
||||||
|
backingComputeService.rebootNodesMatching(filter);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeMetadata getNodeMetadata(String id) {
|
||||||
|
return backingComputeService.getNodeMetadata(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<? extends NodeMetadata> listNodesDetailsMatching(
|
||||||
|
Predicate<ComputeMetadata> filter) {
|
||||||
|
return backingComputeService.listNodesDetailsMatching(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(
|
||||||
|
Predicate<NodeMetadata> filter, String runScript)
|
||||||
|
throws RunScriptOnNodesException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return backingComputeService.runScriptOnNodesMatching(filter, runScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(
|
||||||
|
Predicate<NodeMetadata> filter, Statement runScript)
|
||||||
|
throws RunScriptOnNodesException {
|
||||||
|
return backingComputeService.runScriptOnNodesMatching(filter, runScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(
|
||||||
|
Predicate<NodeMetadata> filter, String runScript,
|
||||||
|
RunScriptOptions options) throws RunScriptOnNodesException {
|
||||||
|
return backingComputeService.runScriptOnNodesMatching(filter, runScript, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(
|
||||||
|
Predicate<NodeMetadata> filter, Statement runScript,
|
||||||
|
RunScriptOptions options) throws RunScriptOnNodesException {
|
||||||
|
return backingComputeService.runScriptOnNodesMatching(filter, runScript, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExecResponse runScriptOnNode(String id, Statement runScript,
|
||||||
|
RunScriptOptions options) {
|
||||||
|
return backingComputeService.runScriptOnNode(id, runScript, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<ExecResponse> submitScriptOnNode(String id,
|
||||||
|
Statement runScript, RunScriptOptions options) {
|
||||||
|
return backingComputeService.submitScriptOnNode(id, runScript, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExecResponse runScriptOnNode(String id, Statement runScript) {
|
||||||
|
return backingComputeService.runScriptOnNode(id, runScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExecResponse runScriptOnNode(String id, String runScript,
|
||||||
|
RunScriptOptions options) {
|
||||||
|
return backingComputeService.runScriptOnNode(id, runScript, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExecResponse runScriptOnNode(String id, String runScript) {
|
||||||
|
return backingComputeService.runScriptOnNode(id, runScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,284 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds 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.nodepool;
|
||||||
|
|
||||||
|
import static com.google.common.base.Throwables.propagate;
|
||||||
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.newStatementList;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.compute.ComputeService;
|
||||||
|
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||||
|
import org.jclouds.compute.RunNodesException;
|
||||||
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeState;
|
||||||
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
|
import org.jclouds.compute.domain.Template;
|
||||||
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
|
import org.jclouds.enterprise.config.EnterpriseConfigurationModule;
|
||||||
|
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
|
||||||
|
import org.jclouds.nodepool.internal.BasePooledComputeService;
|
||||||
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
|
import org.jclouds.scriptbuilder.domain.Statements;
|
||||||
|
import org.jclouds.scriptbuilder.statements.java.InstallJDK;
|
||||||
|
import org.jclouds.scriptbuilder.statements.login.AdminAccess;
|
||||||
|
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit test for simple App.
|
||||||
|
*/
|
||||||
|
public class AppTest extends TestCase {
|
||||||
|
private String identity;
|
||||||
|
private String credential;
|
||||||
|
private String providerName;
|
||||||
|
private File privateKey;
|
||||||
|
private File publicKey;
|
||||||
|
private String endPointUrl;
|
||||||
|
public String profile;
|
||||||
|
private int retentionTime;
|
||||||
|
public int instanceCap;
|
||||||
|
|
||||||
|
private String imageId;
|
||||||
|
private String osFamily;
|
||||||
|
private String osVersion;
|
||||||
|
private String hardwareId;
|
||||||
|
private int ram;
|
||||||
|
private int cores;
|
||||||
|
private String initScript;
|
||||||
|
private String name;
|
||||||
|
private boolean stopOnTerminate;
|
||||||
|
private ComputeService compute;
|
||||||
|
private PooledComputeService pooledCompute;
|
||||||
|
private Collection<NodeMetadata> nodes = new LinkedList<NodeMetadata>();
|
||||||
|
private static Logger LOGGER = Logger.getLogger("AppTest");
|
||||||
|
|
||||||
|
private long time;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
// setup JCloudsCloud
|
||||||
|
identity = "insert-your-identity-here";
|
||||||
|
credential = "insert-your-credential-here";
|
||||||
|
providerName = "aws-ec2";
|
||||||
|
privateKey = new File("private-key");
|
||||||
|
publicKey = new File("public-key");
|
||||||
|
endPointUrl = "";
|
||||||
|
profile = "aws-slave-profile";
|
||||||
|
retentionTime = -1;
|
||||||
|
instanceCap = 3;
|
||||||
|
|
||||||
|
// cloud instance template
|
||||||
|
name = "aws-jenkins-slave";
|
||||||
|
// numExecutors = 1;
|
||||||
|
// description = ""
|
||||||
|
imageId = "us-east-1/ami-4dad7424";
|
||||||
|
osFamily = "";
|
||||||
|
osVersion = "";
|
||||||
|
hardwareId = "t1.micro";
|
||||||
|
ram = -1;
|
||||||
|
cores = -1;
|
||||||
|
// labels = "whii";
|
||||||
|
initScript = "touch /tmp/hellothere";
|
||||||
|
stopOnTerminate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rigourous Test :-)
|
||||||
|
*/
|
||||||
|
public void testApp() {
|
||||||
|
createCompute();
|
||||||
|
assertNotNull(compute);
|
||||||
|
createAndStartPool();
|
||||||
|
assertNotNull(pooledCompute);
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
startCounter();
|
||||||
|
provision("pool-1");
|
||||||
|
stopCounter();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
startCounter();
|
||||||
|
provision("pool-2");
|
||||||
|
stopCounter();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
startCounter();
|
||||||
|
provision("pool-3");
|
||||||
|
stopCounter();
|
||||||
|
}
|
||||||
|
assertEquals(9, getRunningNodesCount());
|
||||||
|
for (NodeMetadata slave : nodes) {
|
||||||
|
assertNotNull(slave);
|
||||||
|
LOGGER.info(slave.getId() + "-" + slave.getGroup());
|
||||||
|
terminate(slave);
|
||||||
|
}
|
||||||
|
assertEquals(0, getRunningNodesCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopCounter() {
|
||||||
|
LOGGER.info("Elapsed time: " + (System.currentTimeMillis() - time));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startCounter() {
|
||||||
|
time = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppTest getCloud() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComputeService getCompute() {
|
||||||
|
return pooledCompute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeMetadata provision(String groupName) {
|
||||||
|
LOGGER.info("Provisioning new node");
|
||||||
|
NodeMetadata nodeMetadata = createNodeWithJdk(groupName);
|
||||||
|
nodes.add(nodeMetadata);
|
||||||
|
return nodeMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRunningNodesCount() {
|
||||||
|
int nodeCount = 0;
|
||||||
|
|
||||||
|
for (ComputeMetadata cm : pooledCompute.listNodes()) {
|
||||||
|
if (NodeMetadata.class.isInstance(cm)) {
|
||||||
|
String nodeGroup = ((NodeMetadata) cm).getGroup();
|
||||||
|
|
||||||
|
if (!((NodeMetadata) cm).getState().equals(NodeState.SUSPENDED)
|
||||||
|
&& !((NodeMetadata) cm).getState().equals(NodeState.TERMINATED)) {
|
||||||
|
nodeCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createCompute() {
|
||||||
|
Properties overrides = new Properties();
|
||||||
|
if (!Strings.isNullOrEmpty(this.endPointUrl)) {
|
||||||
|
overrides.setProperty(Constants.PROPERTY_ENDPOINT, this.endPointUrl);
|
||||||
|
}
|
||||||
|
Iterable<Module> modules = ImmutableSet.<Module> of(new SshjSshClientModule(), new SLF4JLoggingModule(),
|
||||||
|
new EnterpriseConfigurationModule());
|
||||||
|
this.compute = new ComputeServiceContextFactory().createContext(this.providerName, this.identity,
|
||||||
|
this.credential, modules, overrides).getComputeService();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAndStartPool() {
|
||||||
|
LOGGER.info("creating jclouds nodepool");
|
||||||
|
ImmutableMap<String, String> userMetadata = ImmutableMap.of("Name", name);
|
||||||
|
TemplateBuilder templateBuilder = compute.templateBuilder();
|
||||||
|
if (!Strings.isNullOrEmpty(imageId)) {
|
||||||
|
LOGGER.info("Setting image id to " + imageId);
|
||||||
|
templateBuilder.imageId(imageId);
|
||||||
|
} else {
|
||||||
|
if (!Strings.isNullOrEmpty(osFamily)) {
|
||||||
|
LOGGER.info("Setting osFamily to " + osFamily);
|
||||||
|
templateBuilder.osFamily(OsFamily.valueOf(osFamily));
|
||||||
|
}
|
||||||
|
if (!Strings.isNullOrEmpty(osVersion)) {
|
||||||
|
LOGGER.info("Setting osVersion to " + osVersion);
|
||||||
|
templateBuilder.osVersionMatches(osVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!Strings.isNullOrEmpty((hardwareId))) {
|
||||||
|
LOGGER.info("Setting hardware Id to " + hardwareId);
|
||||||
|
} else {
|
||||||
|
LOGGER.info("Setting minRam " + ram + " and minCores " + cores);
|
||||||
|
templateBuilder.minCores(cores).minRam(ram);
|
||||||
|
}
|
||||||
|
|
||||||
|
Template template = templateBuilder.build();
|
||||||
|
|
||||||
|
// setup the jcloudTemplate to customize the nodeMetadata with jdk, etc.
|
||||||
|
// also opening ports
|
||||||
|
AdminAccess adminAccess = AdminAccess.builder().adminUsername("jenkins").installAdminPrivateKey(false) // no
|
||||||
|
// need
|
||||||
|
.grantSudoToAdminUser(false) // no need
|
||||||
|
.adminPrivateKey(getCloud().privateKey) // temporary due to jclouds
|
||||||
|
// bug
|
||||||
|
.authorizeAdminPublicKey(true).adminPublicKey(getCloud().publicKey).build();
|
||||||
|
|
||||||
|
// Jenkins needs /jenkins dir.
|
||||||
|
Statement jenkinsDirStatement = Statements.newStatementList(Statements.exec("mkdir /jenkins"),
|
||||||
|
Statements.exec("chown jenkins /jenkins"));
|
||||||
|
|
||||||
|
Statement bootstrap = newStatementList(adminAccess, jenkinsDirStatement, Statements.exec(this.initScript),
|
||||||
|
InstallJDK.fromOpenJDK());
|
||||||
|
|
||||||
|
template.getOptions().inboundPorts(22).userMetadata(userMetadata).runScript(bootstrap);
|
||||||
|
|
||||||
|
pooledCompute = new BasePooledComputeService(compute, "jenkins-pool", template, 10);
|
||||||
|
|
||||||
|
try {
|
||||||
|
pooledCompute.startPool();
|
||||||
|
} catch (RunNodesException e) {
|
||||||
|
destroyBadNodesAndPropagate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodeMetadata createNodeWithJdk(String groupName) {
|
||||||
|
LOGGER.info("creating jclouds node");
|
||||||
|
|
||||||
|
NodeMetadata nodeMetadata = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
nodeMetadata = getOnlyElement(pooledCompute.createNodesInGroup(groupName, 1));
|
||||||
|
} catch (RunNodesException e) {
|
||||||
|
throw destroyBadNodesAndPropagate(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if nodeMetadata is null and throw
|
||||||
|
return nodeMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RuntimeException destroyBadNodesAndPropagate(RunNodesException e) {
|
||||||
|
for (Map.Entry<? extends NodeMetadata, ? extends Throwable> nodeError : e.getNodeErrors().entrySet())
|
||||||
|
getCloud().getCompute().destroyNode(nodeError.getKey().getId());
|
||||||
|
throw propagate(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void terminate(NodeMetadata nodeMetaData) {
|
||||||
|
if (stopOnTerminate) {
|
||||||
|
LOGGER.info("Suspending the Slave : " + nodeMetaData.getName());
|
||||||
|
final ComputeService compute = getCloud().getCompute();
|
||||||
|
compute.suspendNode(nodeMetaData.getId());
|
||||||
|
} else {
|
||||||
|
LOGGER.info("Terminating the Slave : " + nodeMetaData.getName());
|
||||||
|
final ComputeService compute = getCloud().getCompute();
|
||||||
|
compute.destroyNode(nodeMetaData.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue