blob: 1b075f9aecd198e497c8ef08c686daa2dd68645c [file] [log] [blame]
/*
* 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.jclouds.examples.minecraft;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Iterables.contains;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.jclouds.ContextBuilder;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.apis.Apis;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.events.StatementOnNodeCompletion;
import org.jclouds.compute.events.StatementOnNodeFailure;
import org.jclouds.compute.events.StatementOnNodeSubmission;
import org.jclouds.enterprise.config.EnterpriseConfigurationModule;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.Providers;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.Subscribe;
import com.google.common.net.HostAndPort;
import com.google.inject.Module;
/**
* Demonstrates control of Minecraft.
* <p/>
* Usage is:
* {@code java MainApp provider identity credential groupName (add|list|tail|pids|destroy)}
*/
public class MainApp {
public static final Map<String, ApiMetadata> allApis = Maps.uniqueIndex(
Apis.viewableAs(ComputeServiceContext.class), Apis.idFunction());
public static final Map<String, ProviderMetadata> appProviders = Maps.uniqueIndex(
Providers.viewableAs(ComputeServiceContext.class), Providers.idFunction());
public static final Set<String> allKeys = ImmutableSet.copyOf(Iterables.concat(appProviders.keySet(),
allApis.keySet()));
public static enum Action {
ADD, LIST, TAIL, PIDS, DESTROY;
}
public static int PARAMETERS = 5;
public static String INVALID_SYNTAX = "Invalid number of parameters. Syntax is: provider identity credential groupName (add|list|tail|pids|destroy)";
public static void main(String[] args) {
if (args.length < PARAMETERS)
throw new IllegalArgumentException(INVALID_SYNTAX);
String provider = args[0];
String identity = args[1];
String credential = args[2];
String groupName = args[3];
Action action = Action.valueOf(args[4].toUpperCase());
// note that you can check if a provider is present ahead of time
checkArgument(contains(allKeys, provider), "provider %s not in supported list: %s", provider, allKeys);
MinecraftController controller = initController(provider, identity, credential, groupName);
System.out.printf(">> initialized controller %s%n", controller);
try {
switch (action) {
case ADD:
System.out.printf(">> adding a server to group %s%n", groupName);
HostAndPort server = controller.add();
System.out.printf("<< server %s%n", server);
break;
case LIST:
System.out.printf(">> listing servers in group %s%n", groupName);
Iterable<HostAndPort> servers = controller.list();
System.out.printf("<< servers %s%n", servers);
break;
case TAIL:
System.out.printf(">> tailing all servers in group %s%n", groupName);
Map<HostAndPort, String> output = controller.tail();
System.out.printf("<< output %s%n", output);
break;
case PIDS:
System.out.printf(">> getting pids of all servers in group %s%n", groupName);
Map<HostAndPort, String> pids = controller.pids();
System.out.printf("<< pids %s%n", pids);
break;
case DESTROY:
System.out.printf(">> destroying group %s%n", groupName);
Iterable<HostAndPort> destroyed = controller.destroy();
System.out.printf("<< destroyed servers %s%n", destroyed);
break;
}
} catch (RuntimeException e) {
error = 1;
e.printStackTrace();
} finally {
controller.close();
System.exit(error);
}
}
static int error = 0;
private static MinecraftController initController(String provider, String identity, String credential, String group) {
Properties properties = new Properties();
properties.setProperty("minecraft.port", "25565");
properties.setProperty("minecraft.group", group);
properties.setProperty("minecraft.ms", "1024");
properties.setProperty("minecraft.mx", "1024");
properties.setProperty("minecraft.url",
"https://s3.amazonaws.com/MinecraftDownload/launcher/minecraft_server.jar");
if ("aws-ec2".equals(provider)) {
// since minecraft download is in s3 on us-east, lowest latency is from
// there
properties.setProperty(PROPERTY_REGIONS, "us-east-1");
properties.setProperty("jclouds.ec2.ami-query", "owner-id=137112412989;state=available;image-type=machine");
properties.setProperty("jclouds.ec2.cc-ami-query", "");
}
// example of injecting a ssh implementation
Iterable<Module> modules = ImmutableSet.<Module> of(
new SshjSshClientModule(),
new SLF4JLoggingModule(),
new EnterpriseConfigurationModule(),
// This is extended stuff you might inject!!
new ConfigureMinecraftDaemon());
ContextBuilder builder = ContextBuilder.newBuilder(provider)
.credentials(identity, credential)
.modules(modules)
.overrides(properties);
System.out.printf(">> initializing %s%n", builder.getApiMetadata());
ComputeServiceContext context = builder.buildView(ComputeServiceContext.class);
context.utils().eventBus().register(ScriptLogger.INSTANCE);
return context.utils().injector().getInstance(MinecraftController.class);
}
static enum ScriptLogger {
INSTANCE;
Logger logger = LoggerFactory.getLogger(MainApp.class);
@Subscribe
@AllowConcurrentEvents
public void onStart(StatementOnNodeSubmission event) {
logger.info(">> running {} on node({})", event.getStatement(), event.getNode().getId());
if (logger.isDebugEnabled()) {
logger.debug(">> script for {} on node({})\n{}", new Object[] { event.getStatement(), event.getNode().getId(),
event.getStatement().render(OsFamily.UNIX) });
}
}
@Subscribe
@AllowConcurrentEvents
public void onFailure(StatementOnNodeFailure event) {
logger.error("<< error running {} on node({}): {}", new Object[] { event.getStatement(), event.getNode().getId(),
event.getCause().getMessage() }, event.getCause());
}
@Subscribe
@AllowConcurrentEvents
public void onSuccess(StatementOnNodeCompletion event) {
ExecResponse arg0 = event.getResponse();
if (arg0.getExitStatus() != 0) {
logger.error("<< error running {} on node({}): {}", new Object[] { event.getStatement(), event.getNode().getId(),
arg0 });
} else {
logger.info("<< success executing {} on node({}): {}", new Object[] { event.getStatement(),
event.getNode().getId(), arg0 });
}
}
}
}